mirror of https://github.com/secdev/scapy.git
Allow filters in the Packet slice / .getlayer() API
With a packet `pkt = IP() / IP(ttl=3) / IP()`, this will allow: - pkt.getlayer(IP, ttl=3) - pkt[IP, {"ttl": 3}] This is particularly useful with Dot11Elt() layers, when you want a specific value (the SSID or supported rates for example).
This commit is contained in:
parent
6e173e9f6e
commit
8ac38c611c
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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%")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = ""
|
||||
|
|
Loading…
Reference in New Issue