| % 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="<I").i2m(None,0x12cdef) |
| #assert _ == b"\xef\xcd\x12\x00" |
| #Field("foo", None, fmt="B").addfield(None, "FOO", 0x12) |
| #assert _ == b"FOO\x12" |
| #Field("foo", None, fmt="I").getfield(None, b"\x12\x34\x56\x78ABCD") |
| #assert _ == ("ABCD",0x12345678) |
| |
| |
| = ConditionnalField class |
| ~ core field |
| |
| # Test equality with conditional fields |
| |
| class TEST_COND(Packet): |
| fields_desc = [ |
| IntField("A", 0), |
| ConditionalField(IntField("A0",0), lambda pkt:pkt.A == 0), |
| ConditionalField(IntField("A1",0), lambda pkt:pkt.A != 0), |
| IntField("B", 0), |
| ConditionalField(IntField("B0",0), lambda pkt:pkt.B == 0), |
| ConditionalField(IntField("B1",0), lambda pkt:pkt.B != 0), |
| ] |
| |
| print(TEST_COND(TEST_COND().build()).fields) |
| |
| a = TEST_COND() |
| b = TEST_COND(raw(TEST_COND())) |
| assert raw(a) == raw(b) |
| assert a == b |
| |
| # Test ConditionalField dependencies |
| |
| class TEST_COND(Packet): |
| fields_desc = [ |
| ByteField('A', 0), |
| ConditionalField(ByteField('B', 0), |
| lambda pkt:pkt.A != 0), |
| ConditionalField(ByteField('C', 0), |
| lambda pkt:pkt.B == 0), |
| ] |
| |
| assert TEST_COND().build() == b'\x00' |
| |
| # Test MultipleTypeField in ConditionalField |
| |
| class TEST_INNER(Packet): |
| fields_desc = [ |
| ByteField('A', 0), |
| ByteField('B', 0), |
| ConditionalField( |
| MultipleTypeField( |
| [ |
| (ByteField('C', 1), lambda pkt: pkt.B == 1), |
| (ByteField('C', 2), lambda pkt: pkt.B == 2), |
| ], |
| ByteField('C', 0), |
| ), |
| lambda pkt: pkt.A, |
| ) |
| ] |
| |
| pkt = TEST_INNER() |
| pkt.A = 1 |
| pkt.B = 1 |
| assert pkt.C == 1 |
| |
| = Simple tests |
| |
| assert LongField("test", None).addfield(None, b"", 0x44434241) == b'\x00\x00\x00\x00DCBA' |
| assert SignedLongField("test", None).addfield(None, b"", -2) == b'\xff\xff\xff\xff\xff\xff\xff\xfe' |
| |
| assert LELongField("test", None).addfield(None, b"", 0x44434241) == b'ABCD\x00\x00\x00\x00' |
| assert LESignedLongField("test", None).addfield(None, b"", -2) == b'\xfe\xff\xff\xff\xff\xff\xff\xff' |
| |
| = MACField class |
| ~ core field |
| m = MACField("foo", None) |
| r = m.i2m(None, None) |
| r |
| assert r == b"\x00\x00\x00\x00\x00\x00" |
| r = m.getfield(None, b"\xc0\x01\xbe\xef\xba\xbeABCD") |
| r |
| assert r == (b"ABCD","c0:01:be:ef:ba:be") |
| r = m.addfield(None, b"FOO", "c0:01:be:ef:ba:be") |
| r |
| assert r == b"FOO\xc0\x01\xbe\xef\xba\xbe" |
| |
| = LEMACField class |
| ~ core field |
| m = LEMACField("foo", None) |
| r = m.i2m(None, None) |
| r |
| assert r == b"\x00\x00\x00\x00\x00\x00" |
| r = m.getfield(None, b"\xbe\xba\xef\xbe\x01\xc0ABCD") |
| r |
| assert r == (b"ABCD","c0:01:be:ef:ba:be") |
| r = m.addfield(None, b"FOO", "be:ba:ef:be:01:c0") |
| r |
| assert r == b"FOO\xc0\x01\xbe\xef\xba\xbe" |
| |
| = 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) |
| p = Dot3() / LLC() / SNAP() / ARP(pdst="1.2.3.4") |
| assert p.src == p.hwsrc == p[ARP].hwsrc == get_if_hwaddr(conf.iface) |
| conf.route.delt(net="1.2.3.4/32", dev=conf.iface) |
| |
| = IPField class |
| ~ core field |
| |
| i = IPField("foo", None) |
| r = i.i2m(None, "1.2.3.4") |
| r |
| assert r == b"\x01\x02\x03\x04" |
| r = i.i2m(None, "255.255.255.255") |
| r |
| assert r == b"\xff\xff\xff\xff" |
| r = i.m2i(None, b"\x01\x02\x03\x04") |
| r |
| assert r == "1.2.3.4" |
| r = i.getfield(None, b"\x01\x02\x03\x04ABCD") |
| r |
| assert r == (b"ABCD","1.2.3.4") |
| r = i.addfield(None, b"FOO", "1.2.3.4") |
| r |
| assert r == b"FOO\x01\x02\x03\x04" |
| |
| = SourceIPField |
| ~ core field |
| defaddr = conf.route.route('0.0.0.0')[1] |
| class Test(Packet): fields_desc = [SourceIPField("sourceip")] |
| |
| assert Test().sourceip == defaddr |
| assert Test(raw(Test())).sourceip == defaddr |
| |
| assert IP(dst="0.0.0.0").src == defaddr |
| assert IP(raw(IP(dst="0.0.0.0"))).src == defaddr |
| defaddr = conf.route.route('1.1.1.1')[1] |
| assert IP(dst="1.1.1.1").src == defaddr |
| assert IP(raw(IP(dst="1.1.1.1"))).src == defaddr |
| |
| |
| #= ByteField |
| #~ core field |
| #b = ByteField("foo", None) |
| #b.i2m(" |
| #b.getfield |
| |
| = ThreeBytesField |
| ~ field threebytesfield |
| |
| class TestThreeBytesField(Packet): |
| fields_desc = [ |
| X3BytesField('test1', None), |
| ThreeBytesField('test2', None), |
| XLE3BytesField('test3', None), |
| LEThreeBytesField('test4', None), |
| ] |
| |
| p = TestThreeBytesField(test1=0x123456, test2=123456, test3=0xfedbca, test4=567890) |
| assert raw(p) == b'\x12\x34\x56\x01\xe2\x40\xca\xdb\xfe\x52\xaa\x08' |
| print(p.sprintf('%test1% %test2% %test3% %test4%')) |
| assert p.sprintf('%test1% %test2% %test3% %test4%') == '0x123456 123456 0xfedbca 567890' |
| assert repr(p.test1) == '1193046' |
| |
| |
| = NBytesField |
| ~ field nbytesfield |
| |
| class TestNBytesField(Packet): |
| fields_desc = [ |
| NBytesField('test1', None, 7), |
| XNBytesField('test2', None, 5), |
| XNBytesField('test3', None, 11), |
| NBytesField('test4', None, 11), |
| ] |
| |
| p = TestNBytesField(test1=0x00112233445566, test2=824650445619, test3=0xffeeddccbbaa9988776655, test4=0xffeeddccbbaa9988776655) |
| print(raw(p)) |
| assert raw(p) == b'\x00\x11\x22\x33\x44\x55\x66\xc0\x00\xff\x33\x33\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55' |
| print(p.sprintf('%test1% %test2% %test3% %test4%')) |
| assert p.sprintf('%test1% %test2% %test3% %test4%') == '18838586676582 0xc000ff3333 0xffeeddccbbaa9988776655 309404098707666285700277845' |
| assert p.test1 == 0x112233445566 |
| assert p.test2 == 0xc000ff3333 |
| assert p.test3 == 0xffeeddccbbaa9988776655 |
| assert p.test4 == 309404098707666285700277845 |
| |
| class TestFuzzNBytesField(Packet): |
| fields_desc = [ |
| NBytesField('test1', 0, 128), |
| ] |
| |
| f = fuzz(TestFuzzNBytesField()) |
| assert f.test1.max == 2 ** (128 * 8) - 1 |
| |
| p2 = TestNBytesField(raw(p)) |
| assert p2.sprintf('%test1% %test2% %test3% %test4%') == '18838586676582 0xc000ff3333 0xffeeddccbbaa9988776655 309404098707666285700277845' |
| assert p2.test1 == 18838586676582 |
| assert p2.test2 == 0xc000ff3333 |
| assert p2.test3 == 0xffeeddccbbaa9988776655 |
| assert p2.test4 == 309404098707666285700277845 |
| assert raw(p2) == raw(TestNBytesField(test1=p2.test1, test2=p2.test2, test3=p2.test3, test4=p2.test4)) |
| |
| = StrField |
| ~ field strfield |
| ~ field strlenfield |
| |
| class TestStrField(Packet): |
| fields_desc = [ |
| LEFieldLenField('slen', None, length_of="s1"), |
| StrLenField('s1', None, length_from=lambda pkt: pkt.slen), |
| StrField('s2', None), |
| ] |
| |
| p = TestStrField(s1="cafe", s2="deadbeef") |
| assert raw(p) == b'\x04\x00cafedeadbeef' |
| print(p.sprintf("%s1% %s2%")) |
| assert p.sprintf("%s1% %s2%") == "b'cafe' b'deadbeef'" |
| |
| |
| = StrFieldUtf16 |
| ~ field strfieldutf16 |
| ~ field strlenfieldutf16 |
| |
| class TestStrLenFieldUtf16(Packet): |
| fields_desc = [ |
| LEFieldLenField('slen', None, length_of="s1"), |
| StrLenFieldUtf16('s1', None, length_from=lambda pkt: pkt.slen), |
| ] |
| |
| p = TestStrLenFieldUtf16(s1='cafe') |
| assert raw(p) == b'\x08\x00c\x00a\x00f\x00e\x00' |
| assert p.sprintf("%s1%") == 'cafe' |
| |
| = StrFieldUtf16 |
| ~ field strfieldutf16 |
| ~ field strlenfieldutf16 |
| |
| class TestStrFieldUtf16(Packet): |
| fields_desc = [ |
| StrFieldUtf16('s1', None), |
| ] |
| |
| p = TestStrFieldUtf16(s1='cafe') |
| assert raw(p) == b'c\x00a\x00f\x00e\x00' |
| assert p.sprintf("%s1%") == 'cafe' |
| |
| ############ |
| ############ |
| + Tests on ActionField |
| |
| = Creation of a layer with ActionField |
| ~ field actionfield |
| |
| |
| class TestAction(Packet): |
| __slots__ = ["_val", "_fld", "_priv1", "_priv2"] |
| name = "TestAction" |
| fields_desc = [ ActionField(ByteField("tst", 3), "my_action", priv1=1, priv2=2) ] |
| def __init__(self, *args, **kargs): |
| self._val, self._fld, self._priv1, self._priv2 = None, None, None, None |
| super(TestAction, self).__init__(*args, **kargs) |
| def my_action(self, val, fld, priv1, priv2): |
| print("Action (%i)!" % val) |
| self._val, self._fld, self._priv1, self._priv2 = val, fld, priv1, priv2 |
| |
| = Triggering action |
| ~ field actionfield |
| |
| t = TestAction() |
| assert t._val == t._fld == t._priv1 == t._priv2 == None |
| t.tst=42 |
| assert t._priv1 == 1 |
| assert t._priv2 == 2 |
| assert t._val == 42 |
| |
| |
| ############ |
| ############ |
| + Tests on FieldLenField |
| |
| = Creation of a layer with FieldLenField |
| ~ field |
| class TestFLenF(Packet): |
| fields_desc = [ FieldLenField("len", None, length_of="str", fmt="B", adjust=lambda pkt,x:x+1), |
| StrLenField("str", "default", length_from=lambda pkt:pkt.len-1,) ] |
| |
| = Assembly of an empty packet |
| ~ field |
| p = TestFLenF() |
| p |
| r = raw(p) |
| r |
| r == b"\x08default" |
| |
| = Assembly of non empty packet |
| ~ field |
| p = TestFLenF(str="123") |
| p |
| r = raw(p) |
| r |
| r == b"\x04123" |
| |
| = Disassembly |
| ~ field |
| p = TestFLenF(b"\x04ABCDEFGHIJKL") |
| p |
| p.len == 4 and p.str == b"ABC" and Raw in p |
| |
| |
| = BitFieldLenField test |
| ~ field |
| class TestBFLenF(Packet): |
| fields_desc = [ BitFieldLenField("len", None, 4, length_of="str" , adjust=lambda pkt,x:x+1, tot_size=-2), |
| BitField("nothing",0xfff, 12, end_tot_size=-2), |
| StrLenField("str", "default", length_from=lambda pkt:pkt.len-1, ) ] |
| |
| a=TestBFLenF() |
| r = raw(a) |
| r |
| assert r == b"\xff\x8fdefault" |
| |
| a.str="" |
| r = raw(a) |
| r |
| assert r == b"\xff\x1f" |
| |
| p = TestBFLenF(b"\xff\x1f@@") |
| p |
| assert p.len == 1 and p.str == b"" and Raw in p and p[Raw].load == b"@@" |
| |
| p = TestBFLenF(b"\xff\x6fabcdeFGH") |
| p |
| assert p.len == 6 and p.str == b"abcde" and Raw in p and p[Raw].load == b"FGH" |
| |
| = Test BitLenField |
| ~ field |
| |
| SIZES = {0: 6, 1: 6, 2: 14, 3: 22} |
| |
| class TestBitLenField(Packet): |
| fields_desc = [ |
| BitField("mode", 0, 2), |
| BitLenField("value", 0, length_from=lambda pkt: SIZES[pkt.mode]) |
| ] |
| |
| p = TestBitLenField(mode=1, value=50) |
| assert bytes(p) == b"r" |
| |
| p = TestBitLenField(mode=2, value=5000) |
| assert bytes(p) == b'\x93\x88' |
| |
| p = TestBitLenField(b'\xc0\x01\xf4') |
| assert p.mode == 3 |
| assert p.value == 500 |
| |
| = Test UTCTimeField |
| ~ field |
| |
| class TestUTCTimeField(Packet): |
| fields_desc = [ |
| # A Windows time field. See GH#4308 |
| UTCTimeField( |
| "Time", |
| None, |
| fmt="<Q", |
| epoch=[1601, 1, 1, 0, 0, 0], |
| custom_scaling=1e7, |
| ) |
| ] |
| |
| |
| p = TestUTCTimeField(Time=0) |
| assert p.sprintf("%Time%") == 'Mon, 01 Jan 1601 00:00:00 (-11644473600)' |
| |
| p = TestUTCTimeField(Time=133587912345678900) |
| assert p.sprintf("%Time%") == 'Sun, 28 Apr 2024 15:20:34 (1714317634)' |
| |
| ############ |
| ############ |
| + Tests on FieldListField |
| |
| = Creation of a layer |
| ~ field |
| class TestFLF(Packet): |
| name="test" |
| fields_desc = [ FieldLenField("len", None, count_of="lst", fmt="B"), |
| FieldListField("lst", None, IntField("elt",0), count_from=lambda pkt:pkt.len) |
| ] |
| |
| = Assembly of an empty packet |
| ~ field |
| a = TestFLF() |
| raw(a) |
| |
| = Assembly of a non-empty packet |
| ~ field |
| a = TestFLF() |
| a.lst = [7,65539] |
| ls(a) |
| r = raw(a) |
| r |
| import struct |
| r == struct.pack("!BII", 2,7,65539) |
| |
| = Disassemble |
| ~ field |
| import struct |
| p = TestFLF(b"\x00\x11\x12") |
| p |
| assert p.len == 0 and Raw in p and p[Raw].load == b"\x11\x12" |
| p = TestFLF(struct.pack("!BIII",3,1234,2345,12345678)) |
| p |
| assert p.len == 3 and p.lst == [1234,2345,12345678] |
| |
| = Disassemble unaligned |
| ~ field |
| import struct |
| class TestFLFUnaligned(Packet): |
| name="test" |
| fields_desc = [ BitFieldLenField("len", None, 3, count_of="lst"), |
| FieldListField("lst", None, XBitField("elt",0,8), count_from=lambda pkt:pkt.len), |
| BitField("ignore", None, 5), |
| ] |
| |
| p = TestFLFUnaligned(b"\x68\x28\x48\x6a") |
| p |
| assert p.len == 3 and p.lst == [0x41,0x42,0x43] and p.ignore == 0xa |
| |
| = Manipulate |
| ~ field |
| a = TestFLF(lst=[4]) |
| r = raw(a) |
| r |
| assert r == b"\x01\x00\x00\x00\x04" |
| a.lst.append(1234) |
| TestFLF(raw(a)) |
| a.show2() |
| a.len=7 |
| r = raw(a) |
| assert r == b"\x07\x00\x00\x00\x04\x00\x00\x04\xd2" |
| a.len=2 |
| a.lst=[1,2,3,4,5] |
| p = TestFLF(raw(a)) |
| p |
| assert Raw in p and p[Raw].load == b'\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05' |
| |
| = Test mutability of the default values |
| ~ field |
| class X(Packet): |
| fields_desc = [ FieldListField("f", [], ByteField("", 0)) ] |
| |
| m = X() |
| m.f.append(3) |
| assert raw(m) == b"\x03" |
| assert m.default_fields['f'] == [] |
| assert m.fields['f'] == [3] |
| |
| |
| ############ |
| ############ |
| + PacketListField |
| |
| = Create a layer |
| ~ field lengthfield |
| class TestPLF(Packet): |
| name="test" |
| fields_desc=[ FieldLenField("len", None, count_of="plist"), |
| PacketListField("plist", None, IP, count_from=lambda pkt:pkt.len,) ] |
| |
| = Test the PacketListField assembly |
| ~ field lengthfield |
| x=TestPLF() |
| r = raw(x) |
| r |
| r == b"\x00\x00" |
| |
| = Test the PacketListField assembly 2 |
| ~ field lengthfield |
| x=TestPLF() |
| x.plist=[IP()/TCP(), IP()/UDP()] |
| r = raw(x) |
| r |
| r.startswith(b'\x00\x02E') |
| |
| = Test disassembly |
| ~ field lengthfield |
| x=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()]) |
| p = TestPLF(raw(x)) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 1234567 |
| |
| = Nested PacketListField |
| ~ field lengthfield |
| y=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()]) |
| p = TestPLF(plist=[y,IP()/TCP(seq=333333)]) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333 |
| |
| ############ |
| ############ |
| + PacketListField tests |
| |
| = Create a layer |
| ~ field lengthfield |
| class TestPLF(Packet): |
| name="test" |
| fields_desc=[ FieldLenField("len", None, count_of="plist"), |
| PacketListField("plist", None, IP, count_from=lambda pkt:pkt.len) ] |
| |
| = Test the PacketListField assembly |
| ~ field lengthfield |
| x=TestPLF() |
| r = raw(x) |
| r |
| r == b"\x00\x00" |
| |
| = Test the PacketListField assembly 2 |
| ~ field lengthfield |
| x=TestPLF() |
| x.plist=[IP()/TCP(), IP()/UDP()] |
| r = raw(x) |
| r |
| r.startswith(b'\x00\x02E') |
| |
| = Test disassembly |
| ~ field lengthfield |
| x=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()]) |
| p = TestPLF(raw(x)) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 1234567 |
| |
| = Test parent reference |
| ~ field lengthfield |
| x=TestPLF(plist=[IP()/TCP(), IP()/UDP()]) |
| assert p.getlayer(IP, 1).parent == p and p.getlayer(IP, 2).parent == p |
| p = TestPLF(raw(x)) |
| assert p.getlayer(IP, 1).parent == p and p.getlayer(IP, 2).parent == p |
| |
| = Test parent reference in guess_payload_class |
| |
| class TestGuessPLFInner(Packet): |
| name="test guess inner" |
| fields_desc=[ LenField("foo", None) ] |
| 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(TestGuessPLFInner, self).guess_payload_class(payload) |
| |
| class TestGuessPLF(Packet): |
| name="test guess" |
| fields_desc=[PacketListField("plist", None, TestGuessPLFInner, |
| next_cls_cb=lambda p,l,c,r: TestGuessPLFInner if len(l) == 0 else None)] |
| |
| x=TestGuessPLF(plist=TestGuessPLFInner()/Raw(b'123')) |
| p=TestGuessPLF(raw(x)) |
| assert p[TestGuessPLFInner].parentflag |
| assert p[TestGuessPLFInner].parent == p |
| |
| = Nested PacketListField |
| ~ field lengthfield |
| y=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()]) |
| p = TestPLF(plist=[y,IP()/TCP(seq=333333)]) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333 |
| |
| = Complex packet |
| ~ field lengthfield ccc |
| class TestPkt(Packet): |
| fields_desc = [ ByteField("f1",65), |
| ShortField("f2",0x4244) ] |
| def extract_padding(self, p): |
| return "", p |
| |
| class TestPLF2(Packet): |
| fields_desc = [ FieldLenField("len1", None, count_of="plist", fmt="H", |
| adjust=lambda pkt, x: x + 2), |
| FieldLenField("len2", None, length_of="plist", fmt="I", |
| adjust=lambda pkt, x: (x + 1) // 2), |
| PacketListField("plist", None, TestPkt, |
| length_from=lambda x: (x.len2 * 2) // 3 * 3) ] |
| |
| a=TestPLF2() |
| r = raw(a) |
| r |
| assert r == b"\x00\x02\x00\x00\x00\x00" |
| |
| a.plist=[TestPkt(),TestPkt(f1=100)] |
| r = raw(a) |
| r |
| assert r == b'\x00\x04\x00\x00\x00\x03ABDdBD' |
| |
| a /= "123456" |
| b = TestPLF2(raw(a)) |
| b.show() |
| assert b.len1 == 4 and b.len2 == 3 |
| assert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244 |
| assert b[TestPkt:2].f1 == 100 |
| assert Raw in b and b[Raw].load == b"123456" |
| |
| a.plist.append(TestPkt(f1=200)) |
| b = TestPLF2(raw(a)) |
| b.show() |
| assert b.len1 == 5 and b.len2 == 5 |
| assert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244 |
| assert b[TestPkt:2].f1 == 100 |
| assert b[TestPkt:3].f1 == 200 |
| assert b.getlayer(TestPkt,4) is None |
| assert Raw in b and b[Raw].load == b"123456" |
| hexdiff(a,b) |
| assert raw(a) == raw(b) |
| |
| ############ |
| ############ |
| + Tests on TCPOptionsField |
| |
| = Test calls on TCPOptionsField.getfield |
| |
| assert TCPOptionsField("test", "").getfield(TCP(dataofs=0), "") == ('', []) |
| |
| |
| ############ |
| ############ |
| + PacketListField tests |
| |
| = Create a layer |
| ~ field lengthfield |
| class TestPLF(Packet): |
| name="test" |
| fields_desc=[ FieldLenField("len", None, count_of="plist"), |
| PacketListField("plist", None, IP, count_from=lambda pkt:pkt.len) ] |
| |
| = Test the PacketListField assembly |
| ~ field lengthfield |
| x=TestPLF() |
| r = raw(x) |
| r |
| r == b"\x00\x00" |
| |
| = Test the PacketListField assembly 2 |
| ~ field lengthfield |
| x=TestPLF() |
| x.plist=[IP()/TCP(), IP()/UDP()] |
| r = raw(x) |
| r |
| r.startswith(b'\x00\x02E') |
| |
| = Test disassembly |
| ~ field lengthfield |
| x=TestPLF(plist=[IP()/TCP(seq=1234567), IP()/UDP()]) |
| p = TestPLF(raw(x)) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 1234567 |
| |
| = Nested PacketListField |
| ~ field lengthfield |
| y=IP()/TCP(seq=111111)/TestPLF(plist=[IP()/TCP(seq=222222),IP()/UDP()]) |
| p = TestPLF(plist=[y,IP()/TCP(seq=333333)]) |
| p |
| p.show() |
| IP in p and TCP in p and UDP in p and p[TCP].seq == 111111 and p[TCP:2].seq==222222 and p[TCP:3].seq == 333333 |
| |
| = Complex packet |
| ~ field lengthfield ccc |
| class TestPkt(Packet): |
| fields_desc = [ ByteField("f1",65), |
| ShortField("f2",0x4244) ] |
| def extract_padding(self, p): |
| return "", p |
| |
| class TestPLF2(Packet): |
| fields_desc = [ FieldLenField("len1", None, count_of="plist",fmt="H", |
| adjust=lambda pkt,x: x + 2), |
| FieldLenField("len2", None, length_of="plist", fmt="I", |
| adjust=lambda pkt, x: (x + 1) // 2), |
| PacketListField("plist", None, TestPkt, |
| length_from=lambda x: (x.len2 * 2) // 3 *3) ] |
| |
| a=TestPLF2() |
| r = raw(a) |
| r |
| assert r == b"\x00\x02\x00\x00\x00\x00" |
| |
| a.plist=[TestPkt(),TestPkt(f1=100)] |
| r = raw(a) |
| r |
| assert r == b'\x00\x04\x00\x00\x00\x03ABDdBD' |
| |
| a /= "123456" |
| b = TestPLF2(raw(a)) |
| b.show() |
| assert b.len1 == 4 and b.len2 == 3 |
| assert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244 |
| assert b[TestPkt:2].f1 == 100 |
| assert Raw in b and b[Raw].load == b"123456" |
| |
| a.plist.append(TestPkt(f1=200)) |
| b = TestPLF2(raw(a)) |
| b.show() |
| assert b.len1 == 5 and b.len2 == 5 |
| assert b[TestPkt].f1 == 65 and b[TestPkt].f2 == 0x4244 |
| assert b[TestPkt:2].f1 == 100 |
| assert b[TestPkt:3].f1 == 200 |
| assert b.getlayer(TestPkt,4) is None |
| assert Raw in b and b[Raw].load == b"123456" |
| hexdiff(a,b) |
| assert raw(a) == raw(b) |
| |
| = Create layers for heterogeneous PacketListField |
| ~ field lengthfield |
| TestPLFH1 = type('TestPLFH1', (Packet,), { |
| 'name': 'test1', |
| 'fields_desc': [ByteField('data', 0)], |
| 'guess_payload_class': lambda self, p: conf.padding_layer, |
| } |
| ) |
| TestPLFH2 = type('TestPLFH2', (Packet,), { |
| 'name': 'test2', |
| 'fields_desc': [ShortField('data', 0)], |
| 'guess_payload_class': lambda self, p: conf.padding_layer, |
| } |
| ) |
| class TestPLFH3(Packet): |
| name = 'test3' |
| fields_desc = [ |
| PacketListField( |
| 'data', [], |
| next_cls_cb=lambda pkt, lst, p, remain: pkt.detect_next_packet(lst, p, remain) |
| ) |
| ] |
| def detect_next_packet(self, lst, p, remain): |
| if len(remain) < 3: |
| return None |
| if isinstance(p, type(None)): |
| return TestPLFH1 |
| if p.data & 3 == 1: |
| return TestPLFH1 |
| if p.data & 3 == 2: |
| return TestPLFH2 |
| return None |
| |
| = Test heterogeneous PacketListField |
| ~ field lengthfield |
| |
| p = TestPLFH3(b'\x02\x01\x01\xc1\x02\x80\x04toto') |
| assert isinstance(p.data[0], TestPLFH1) |
| assert p.data[0].data == 0x2 |
| assert isinstance(p.data[1], TestPLFH2) |
| assert p.data[1].data == 0x101 |
| assert isinstance(p.data[2], TestPLFH1) |
| assert p.data[2].data == 0xc1 |
| assert isinstance(p.data[3], TestPLFH1) |
| assert p.data[3].data == 0x2 |
| assert isinstance(p.data[4], TestPLFH2) |
| assert p.data[4].data == 0x8004 |
| assert isinstance(p.payload, conf.raw_layer) |
| assert p.payload.load == b'toto' |
| |
| p = TestPLFH3(b'\x02\x01\x01\xc1\x02\x80\x02to') |
| assert isinstance(p.data[0], TestPLFH1) |
| assert p.data[0].data == 0x2 |
| assert isinstance(p.data[1], TestPLFH2) |
| assert p.data[1].data == 0x101 |
| assert isinstance(p.data[2], TestPLFH1) |
| assert p.data[2].data == 0xc1 |
| assert isinstance(p.data[3], TestPLFH1) |
| assert p.data[3].data == 0x2 |
| assert isinstance(p.data[4], TestPLFH2) |
| assert p.data[4].data == 0x8002 |
| assert isinstance(p.payload, conf.raw_layer) |
| assert p.payload.load == b'to' |
| |
| = Create layers for heterogeneous PacketListField with memory |
| ~ field lengthfield |
| TestPLFH4 = type('TestPLFH4', (Packet,), { |
| 'name': 'test4', |
| 'fields_desc': [ByteField('data', 0)], |
| 'guess_payload_class': lambda self, p: conf.padding_layer, |
| } |
| ) |
| TestPLFH5 = type('TestPLFH5', (Packet,), { |
| 'name': 'test5', |
| 'fields_desc': [ShortField('data', 0)], |
| 'guess_payload_class': lambda self, p: conf.padding_layer, |
| } |
| ) |
| class TestPLFH6(Packet): |
| __slots__ = ['_memory'] |
| name = 'test6' |
| fields_desc = [ |
| PacketListField( |
| 'data', [], |
| next_cls_cb=lambda pkt, lst, p, remain: pkt.detect_next_packet(lst, p, remain) |
| ) |
| ] |
| def detect_next_packet(self, lst, p, remain): |
| if isinstance(p, type(None)): |
| self._memory = [TestPLFH4] * 3 + [TestPLFH5] |
| try: |
| return self._memory.pop(0) |
| except IndexError: |
| return None |
| |
| = Test heterogeneous PacketListField with memory |
| ~ field lengthfield |
| |
| p = TestPLFH6(b'\x01\x02\x03\xc1\x02toto') |
| assert isinstance(p.data[0], TestPLFH4) |
| assert p.data[0].data == 0x1 |
| assert isinstance(p.data[1], TestPLFH4) |
| assert p.data[1].data == 0x2 |
| assert isinstance(p.data[2], TestPLFH4) |
| assert p.data[2].data == 0x3 |
| assert isinstance(p.data[3], TestPLFH5) |
| assert p.data[3].data == 0xc102 |
| assert isinstance(p.payload, conf.raw_layer) |
| assert p.payload.load == b'toto' |
| |
| = Test nested PacketListFields |
| ~ field |
| # Note: having packets that look like this is a terrible idea, and will perform |
| # very badly. However we must ensure we don't freeze because of it. |
| |
| # https://github.com/secdev/scapy/issues/3894 |
| |
| class GuessPayload(Packet): |
| @classmethod |
| def dispatch_hook(cls, *args, **kargs): |
| return TestNestedPLF |
| |
| class TestNestedPLF(Packet): |
| fields_desc = [ |
| ByteField('b', 0), |
| PacketListField('pl', [], GuessPayload) |
| ] |
| |
| p = TestNestedPLF(b'\x01' * 100) |
| |
| # check |
| i = 1 |
| while p.pl: |
| p = p.pl[0] |
| p.show() |
| i += 1 |
| |
| assert i == 100 |
| |
| = Test cache handling of payload modification in a PacketListField |
| ~ field |
| |
| # GH4414 |
| class SubPacket(Packet): |
| fields_desc = [ |
| ByteField("b", 0), |
| ] |
| |
| class MyPacket(Packet): |
| fields_desc = [ |
| PacketListField("a", [], SubPacket), |
| ] |
| |
| |
| p = MyPacket(b"\x00extrapayload") |
| p.a[0] = SubPacket(b=0) / b"test" |
| |
| assert bytes(p) == b"\x00test" |
| |
| = Test cache handling of payload modification in a PacketField |
| ~ field |
| |
| # also GH4414 |
| class PayloadPacket(Packet): |
| fields_desc = [ |
| StrField("b", ""), |
| ] |
| |
| class SubPacket(Packet): |
| fields_desc = [] |
| |
| bind_layers(SubPacket, PayloadPacket) |
| |
| class MyPacket(Packet): |
| fields_desc = [ |
| PacketField("a", None, SubPacket), |
| ] |
| |
| |
| s = b'test' |
| p = MyPacket(s) |
| |
| p[PayloadPacket].b = b'new' |
| assert p.build() != s |
| |
| |
| ############ |
| ############ |
| + Tests on MultiFlagsField |
| |
| = Test calls on MultiFlagsField.any2i |
| ~ multiflagsfield |
| |
| import collections |
| MockPacket = collections.namedtuple('MockPacket', ['type']) |
| |
| f = MultiFlagsField('flags', set(), 3, { |
| 0: { |
| 0: MultiFlagsEntry('A', 'OptionA'), |
| 1: MultiFlagsEntry('B', 'OptionB'), |
| }, |
| 1: { |
| 0: MultiFlagsEntry('+', 'Plus'), |
| 1: MultiFlagsEntry('*', 'Star'), |
| }, |
| }, |
| depends_on=lambda x: x.type |
| ) |
| |
| mp = MockPacket(0) |
| x = f.any2i(mp, set()) |
| assert isinstance(x, set) |
| assert len(x) == 0 |
| x = f.any2i(mp, {'A'}) |
| assert isinstance(x, set) |
| assert len(x) == 1 |
| assert 'A' in x |
| assert 'B' not in x |
| assert '+' not in x |
| x = f.any2i(mp, {'A', 'B'}) |
| assert isinstance(x, set) |
| assert len(x) == 2 |
| assert 'A' in x |
| assert 'B' in x |
| assert '+' not in x |
| assert '*' not in x |
| x = f.any2i(mp, 3) |
| assert isinstance(x, set) |
| assert len(x) == 2 |
| assert 'A' in x |
| assert 'B' in x |
| assert '+' not in x |
| assert '*' not in x |
| x = f.any2i(mp, 7) |
| assert isinstance(x, set) |
| assert len(x) == 3 |
| assert 'A' in x |
| assert 'B' in x |
| assert 'bit 2' in x |
| assert '+' not in x |
| assert '*' not in x |
| mp = MockPacket(1) |
| x = f.any2i(mp, {'+', '*'}) |
| assert isinstance(x, set) |
| assert len(x) == 2 |
| assert '+' in x |
| assert '*' in x |
| assert 'A' not in x |
| assert 'B' not in x |
| try: |
| x = f.any2i(mp, {'A'}) |
| ret = False |
| except AssertionError: |
| ret = True |
| |
| assert ret |
| #Following test demonstrate a non-sensical yet acceptable usage :( |
| x = f.any2i(None, {'Toto'}) |
| assert 'Toto' in x |
| |
| = Test calls on MultiFlagsField.i2m |
| ~ multiflagsfield |
| |
| import collections |
| MockPacket = collections.namedtuple('MockPacket', ['type']) |
| |
| f = MultiFlagsField('flags', set(), 3, { |
| 0: { |
| 0: MultiFlagsEntry('A', 'OptionA'), |
| 1: MultiFlagsEntry('B', 'OptionB'), |
| }, |
| 1: { |
| 0: MultiFlagsEntry('+', 'Plus'), |
| 1: MultiFlagsEntry('*', 'Star'), |
| }, |
| }, |
| depends_on=lambda x: x.type |
| ) |
| |
| mp = MockPacket(0) |
| x = f.i2m(mp, set()) |
| assert isinstance(x, int) |
| assert x == 0 |
| x = f.i2m(mp, {'A'}) |
| assert isinstance(x, int) |
| assert x == 1 |
| x = f.i2m(mp, {'A', 'B'}) |
| assert isinstance(x, int) |
| assert x == 3 |
| x = f.i2m(mp, {'A', 'B', 'bit 2'}) |
| assert isinstance(x, int) |
| assert x == 7 |
| try: |
| x = f.i2m(mp, {'+'}) |
| ret = False |
| except: |
| ret = True |
| |
| assert ret |
| |
| = Test calls on MultiFlagsField.m2i |
| ~ multiflagsfield |
| |
| import collections |
| MockPacket = collections.namedtuple('MockPacket', ['type']) |
| |
| f = MultiFlagsField('flags', set(), 3, { |
| 0: { |
| 0: MultiFlagsEntry('A', 'OptionA'), |
| 1: MultiFlagsEntry('B', 'OptionB'), |
| }, |
| 1: { |
| 0: MultiFlagsEntry('+', 'Plus'), |
| 1: MultiFlagsEntry('*', 'Star'), |
| }, |
| }, |
| depends_on=lambda x: x.type |
| ) |
| |
| mp = MockPacket(0) |
| x = f.m2i(mp, 2) |
| assert isinstance(x, set) |
| assert len(x) == 1 |
| assert 'B' in x |
| assert 'A' not in x |
| assert '*' not in x |
| |
| x = f.m2i(mp, 7) |
| assert isinstance(x, set) |
| assert 'B' in x |
| assert 'A' in x |
| assert 'bit 2' in x |
| assert '*' not in x |
| assert '+' not in x |
| x = f.m2i(mp, 0) |
| assert len(x) == 0 |
| mp = MockPacket(1) |
| x = f.m2i(mp, 2) |
| assert isinstance(x, set) |
| assert len(x) == 1 |
| assert '*' in x |
| assert '+' not in x |
| assert 'B' not in x |
| |
| = Test calls on MultiFlagsField.i2repr |
| ~ multiflagsfield |
| |
| import collections, re |
| MockPacket = collections.namedtuple('MockPacket', ['type']) |
| |
| f = MultiFlagsField('flags', set(), 3, { |
| 0: { |
| 0: MultiFlagsEntry('A', 'OptionA'), |
| 1: MultiFlagsEntry('B', 'OptionB'), |
| }, |
| 1: { |
| 0: MultiFlagsEntry('+', 'Plus'), |
| 1: MultiFlagsEntry('*', 'Star'), |
| }, |
| }, |
| depends_on=lambda x: x.type |
| ) |
| |
| mp = MockPacket(0) |
| x = f.i2repr(mp, {'A', 'B'}) |
| assert re.match(r'^.*OptionA \(A\).*$', x) is not None |
| assert re.match(r'^.*OptionB \(B\).*$', x) is not None |
| mp = MockPacket(1) |
| x = f.i2repr(mp, {'*', '+', 'bit 2'}) |
| assert re.match(r'^.*Star \(\*\).*$', x) is not None |
| assert re.match(r'^.*Plus \(\+\).*$', x) is not None |
| assert re.match(r'^.*bit 2.*$', x) is not None |
| |
| ############ |
| ############ |
| + EnumField tests |
| |
| = EnumField tests initialization |
| |
| # Basic EnumField |
| f = EnumField('test', 0, {0: 'Foo', 1: 'Bar'}) |
| # Reverse i2s/s2i |
| rf = EnumField('test', 0, {'Foo': 0, 'Bar': 1}) |
| # EnumField initialized with a list |
| lf = EnumField('test', 0, ['Foo', 'Bar']) |
| # EnumField with i2s_cb/s2i_cb |
| fcb = EnumField('test', 0, ( |
| lambda x: 'Foo' if x == 0 else 'Bar' if 1 <= x <= 10 else repr(x), |
| lambda x: 0 if x == 'Foo' else 1 if x == 'Bar' else int(x), |
| ) |
| ) |
| |
| def expect_exception(e, c): |
| try: |
| eval(c) |
| assert False |
| except e: |
| assert True |
| |
| |
| = EnumField.any2i_one |
| ~ field enumfield |
| |
| assert f.any2i_one(None, 'Foo') == 0 |
| assert f.any2i_one(None, 'Bar') == 1 |
| assert f.any2i_one(None, 2) == 2 |
| expect_exception(KeyError, 'f.any2i_one(None, "Baz")') |
| |
| assert rf.any2i_one(None, 'Foo') == 0 |
| assert rf.any2i_one(None, 'Bar') == 1 |
| assert rf.any2i_one(None, 2) == 2 |
| expect_exception(KeyError, 'rf.any2i_one(None, "Baz")') |
| |
| assert lf.any2i_one(None, 'Foo') == 0 |
| assert lf.any2i_one(None, 'Bar') == 1 |
| assert lf.any2i_one(None, 2) == 2 |
| expect_exception(KeyError, 'lf.any2i_one(None, "Baz")') |
| |
| assert fcb.any2i_one(None, 'Foo') == 0 |
| assert fcb.any2i_one(None, 'Bar') == 1 |
| assert fcb.any2i_one(None, 5) == 5 |
| expect_exception(ValueError, 'fcb.any2i_one(None, "Baz")') |
| |
| = EnumField.any2i |
| ~ field enumfield |
| |
| assert f.any2i(None, 'Foo') == 0 |
| assert f.any2i(None, 'Bar') == 1 |
| assert f.any2i(None, 2) == 2 |
| expect_exception(KeyError, 'f.any2i(None, "Baz")') |
| assert f.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2] |
| |
| assert rf.any2i(None, 'Foo') == 0 |
| assert rf.any2i(None, 'Bar') == 1 |
| assert rf.any2i(None, 2) == 2 |
| expect_exception(KeyError, 'rf.any2i(None, "Baz")') |
| assert rf.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2] |
| |
| assert lf.any2i(None, 'Foo') == 0 |
| assert lf.any2i(None, 'Bar') == 1 |
| assert lf.any2i(None, 2) == 2 |
| expect_exception(KeyError, 'lf.any2i(None, "Baz")') |
| assert lf.any2i(None, ['Foo', 'Bar', 2]) == [0, 1, 2] |
| |
| assert fcb.any2i(None, 'Foo') == 0 |
| assert fcb.any2i(None, 'Bar') == 1 |
| assert fcb.any2i(None, 5) == 5 |
| expect_exception(ValueError, 'fcb.any2i(None, "Baz")') |
| assert f.any2i(None, ['Foo', 'Bar', 5]) == [0, 1, 5] |
| |
| True |
| |
| = EnumField.i2repr_one |
| ~ field enumfield |
| |
| assert f.i2repr_one(None, 0) == 'Foo' |
| assert f.i2repr_one(None, 1) == 'Bar' |
| assert f.i2repr_one(None, 2) == '2' |
| |
| assert rf.i2repr_one(None, 0) == 'Foo' |
| assert rf.i2repr_one(None, 1) == 'Bar' |
| assert rf.i2repr_one(None, 2) == '2' |
| |
| assert lf.i2repr_one(None, 0) == 'Foo' |
| assert lf.i2repr_one(None, 1) == 'Bar' |
| assert lf.i2repr_one(None, 2) == '2' |
| |
| assert fcb.i2repr_one(None, 0) == 'Foo' |
| assert fcb.i2repr_one(None, 1) == 'Bar' |
| assert fcb.i2repr_one(None, 5) == 'Bar' |
| assert fcb.i2repr_one(None, 11) == repr(11) |
| |
| conf.noenum.add(f, rf, lf, fcb) |
| |
| assert f.i2repr_one(None, 0) == repr(0) |
| assert f.i2repr_one(None, 1) == repr(1) |
| assert f.i2repr_one(None, 2) == repr(2) |
| |
| assert rf.i2repr_one(None, 0) == repr(0) |
| assert rf.i2repr_one(None, 1) == repr(1) |
| assert rf.i2repr_one(None, 2) == repr(2) |
| |
| assert lf.i2repr_one(None, 0) == repr(0) |
| assert lf.i2repr_one(None, 1) == repr(1) |
| assert lf.i2repr_one(None, 2) == repr(2) |
| |
| assert fcb.i2repr_one(None, 0) == repr(0) |
| assert fcb.i2repr_one(None, 1) == repr(1) |
| assert fcb.i2repr_one(None, 5) == repr(5) |
| assert fcb.i2repr_one(None, 11) == repr(11) |
| |
| conf.noenum.remove(f, rf, lf, fcb) |
| |
| assert f.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| assert rf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| assert lf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| assert fcb.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| |
| 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)) == '<RandNum>' |
| assert rf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| assert lf.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| assert fcb.i2repr_one(None, RandNum(0, 10)) == '<RandNum>' |
| |
| 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 == '<RandBin>' |
| |
| ############ |
| ############ |
| + 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] |