diff --git a/scapy/fields.py b/scapy/fields.py index e97e485cd011dc7ff4bc323350d2787d6cb5fd23..fc41b7600b4000df9cc31d0c6abd1ab4ee3aa2e4 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -1139,26 +1139,40 @@ class FlagsField(BitField): """ ismutable = True __slots__ = ["multi", "names"] + def __init__(self, name, default, size, names): self.multi = isinstance(names, list) self.names = names BitField.__init__(self, name, default, size) - def any2i(self, pkt, x): + + def _fixup_val(self, x): + """Returns a FlagValue instance when needed. Internal method, to be +used in *2i() and i2*() methods. + + """ if isinstance(x, (list, tuple)): - return type(x)(None if v is None else FlagValue(v, self.names) - for v in x) - return None if x is None else FlagValue(x, self.names) + return type(x)( + v if v is None or isinstance(v, FlagValue) + else FlagValue(v, self.names) + for v in x + ) + return x if x is None or isinstance(x, FlagValue) else FlagValue(x, self.names) + + def any2i(self, pkt, x): + return self._fixup_val(super(FlagsField, self).any2i(pkt, x)) + def m2i(self, pkt, x): - if isinstance(x, (list, tuple)): - return type(x)(None if v is None else FlagValue(v, self.names) - for v in x) - return None if x is None else FlagValue(x, self.names) + return self._fixup_val(super(FlagsField, self).m2i(pkt, x)) + + def i2h(self, pkt, x): + return self._fixup_val(super(FlagsField, self).i2h(pkt, x)) + def i2repr(self, pkt, x): if isinstance(x, (list, tuple)): return repr(type(x)( - None if v is None else str(FlagValue(v, self.names)) - for v in x)) - return None if x is None else str(FlagValue(x, self.names)) + None if v is None else str(self._fixup_val(v)) for v in x + )) + return None if x is None else str(self._fixup_val(x)) MultiFlagsEntry = collections.namedtuple('MultiFlagEntry', ['short', 'long']) diff --git a/scapy/layers/vxlan.py b/scapy/layers/vxlan.py index 1d1d9ae4fb8ccfe253e56618f5dd5b94a3613644..5eb3e2bb372d9d73d5b1db6861210c1cdc9c5743 100644 --- a/scapy/layers/vxlan.py +++ b/scapy/layers/vxlan.py @@ -26,7 +26,7 @@ class VXLAN(Packet): 'V1', 'V2', 'R', 'G']), ConditionalField( ShortField("reserved0", 0), - lambda pkt: pkt.flags & 0x04, + lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( ByteEnumField('NextProtocol', 0, @@ -35,22 +35,22 @@ class VXLAN(Packet): 2: 'IPv6', 3: 'Ethernet', 4: 'NSH'}), - lambda pkt: pkt.flags & 0x04, + lambda pkt: pkt.flags.NextProtocol, ), ConditionalField( - ThreeBytesField("reserved1", 0x000000), - lambda pkt: (not pkt.flags & 0x80) and (not pkt.flags & 0x04), + ThreeBytesField("reserved1", 0), + lambda pkt: (not pkt.flags.G) and (not pkt.flags.NextProtocol), ), ConditionalField( - FlagsField("gpflags", 0x0, 8, _GP_FLAGS), - lambda pkt: pkt.flags & 0x80, + FlagsField("gpflags", 0, 8, _GP_FLAGS), + lambda pkt: pkt.flags.G, ), ConditionalField( ShortField("gpid", 0), - lambda pkt: pkt.flags & 0x80, + lambda pkt: pkt.flags.G, ), X3BytesField("vni", 0), - XByteField("reserved2", 0x00), + XByteField("reserved2", 0), ] # Use default linux implementation port @@ -59,7 +59,7 @@ class VXLAN(Packet): } def mysummary(self): - if self.flags & 0x80: + if self.flags.G: return self.sprintf("VXLAN (vni=%VXLAN.vni% gpid=%VXLAN.gpid%)") else: return self.sprintf("VXLAN (vni=%VXLAN.vni%)") @@ -68,9 +68,11 @@ bind_layers(UDP, VXLAN, dport=4789) # RFC standard vxlan port bind_layers(UDP, VXLAN, dport=4790) # RFC standard vxlan-gpe port bind_layers(UDP, VXLAN, dport=6633) # New IANA assigned port for use with NSH bind_layers(UDP, VXLAN, dport=8472) # Linux implementation port -bind_layers(VXLAN, Ether, {'flags': 0x8}) -bind_layers(VXLAN, Ether, {'flags': 0x88}) -bind_layers(VXLAN, Ether, {'flags': 0xC, 'NextProtocol': 0}, NextProtocol=0) -bind_layers(VXLAN, IP, {'flags': 0xC, 'NextProtocol': 1}, NextProtocol=1) -bind_layers(VXLAN, IPv6, {'flags': 0xC, 'NextProtocol': 2}, NextProtocol=2) -bind_layers(VXLAN, Ether, {'flags': 0xC, 'NextProtocol': 3}, NextProtocol=3) + +bind_layers(VXLAN, Ether) +bind_layers(VXLAN, IP, NextProtocol=1) +bind_layers(VXLAN, IPv6, NextProtocol=2) +bind_layers(VXLAN, Ether, flags=4, NextProtocol=0) +bind_layers(VXLAN, IP, flags=4, NextProtocol=1) +bind_layers(VXLAN, IPv6, flags=4, NextProtocol=2) +bind_layers(VXLAN, Ether, flags=4, NextProtocol=3) diff --git a/test/regression.uts b/test/regression.uts index 1e6dbebc8e9cf10e4a228b30f0aea51bb209dad1..4e445490d660dbc024a578f0fe99b1175bd099d3 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -643,8 +643,8 @@ Dot11WEP(_) assert(TCP in _ and _[TCP].seq == 12345678) = RadioTap Big-Small endian dissection -raw = b'\x00\x00\x1a\x00/H\x00\x00\xe1\xd3\xcb\x05\x00\x00\x00\x00@0x\x14@\x01\xac\x00\x00\x00' -r = RadioTap(raw) +data = b'\x00\x00\x1a\x00/H\x00\x00\xe1\xd3\xcb\x05\x00\x00\x00\x00@0x\x14@\x01\xac\x00\x00\x00' +r = RadioTap(data) r.show() assert r.present == 18479 @@ -7435,7 +7435,8 @@ assert(p.data[0].ifname.startswith("lo")) str(UDP(sport=1024, dport=4789, len=None, chksum=None)/VXLAN(flags=0x08, vni=42)) == b'\x04\x00\x12\xb5\x00\x10\x00\x00\x08\x00\x00\x00\x00\x00\x2a\x00' = Verify VXLAN Ethernet Binding -str(VXLAN(vni=23)/Ether(dst="11:11:11:11:11:11", src="11:11:11:11:11:11", type=0x800)) == b'\x0c\x00\x00\x03\x00\x00\x17\x00\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x08\x00' +pkt = VXLAN(raw(VXLAN(vni=23)/Ether(dst="11:11:11:11:11:11", src="11:11:11:11:11:11", type=0x800))) +pkt.flags.NextProtocol and pkt.NextProtocol == 3 = Verify UDP dport overloading p = Ether(dst="11:11:11:11:11:11", src="22:22:22:22:22:22")