diff --git a/scapy/contrib/bgp.py b/scapy/contrib/bgp.py index a0a5fdadc55a7e1084625a2720eed8a5ae0b9853..48fcace7f43a8b1d78d4841d897119194702874f 100644 --- a/scapy/contrib/bgp.py +++ b/scapy/contrib/bgp.py @@ -619,16 +619,15 @@ class BGPCapability(six.with_metaclass(_BGPCapability_metaclass, Packet)): ret = 1 return ret - def getlayer(self, cls, nb=1, _track=None): - layer = None + def getlayer(self, cls, nb=1, _track=None, **flt): if cls == BGPCapability: for cap_class in _capabilities_registry: - if isinstance(self, _capabilities_registry[cap_class]): - layer = self - break + if isinstance(self, _capabilities_registry[cap_class]) and \ + all(self.getfieldval(fldname) == fldvalue + for fldname, fldvalue in flt.iteritems()): + return self else: - layer = Packet.getlayer(self, cls, nb, _track) - return layer + return Packet.getlayer(self, cls, nb, _track, **flt) def post_build(self, p, pay): length = 0 diff --git a/scapy/layers/eap.py b/scapy/layers/eap.py index b441ff446d83af59506e04710e10a0df29d76689..d86b78a1c5e8053de97fb83faf3ce28cc1ec026d 100644 --- a/scapy/layers/eap.py +++ b/scapy/layers/eap.py @@ -248,16 +248,15 @@ class EAP(Packet): ret = 1 return ret - def getlayer(self, cls, nb=1, _track=None): - layer = None + def getlayer(self, cls, nb=1, _track=None, **flt): if cls == EAP: for eap_class in EAP.registered_methods.values(): - if isinstance(self, eap_class): - layer = self - break + if isinstance(self, eap_class) and \ + all(self.getfieldval(fldname) == fldvalue + for fldname, fldvalue in flt.iteritems()): + return self else: - layer = Packet.getlayer(self, cls, nb, _track) - return layer + return Packet.getlayer(self, cls, nb, _track, **flt) def answers(self, other): if isinstance(other, EAP): diff --git a/scapy/layers/ntp.py b/scapy/layers/ntp.py index 2e75067e27a55278e5c803d85e9a40a0fd6d6e96..a9512d5fc70ace5fd029ca3fead2eab2a7fb06ba 100644 --- a/scapy/layers/ntp.py +++ b/scapy/layers/ntp.py @@ -255,21 +255,20 @@ class NTP(Packet): ret = 1 return ret - def getlayer(self, cls, nb=1, _track=None): + def getlayer(self, cls, nb=1, _track=None, **flt): ntp_classes = [ get_cls("NTPHeader"), get_cls("NTPControl"), get_cls("NTPPrivate") ] - layer = None if cls == NTP: for ntp_class in ntp_classes: - if isinstance(self, ntp_class): - layer = self - break + if isinstance(self, ntp_class) and \ + all(self.getfieldval(fldname) == fldvalue + for fldname, fldvalue in flt.iteritems()): + return self else: - layer = Packet.getlayer(self, cls, nb, _track) - return layer + return Packet.getlayer(self, cls, nb, _track, **flt) def mysummary(self): return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%") diff --git a/scapy/layers/radius.py b/scapy/layers/radius.py index 9b7507fbdbf60776032bcedf235a8de8babf926d..118233c37510d8644acc9760ff42b55bfac8f10a 100644 --- a/scapy/layers/radius.py +++ b/scapy/layers/radius.py @@ -278,17 +278,15 @@ class RadiusAttribute(Packet): return True return False - def getlayer(self, cls, nb=1, _track=None): - layer = None + def getlayer(self, cls, nb=1, _track=None, **flt): if cls == RadiusAttribute: for attr_class in RadiusAttribute.registered_attributes.values(): - if isinstance(self, attr_class): - layer = self - break + if isinstance(self, attr_class) and \ + all(self.getfieldval(fldname) == fldvalue + for fldname, fldvalue in flt.iteritems()): + return self else: - layer = Packet.getlayer(self, cls, nb, _track) - return layer - + return Packet.getlayer(self, cls, nb, _track, **flt) def post_build(self, p, pay): length = self.len diff --git a/scapy/packet.py b/scapy/packet.py index 326f15b1a538bd290fe23eac339f560f72853c32..50fe67a44b069c839761bba0d8f8500d8311a03e 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -888,8 +888,12 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket)): if ret: return ret return self.payload.haslayer(cls) - def getlayer(self, cls, nb=1, _track=None): - """Return the nb^th layer that is an instance of cls.""" + + def getlayer(self, cls, nb=1, _track=None, **flt): + """Return the nb^th layer that is an instance of cls, matching flt +values. + + """ if isinstance(cls, int): nb = cls+1 cls = None @@ -898,13 +902,15 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket)): else: ccls,fld = cls,None if cls is None or self.__class__ == cls or self.__class__.__name__ == ccls: - if nb == 1: - if fld is None: - return self + if all(self.getfieldval(fldname) == fldvalue + for fldname, fldvalue in flt.iteritems()): + if nb == 1: + if fld is None: + return self + else: + return self.getfieldval(fld) else: - return self.getfieldval(fld) - else: - nb -=1 + nb -=1 for f in self.packetfields: fvalue_gen = self.getfieldval(f.name) if fvalue_gen is None: @@ -918,7 +924,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket)): if ret is not None: return ret nb = track[0] - return self.payload.getlayer(cls,nb,_track=_track) + return self.payload.getlayer(cls, nb=nb, _track=_track, **flt) def firstlayer(self): q = self @@ -930,13 +936,11 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket)): if isinstance(cls, slice): lname = cls.start if cls.stop: - ret = self.getlayer(cls.start, cls.stop) + ret = self.getlayer(cls.start, nb=cls.stop, **(cls.step or {})) else: - ret = self.getlayer(cls.start) - if ret is None and cls.step is not None: - ret = cls.step + ret = self.getlayer(cls.start, **(cls.step or {})) else: - lname=cls + lname = cls ret = self.getlayer(cls) if ret is None: if isinstance(lname, Packet_metaclass): @@ -1287,7 +1291,7 @@ class NoPayload(Packet): return isinstance(other, NoPayload) or isinstance(other, conf.padding_layer) def haslayer(self, cls): return 0 - def getlayer(self, cls, nb=1, _track=None): + def getlayer(self, cls, nb=1, _track=None, **flt): if _track is not None: _track.append(nb) return None diff --git a/test/regression.uts b/test/regression.uts index 43e5543a7b89f3448c4f76dd3131ee2a23a7a345..dff21aa8991ae22dd04a211b51426ec66fa09593 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -8645,6 +8645,11 @@ Dot11(type=0, subtype=1).answers(query) == True assert Dot11Elt(info="scapy").summary() == "SSID='scapy'" assert Dot11Elt(ID=1).mysummary() == "" += Multiple Dot11Elt layers +pkt = Dot11() / Dot11Beacon() / Dot11Elt(ID="Rates") / Dot11Elt(ID="SSID", info="Scapy") +assert pkt[Dot11Elt::{"ID": 0}].info == "Scapy" +assert pkt.getlayer(Dot11Elt, ID=0).info == "Scapy" + = Dot11WEP - build ~ crypto conf.wepkey = ""