% Regression tests for Scapy regarding fields ############ ############ + Tests on basic fields #= Field class #~ core field #Field("foo", None, fmt="H").i2m(None,0xabcdef) #assert _ == b"\xcd\xef" #Field("foo", None, fmt="' assert rf.i2repr_one(None, RandNum(0, 10)) == '' assert lf.i2repr_one(None, RandNum(0, 10)) == '' assert fcb.i2repr_one(None, RandNum(0, 10)) == '' True = EnumField.i2repr ~ field enumfield assert f.i2repr(None, 0) == 'Foo' assert f.i2repr(None, 1) == 'Bar' assert f.i2repr(None, 2) == '2' assert f.i2repr(None, [0, 1]) == ['Foo', 'Bar'] assert rf.i2repr(None, 0) == 'Foo' assert rf.i2repr(None, 1) == 'Bar' assert rf.i2repr(None, 2) == '2' assert rf.i2repr(None, [0, 1]) == ['Foo', 'Bar'] assert lf.i2repr(None, 0) == 'Foo' assert lf.i2repr(None, 1) == 'Bar' assert lf.i2repr(None, 2) == '2' assert lf.i2repr(None, [0, 1]) == ['Foo', 'Bar'] assert fcb.i2repr(None, 0) == 'Foo' assert fcb.i2repr(None, 1) == 'Bar' assert fcb.i2repr(None, 5) == 'Bar' assert fcb.i2repr(None, 11) == repr(11) assert fcb.i2repr(None, [0, 1, 5, 11]) == ['Foo', 'Bar', 'Bar', repr(11)] conf.noenum.add(f, rf, lf, fcb) assert f.i2repr(None, 0) == repr(0) assert f.i2repr(None, 1) == repr(1) assert f.i2repr(None, 2) == repr(2) assert f.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)] assert rf.i2repr(None, 0) == repr(0) assert rf.i2repr(None, 1) == repr(1) assert rf.i2repr(None, 2) == repr(2) assert rf.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)] assert lf.i2repr(None, 0) == repr(0) assert lf.i2repr(None, 1) == repr(1) assert lf.i2repr(None, 2) == repr(2) assert lf.i2repr(None, [0, 1, 2]) == [repr(0), repr(1), repr(2)] assert fcb.i2repr(None, 0) == repr(0) assert fcb.i2repr(None, 1) == repr(1) assert fcb.i2repr(None, 5) == repr(5) assert fcb.i2repr(None, 11) == repr(11) assert fcb.i2repr(None, [0, 1, 5, 11]) == [repr(0), repr(1), repr(5), repr(11)] conf.noenum.remove(f, rf, lf, fcb) assert f.i2repr_one(None, RandNum(0, 10)) == '' assert rf.i2repr_one(None, RandNum(0, 10)) == '' assert lf.i2repr_one(None, RandNum(0, 10)) == '' assert fcb.i2repr_one(None, RandNum(0, 10)) == '' True = EnumField with Enum from enum import Enum class JUICE(Enum): APPLE = 0 ORANGE = 1 PINEAPPLE = 2 class Breakfast(Packet): fields_desc = [EnumField("juice", 1, JUICE, fmt="H")] assert raw(Breakfast(juice="ORANGE")) == b"\x00\x01" = LE3BytesEnumField ~ field le3bytesenumfield f = LE3BytesEnumField('test', 0, {0: 'Foo', 1: 'Bar'}) = LE3BytesEnumField.i2repr_one ~ field le3bytesenumfield assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 2) == '2' = XLE3BytesEnumField assert XLE3BytesEnumField("a", 0, {0: "test"}).i2repr_one(None, 0) == "test" assert XLE3BytesEnumField("a", 0, {0: "test"}).i2repr_one(None, 1) == "0x1" ############ ############ + CharEnumField tests = Building expect_exception handler ~ field charenumfield def expect_exception(e, c): try: eval(c) assert False except e: assert True = CharEnumField tests initialization ~ field charenumfield fc = CharEnumField('test', 'f', {'f': 'Foo', 'b': 'Bar'}) fcb = CharEnumField('test', 'a', ( lambda x: 'Foo' if x == 'a' else 'Bar' if x == 'b' else 'Baz', lambda x: 'a' if x == 'Foo' else 'b' if x == 'Bar' else '' )) True = CharEnumField.any2i_one ~ field charenumfield assert fc.any2i_one(None, 'Foo') == 'f' assert fc.any2i_one(None, 'Bar') == 'b' expect_exception(KeyError, 'fc.any2i_one(None, "Baz")') assert fcb.any2i_one(None, 'Foo') == 'a' assert fcb.any2i_one(None, 'Bar') == 'b' assert fcb.any2i_one(None, 'Baz') == '' True ############ ############ + XByteEnumField tests = Building expect_exception handler ~ field xbyteenumfield def expect_exception(e, c): try: eval(c) assert False except e: assert True = XByteEnumField tests initialization ~ field xbyteenumfield f = XByteEnumField('test', 0, {0: 'Foo', 1: 'Bar'}) fcb = XByteEnumField('test', 0, ( lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x), lambda x: x )) True = XByteEnumField.i2repr_one ~ field xbyteenumfield assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 0xff) == '0xff' True = XByteEnumField update tests initialization ~ field xbyteenumfield enum = ObservableDict({0: 'Foo', 1: 'Bar'}) f = XByteEnumField('test', 0, enum) fcb = XByteEnumField('test', 0, ( lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x), lambda x: x )) True = XByteEnumField.i2repr_one with update ~ field xbyteenumfield assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 2) == '0x2' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 2) == '0x2' assert f.i2repr_one(None, 0xff) == '0xff' del enum[1] enum[2] = 'Baz' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == '0x1' assert f.i2repr_one(None, 2) == 'Baz' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == '0x1' assert f.i2repr_one(None, 2) == 'Baz' assert f.i2repr_one(None, 0xff) == '0xff' True ############ ############ + XShortEnumField tests = Building expect_exception handler ~ field xshortenumfield def expect_exception(e, c): try: eval(c) assert False except e: assert True = XShortEnumField tests initialization ~ field xshortenumfield f = XShortEnumField('test', 0, {0: 'Foo', 1: 'Bar'}) fcb = XShortEnumField('test', 0, ( lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x), lambda x: x )) True = XShortEnumField.i2repr_one ~ field xshortenumfield assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 0xff) == '0xff' True = XShortEnumField update tests initialization ~ field xshortenumfield enum = ObservableDict({0: 'Foo', 1: 'Bar'}) f = XShortEnumField('test', 0, enum) fcb = XShortEnumField('test', 0, ( lambda x: 'Foo' if x == 0 else 'Bar' if x == 1 else lhex(x), lambda x: x )) True = XShortEnumField.i2repr_one with update ~ field xshortenumfield assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 2) == '0x2' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == 'Bar' assert f.i2repr_one(None, 2) == '0x2' assert f.i2repr_one(None, 0xff) == '0xff' del enum[1] enum[2] = 'Baz' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == '0x1' assert f.i2repr_one(None, 2) == 'Baz' assert f.i2repr_one(None, 0xff) == '0xff' assert f.i2repr_one(None, 0) == 'Foo' assert f.i2repr_one(None, 1) == '0x1' assert f.i2repr_one(None, 2) == 'Baz' assert f.i2repr_one(None, 0xff) == '0xff' True ############ ############ + DNSStrField tests = Raise exception - test data dnsf = DNSStrField("test", "") assert dnsf.getfield(None, b"\x01x\x00") == (b"", b"x.") try: dnsf.getfield(None, b"\xc0\xff") assert False except (Scapy_Exception, IndexError): pass + YesNoByteField = default usage yn_bf = YesNoByteField('test', 0x00) assert yn_bf.i2repr(None, 0x00) == 'no' assert yn_bf.i2repr(None, 0x01) == 'yes' assert yn_bf.i2repr(None, 0x02) == 'yes' assert yn_bf.i2repr(None, 0xff) == 'yes' = inverted yes - no (scalar config) yn_bf = YesNoByteField('test', 0x00, config={'yes': 0x00, 'no': 0x01}) assert yn_bf.i2repr(None, 0x00) == 'yes' assert yn_bf.i2repr(None, 0x01) == 'no' assert yn_bf.i2repr(None, 0x02) == 2 assert yn_bf.i2repr(None, 0xff) == 255 = inverted yes - no (range config) yn_bf = YesNoByteField('test', 0x00, config={'yes': 0x00, 'no': (0x01, 0xff)}) assert yn_bf.i2repr(None, 0x00) == 'yes' assert yn_bf.i2repr(None, 0x01) == 'no' assert yn_bf.i2repr(None, 0x02) == 'no' assert yn_bf.i2repr(None, 0xff) == 'no' = yes - no (using sets) yn_bf = YesNoByteField('test', 0x00, config={'yes': [0x00, 0x02], 'no': [0x01, 0x04, 0xff]}) assert yn_bf.i2repr(None, 0x00) == 'yes' assert yn_bf.i2repr(None, 0x01) == 'no' assert yn_bf.i2repr(None, 0x02) == 'yes' assert yn_bf.i2repr(None, 0x03) == 3 assert yn_bf.i2repr(None, 0x04) == 'no' assert yn_bf.i2repr(None, 0x05) == 5 assert yn_bf.i2repr(None, 0xff) == 'no' = yes, no and invalid yn_bf = YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': 0x01, 'invalid': (0x02, 0xff)}) assert yn_bf.i2repr(None, 0x00) == 'no' assert yn_bf.i2repr(None, 0x01) == 'yes' assert yn_bf.i2repr(None, 0x02) == 'invalid' assert yn_bf.i2repr(None, 0xff) == 'invalid' = invalid scalar spec try: YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': 256}) assert False except FieldValueRangeException: pass = invalid range spec - invalid length try: YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x00, 0x02, 0x02)}) assert False except FieldAttributeException: pass = invalid range spec - invalid value try: YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x100, 0x01)}) assert False except FieldValueRangeException: pass try: YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': (0x00, 0x100)}) assert False except FieldValueRangeException: pass = invalid set spec - invalid value try: YesNoByteField('test', 0x00, config={'no': 0x00, 'yes': [0x01, 0x101]}) assert False except FieldValueRangeException: pass = FlasgField - Python incompatible name assert Dot11().FCfield.to_DS is False ######## ######## + MultipleTypeField ~ mtf = Test initialization order class DebugPacket(Packet): fields_desc = [ ByteEnumField("atyp", 0x1, {0x1: "IPv4", 0x3: "DNS", 0x4: "IPv6"}), MultipleTypeField( [ # IPv4 (IPField("addr", "0.0.0.0"), lambda pkt: pkt.atyp == 0x1), # DNS (DNSStrField("addr", ""), lambda pkt: pkt.atyp == 0x3), # IPv6 (IP6Field("addr", "::"), lambda pkt: pkt.atyp == 0x4), ], StrField("addr", "") ), ] = Default order a = DebugPacket(atyp=0x3, addr="scapy.net") a = DebugPacket(raw(a)) assert a.addr == b"scapy.net." = Reversed order 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 o = SweetPacket(switch=1, subfield=0x88) assert o.subfield == 0x88 = MultipleTypeField - syntax error import warnings with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") class MTFPacket(Packet): fields_desc = [ByteField("a", 0), MultipleTypeField([ (ByteField("b", 0), lambda pkt: pkt.a == 0), (ShortField("not_b", 0), lambda: pkt.a != 0), ], IntField("b", 0))] assert len(w) == 1 assert issubclass(w[-1].category, SyntaxWarning) ######## ######## + FlagsField = Test Flags Field Iterator class FlagsTest(Packet): fields_desc = [FlagsField("flags", 0, 8, ["f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"])] = Test upper nibble a = FlagsTest(b"\xf0") flags = list(a.flags) assert len(flags) == 4 assert "f4" in flags assert "f5" in flags assert "f6" in flags assert "f7" in flags = Test lower nibble a = FlagsTest(b"\x0f") flags = list(a.flags) assert len(flags) == 4 assert "f3" in flags assert "f2" in flags assert "f1" in flags assert "f0" in flags = Test single flag 1 a = FlagsTest(b"\x01") flags = list(a.flags) assert len(flags) == 1 assert "f0" in flags = Test single flag 2 a = FlagsTest(b"\x02") flags = list(a.flags) assert len(flags) == 1 assert "f1" in flags = Test single flag 0x80 a = FlagsTest(b"\x80") flags = list(a.flags) assert len(flags) == 1 assert "f7" in flags = Test pattern 0x55 a = FlagsTest(b"\x55") flags = list(a.flags) assert len(flags) == 4 assert "f6" in flags assert "f2" in flags assert "f4" in flags assert "f0" in flags = Test pattern 0xAA a = FlagsTest(b"\xAA") flags = list(a.flags) assert len(flags) == 4 assert "f7" in flags assert "f3" in flags assert "f5" in flags assert "f1" in flags = Test pattern 0x00 a = FlagsTest(b"\x00") flags = list(a.flags) assert len(flags) == 0 = Test pattern 0xFF a = FlagsTest(b"\xFF") flags = list(a.flags) assert len(flags) == 8 assert "f7" in flags assert "f3" in flags assert "f5" in flags assert "f1" in flags assert "f6" in flags assert "f2" in flags assert "f4" in flags assert "f0" in flags = FlagsField with str class TCPTest(Packet): fields_desc = [ BitField("reserved", 0, 7), FlagsField("flags", 0x2, 9, "FSRPAUECN") ] a = TCPTest(flags=3) assert a.flags.F assert a.flags.S assert a.sprintf("%flags%") == "FS" = FlagsField with dict class FlagsTest2(Packet): fields_desc = [ FlagsField("flags", 0x2, 16, { 0x0001: "A", 0x0008: "B", 0x1000: "C", }) ] a = FlagsTest2(flags=9) a.sprintf("%flags%") assert a.flags.A assert a.flags.B assert a.sprintf("%flags%") == "A+B" b = FlagsTest2(flags="B+C") assert b.flags == 0x1000 | 0x0008 = Conditional FlagsField command class CondFlagsTest(Packet): fields_desc = [ ByteField("b", 0), ConditionalField(FlagsField("f", 0, 8, ""), lambda p: p.b == 0) ] p = CondFlagsTest(b"\x00\x0f") assert p == eval(p.command()) ######## ######## + ScalingField = ScalingField Test default behaviour class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0) ] x = DebugPacket() assert len(x) == 1 assert x.data == 0 x.data = 1 assert x.data == 1 = ScalingField Test string assignment class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1) ] x = DebugPacket() x.data = '\x01' assert x.data == 0.1 x.data = 2.0 assert x.data == 2.0 assert bytes(x) == b"\x14" x.data = b'\xff' assert x.data == 25.5 x.data = '\x7f' assert x.data == 12.7 = ScalingField Test scaling class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1) ] x = DebugPacket() x.data = b'\x01' assert x.data == 0.1 x.data = 2.0 assert x.data == 2.0 assert bytes(x) == b"\x14" x.data = b'\xff' assert x.data == 25.5 = ScalingField Test scaling signed class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, fmt="b") ] x = DebugPacket() x.data = b'\x01' assert x.data == 0.1 x.data = 12.7 assert x.data == 12.7 assert bytes(x) == b"\x7f" x.data = b'\x80' assert x.data == -12.8 x.data = -0.1 assert x.data == -0.1 assert bytes(x) == b"\xff" = ScalingField Test scaling signed offset class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-1, fmt="b") ] x = DebugPacket() x.data = b'\x01' assert x.data == -0.9 x.data = 11.7 assert x.data == 11.7 assert bytes(x) == b"\x7f" x.data = b'\x80' assert x.data == -13.8 x.data = -1.1 assert x.data == -1.1 assert bytes(x) == b"\xff" = ScalingField Test scaling offset class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-1) ] x = DebugPacket() x.data = b'\x01' assert x.data == -0.9 x.data = 11.7 assert x.data == 11.7 assert bytes(x) == b"\x7f" x.data = b'\x80' assert x.data == 11.8 x.data = 24.5 assert x.data == 24.5 assert bytes(x) == b"\xff" = ScalingField Test unit class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, unit="V") ] x = DebugPacket() x.data = b'\x01' assert x.data == 1 assert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '1 V' = ScalingField Test unit and ndigits class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.123456, unit="V", ndigits=1) ] x = DebugPacket() x.data = b'\x01' assert x.data == 0.1 assert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.1 V' = ScalingField Test unit and ndigits 2 class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.123456, unit="V", ndigits=3) ] x = DebugPacket() x.data = b'\x01' print(x.__repr__()) assert x.data == 0.123 assert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.123 V' = ScalingField Test unit and ndigits 3 class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.123456, unit="V", ndigits=5) ] x = DebugPacket() x.data = b'\x01' print(x.__repr__()) assert x.data == 0.12346 assert ScalingField.i2repr(x.fields_desc[0],x, x.data) == '0.12346 V' = ScalingField randval byte class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-5) ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -5.0 assert r.max == 20.5 = ScalingField randval byte 2 class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=-0.1, offset=-5) ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -30.5 assert r.max == -5 = ScalingField signed randval byte class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=-0.1, offset=-5, fmt="b") ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -17.7 assert r.max == 7.8 = ScalingField signed randval byte 2 class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-5, fmt="b") ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -17.8 assert r.max == 7.7 = ScalingField signed randval short class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-5, fmt="h") ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -3281.8 assert r.max == 3271.7 = ScalingField signed randval int class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-5, fmt="i") ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -214748369.8 assert r.max == 214748359.7 = ScalingField signed randval long class DebugPacket(Packet): fields_desc = [ ScalingField('data', 0, scaling=0.1, offset=-5, fmt="q") ] x = DebugPacket() r = x.fields_desc[0].randval() val = r._fix() assert r.min == -922337203685477585.8 assert r.max == 922337203685477575.7 = ScalingField signed randval long y = fuzz(x) assert bytes(y) != bytes(y) ############ ############ + BitExtendedField = BitExtendedField: simple test class DebugPacket(Packet): fields_desc = [ BitExtendedField("val", None, extension_bit=0) ] a = DebugPacket(val=1234) assert a.val == 1234 = BitExtendedField i2m: corner values * 7 bits of data = 0 import codecs for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.i2m(None, 0) r = int(codecs.encode(r, 'hex'), 16) assert r == 0 * 7 bits of data = 1 for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.i2m(None, 0b1111111) r = int(codecs.encode(r, 'hex'), 16) assert r == 0xff - 2**i = BitExtendedField i2m: field expansion * If there is 8 bits of data, we need to add a byte m = BitExtendedField("foo", None, extension_bit=0) r = m.i2m(None, 0b10000000) r = int(codecs.encode(r, 'hex'), 16) assert r == 0x0300 = BitExtendedField i2m: test all FX bit positions * Data is 0b10000001 (129) and all str values are precomputed data_129 = { "extended": 129, "int_with_fx": [770, 769, 1281, 2305, 4353, 8449, 16641, 33025], "str_with_fx" : [] } for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.i2m(None, data_129["extended"]) data_129["str_with_fx"].append(r) r = int(codecs.encode(r, 'hex'), 16) assert r == data_129["int_with_fx"][i] = BitExtendedField m2i: test all FX bit positions * Data is 0b10000001 (129) and all str values are precomputed for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.m2i(None, data_129["str_with_fx"][i]) assert r == data_129["extended"] = BitExtendedField m2i: stop at FX zero * 1 byte of zeroes (FX stop) then 1 byte of ones : ignore 2nd byte for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.m2i(None, b'\x00\xff') assert r == 0 = BitExtendedField m2i: multiple bytes * 0b00000011 0b11111110 --> 0xff data_254 = { "extended": 0xff, "str_with_fx" : [b'\x03\xfe', b'\x03\xfd', b'\x05\xfb', b'\x09\xf7', b'\x11\xef', b'\x21\xdf', b'\x41\xbf', b'\x81\x7f'] } for i in range(len(data_254['str_with_fx'])): m = BitExtendedField("foo", None, extension_bit=i) r = m.m2i(None, data_254["str_with_fx"][i]) assert r == data_254['extended'] = BitExtendedField m2i: invalid field with no stopping bit * 1 byte of one (no FX stop) shall return an error for i in range(8): m = BitExtendedField("foo", None, extension_bit=i) r = m.m2i(None, b'\xff') assert r == None = LSBExtendedField * Test i2m and m2i data_129 = { "extended": 129, "int_with_fx": 770, "str_with_fx" : None } m = LSBExtendedField("foo", None) r = m.i2m(None, data_129["extended"]) data_129["str_with_fx"] = r r = int(codecs.encode(r, 'hex'), 16) assert r == data_129["int_with_fx"] m = LSBExtendedField("foo", None) r = m.m2i(None, data_129["str_with_fx"]) assert r == data_129["extended"] = MSBExtendedField * Test i2m and m2i data_129 = { "extended": 129, "int_with_fx": 33025, "str_with_fx" : None } m = MSBExtendedField("foo", None) r = m.i2m(None, data_129["extended"]) data_129["str_with_fx"] = r r = int(codecs.encode(r, 'hex'), 16) assert r == data_129["int_with_fx"] m = MSBExtendedField("foo", None) r = m.m2i(None, data_129["str_with_fx"]) assert r == data_129["extended"] ############ ############ + Deprecated fields in Packet ~ deprecated = Field Deprecation test class TestPacket(Packet): fields_desc = [ ByteField("a", 0), LEShortField("b", 15), ] deprecated_fields = { "dpr": ("a", "1.0"), "B": ("b", "1.0"), } try: pkt = TestPacket(a=2, B=3) assert pkt.B == 3 assert pkt.b == 3 assert pkt.a == 2 import warnings with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") assert pkt.dpr == 2 assert len(w) == 1 assert issubclass(w[-1].category, DeprecationWarning) except DeprecationWarning: # -Werror is used pass ############ ############ + FCSField = FCSField: basic test class TestPacket(Packet): fields_desc = [ ByteField("a", 0), LEShortField("b", 15), LEIntField("c", 7), FCSField("fcs", None), IntField("bottom", 0) ] bind_layers(TestPacket, Ether) pkt = TestPacket(a=12, fcs=0xbeef, bottom=123)/Ether(src="aa:aa:aa:aa:aa:aa", dst="bb:bb:bb:bb:bb:bb")/IP(src="127.0.0.1", dst="127.0.0.1") assert raw(pkt) == b'\x0c\x0f\x00\x07\x00\x00\x00\x00\x00\x00{\xbb\xbb\xbb\xbb\xbb\xbb\xaa\xaa\xaa\xaa\xaa\xaa\x08\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01\xbe\xef' # Test that it is consistent assert raw(pkt) == b'\x0c\x0f\x00\x07\x00\x00\x00\x00\x00\x00{\xbb\xbb\xbb\xbb\xbb\xbb\xaa\xaa\xaa\xaa\xaa\xaa\x08\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01\xbe\xef' pkt = TestPacket(raw(pkt)) assert pkt.fcs == 0xbeef = FCSField: multiple class TestPacket2(Packet): fields_desc = [ ByteField("a", 0), LEShortField("b", 15), FCSField("fcs1", None), LEIntField("c", 7), FCSField("fcs2", None), IntField("bottom", 0), ] bind_layers(TestPacket2, Ether) pkt = TestPacket2(a=12, fcs1=0xbeef, fcs2=0xfeed, bottom=123)/Ether(src="aa:aa:aa:aa:aa:aa", dst="bb:bb:bb:bb:bb:bb")/IP(src="127.0.0.1", dst="127.0.0.1") assert raw(pkt) == b'\x0c\x0f\x00\x07\x00\x00\x00\x00\x00\x00{\xbb\xbb\xbb\xbb\xbb\xbb\xaa\xaa\xaa\xaa\xaa\xaa\x08\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01\xfe\xed\xbe\xef' assert raw(pkt) == b'\x0c\x0f\x00\x07\x00\x00\x00\x00\x00\x00{\xbb\xbb\xbb\xbb\xbb\xbb\xaa\xaa\xaa\xaa\xaa\xaa\x08\x00E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01\xfe\xed\xbe\xef' pkt = TestPacket2(raw(pkt)) assert pkt.fcs1 == 0xbeef assert pkt.fcs2 == 0xfeed assert pkt.bottom == 123 assert pkt.a == 12 ############ ############ + PacketField = PacketField: randval() class DebugPacket(Packet): fields_desc = [ ShortField('short', 0), ByteField('byte', 0), LongField('long', 0) ] p = PacketField('packet', b'', DebugPacket).randval() assert isinstance(p.short, RandShort) assert isinstance(p.byte, RandByte) assert isinstance(p.long, RandLong) = PacketField: randval(), PacketField in PacketField class DebugPacket(Packet): fields_desc = [ ShortField('short1', 0), ByteField('byte', 0), LongField('long', 0) ] class DummyPacket(Packet): fields_desc = [ PacketField('packet', b'', DebugPacket), ShortField('short2', 0) ] p = PacketField('packet', b'', DummyPacket).randval() assert isinstance(p.packet.short1, RandShort) assert isinstance(p.packet.byte, RandByte) assert isinstance(p.packet.long, RandLong) assert isinstance(p.short2, RandShort) = Test parent reference in guess_payload_class class TestGuessInner(Packet): name="test guess inner" fields_desc=[ ByteField("foo", 0) ] def guess_payload_class(self, payload): self.parentflag = True if self.parent is None: # all exceptions are caught, so have to use flag self.parentflag = False return super(TestGuessInner, self).guess_payload_class(payload) class TestGuess(Packet): name="test guess" fields_desc=[ PacketField("pf", None, TestGuessInner) ] x=TestGuess(pf=TestGuessInner()/Raw(b'123')) p=TestGuess(raw(x)) assert p[TestGuessInner].parentflag assert p[TestGuessInner].parent == p ############ ############ + XStr(*)Field tests = i2repr ~ field xstrfield from collections import namedtuple MockPacket = namedtuple('MockPacket', ['type']) mp = MockPacket(0) f = XStrField('test', None) x = f.i2repr(mp, RandBin()) assert x == '' ############ ############ + Raw() tests = unaligned data p = Raw(b"abc") p offsetdata = bytes.fromhex("0" + p.load.hex() + "0") p = Raw((offsetdata, 4)) p ############ ############ + PacketListField() tests = unaligned data class PInner(Packet): name = "PInner" fields_desc = [ BitField("x", 0, 8), ] def extract_padding(self, s): return '', s class POuter(Packet): name = "POuter" fields_desc = [ BitField("indent", 0, 4), BitFieldLenField("pcount", None, 8, count_of="plist"), PacketListField("plist", None, PInner, count_from=lambda pkt: pkt.pcount), ] p = POuter(b"\xf0\x44\x14\x24\x34\x40") p assert p.indent == 0xf assert p.pcount == 4 assert [p.x for p in p.plist] == [0x41, 0x42, 0x43, 0x44]