From fcbd44082acc3307b98aa6e8ff099f6bafe0c06c Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Sun, 21 Apr 2019 11:51:56 +0200 Subject: [PATCH 1/2] Fix MultipleTypeField default values handling --- scapy/fields.py | 59 +++++++++++++++++++++++++++++++------------------ test/fields.uts | 29 ++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 21 deletions(-) diff --git a/scapy/fields.py b/scapy/fields.py index 0c7bddf614c..b1017c8c396 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -275,31 +275,41 @@ def __init__(self, flds, dflt): self.dflt = dflt self.name = self.dflt.name + def _iterate_fields_cond(self, pkt, val, use_val): + """Internal function used by _find_fld_pkt & _find_fld_pkt_val""" + # Iterate through the fields + for fld, cond in self.flds: + if isinstance(cond, tuple): + if use_val: + if cond[1](pkt, val): + return fld + continue + else: + cond = cond[0] + if cond(pkt): + return fld + return self.dflt + def _find_fld_pkt(self, pkt): """Given a Packet instance `pkt`, returns the Field subclass to be used. If you know the value to be set (e.g., in .addfield()), use ._find_fld_pkt_val() instead. """ - for fld, cond in self.flds: - if isinstance(cond, tuple): - cond = cond[0] - if cond(pkt): - return fld - return self.dflt + return self._iterate_fields_cond(pkt, None, False) def _find_fld_pkt_val(self, pkt, val): """Given a Packet instance `pkt` and the value `val` to be set, -returns the Field subclass to be used. +returns the Field subclass to be used, and the updated `val` if necessary. """ - for fld, cond in self.flds: - if isinstance(cond, tuple): - if cond[1](pkt, val): - return fld - elif cond(pkt): - return fld - return self.dflt + fld = self._iterate_fields_cond(pkt, val, True) + # Default ? (in this case, let's make sure it's up-do-date) + dflts_pkt = pkt.default_fields + if val == dflts_pkt[self.name] and self.name not in pkt.fields: + dflts_pkt[self.name] = fld.default + val = fld.default + return fld, val def _find_fld(self): """Returns the Field subclass to be used, depending on the Packet @@ -331,25 +341,32 @@ def getfield(self, pkt, s): return self._find_fld_pkt(pkt).getfield(pkt, s) def addfield(self, pkt, s, val): - return self._find_fld_pkt_val(pkt, val).addfield(pkt, s, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.addfield(pkt, s, val) def any2i(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).any2i(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.any2i(pkt, val) def h2i(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).h2i(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.h2i(pkt, val) def i2h(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).i2h(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.i2h(pkt, val) def i2m(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).i2m(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.i2m(pkt, val) def i2len(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).i2len(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.i2len(pkt, val) def i2repr(self, pkt, val): - return self._find_fld_pkt_val(pkt, val).i2repr(pkt, val) + fld, val = self._find_fld_pkt_val(pkt, val) + return fld.i2repr(pkt, val) def register_owner(self, cls): for fld, _ in self.flds: diff --git a/test/fields.uts b/test/fields.uts index b518c73940a..ae6337abcf0 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -1283,6 +1283,35 @@ a = DebugPacket(addr="scapy.net", atyp=0x3) a = DebugPacket(raw(a)) assert a.addr == b"scapy.net." += Test default values auto-update + +class SweetPacket(Packet): + name = 'Sweet Celestian Packet' + fields_desc = [ + IntField('switch', 0), + MultipleTypeField([ + (XShortField('subfield', 0xDEAD), lambda pkt: pkt.switch == 1), + (XIntField('subfield', 0xBEEFBEEF), lambda pkt: pkt.switch == 2)], + XByteField('subfield', 0x88) + ) + ] + +o = SweetPacket() +assert o.subfield == 0x88 + +o = SweetPacket(switch=1) +assert o.subfield == 0xDEAD + +o = SweetPacket(switch=2) +assert o.subfield == 0xBEEFBEEF + +o = SweetPacket() +assert o.subfield == 0x88 +o.switch = 1 +assert o.subfield == 0xDEAD +o.switch = 2 +assert o.subfield == 0xBEEFBEEF + ######## ######## + FlagsField From c8100a3f2d72931548c9320463fb6e0493e88539 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Mon, 22 Apr 2019 12:17:39 +0200 Subject: [PATCH 2/2] Fix ARP IPv6 routing & remove useless ARPSourceMACField --- doc/scapy/build_dissect.rst | 1 - scapy/arch/windows/__init__.py | 2 ++ scapy/layers/l2.py | 17 +++++++++-------- test/fields.uts | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/doc/scapy/build_dissect.rst b/doc/scapy/build_dissect.rst index 1496edd41b9..20623b21e5b 100644 --- a/doc/scapy/build_dissect.rst +++ b/doc/scapy/build_dissect.rst @@ -1071,7 +1071,6 @@ TCP/IP MACField DestMACField(MACField) SourceMACField(MACField) - ARPSourceMACField(MACField) ICMPTimeStampField diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py index 418d50610f4..2bf5eb2e0a3 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -723,6 +723,8 @@ def reload(self): from scapy.arch.pcapdnet import load_winpcapy load_winpcapy() self.load() + # Reload conf.iface + conf.iface = get_working_if() def show(self, resolve_mac=True, print_result=True): """Print list of available network interfaces in human readable form""" diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py index cdcd9c3b14f..ef884de61b4 100644 --- a/scapy/layers/l2.py +++ b/scapy/layers/l2.py @@ -148,11 +148,6 @@ def i2m(self, pkt, x): return MACField.i2m(self, pkt, self.i2h(pkt, x)) -class ARPSourceMACField(SourceMACField): - def __init__(self, name): - super(ARPSourceMACField, self).__init__(name) - - # Layers ETHER_TYPES['802_AD'] = 0x88a8 @@ -326,7 +321,7 @@ class ARP(Packet): }), MultipleTypeField( [ - (ARPSourceMACField("hwsrc"), + (SourceMACField("hwsrc"), (lambda pkt: pkt.hwtype == 1 and pkt.hwlen == 6, lambda pkt, val: pkt.hwtype == 1 and ( pkt.hwlen == 6 or (pkt.hwlen is None and @@ -400,10 +395,16 @@ def answers(self, other): return self_psrc[:len(other_pdst)] == other_pdst[:len(self_psrc)] def route(self): - dst = self.pdst + fld, dst = self.getfield_and_val("pdst") + fld, dst = fld._find_fld_pkt_val(self, dst) if isinstance(dst, Gen): dst = next(iter(dst)) - return conf.route.route(dst) + if isinstance(fld, IP6Field): + return conf.route6.route(dst) + elif isinstance(fld, IPField): + return conf.route.route(dst) + else: + return None def extract_padding(self, s): return "", s diff --git a/test/fields.uts b/test/fields.uts index ae6337abcf0..9c3cf252ed8 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -37,7 +37,7 @@ r = m.addfield(None, b"FOO", "c0:01:be:ef:ba:be") r assert(r == b"FOO\xc0\x01\xbe\xef\xba\xbe" ) -= SourceMACField, ARPSourceMACField += SourceMACField, SourceMACField conf.route.add(net="1.2.3.4/32", dev=conf.iface) p = Ether() / ARP(pdst="1.2.3.4") assert p.src == p.hwsrc == p[ARP].hwsrc == get_if_hwaddr(conf.iface)