diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index 58720b79ea3..e4dc7f39550 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -39,6 +39,7 @@ BitField, ByteEnumField, ByteField, + ConditionalField, DestIP6Field, FieldLenField, FlagsField, @@ -997,12 +998,17 @@ class IPv6ExtHdrRouting(_IPv6ExtHdr): name = "IPv6 Option Header Routing" fields_desc = [ByteEnumField("nh", 59, ipv6nh), FieldLenField("len", None, count_of="addresses", fmt="B", - adjust=lambda pkt, x:2 * x), # in 8 bytes blocks # noqa: E501 + adjust=lambda pkt, x: 2 * x + len(pkt.getfieldval("data") or b"") // 8), # noqa: E501 ByteField("type", 0), ByteField("segleft", None), BitField("reserved", 0, 32), # There is meaning in this field ... # noqa: E501 IP6ListField("addresses", [], - length_from=lambda pkt: 8 * pkt.len)] + length_from=lambda pkt: 16 * (pkt.len // 2)), + ConditionalField(StrLenField("data", b"", + length_from=lambda pkt: 8), + lambda pkt: (bool(pkt.getfieldval("data")) + if pkt.len is None + else pkt.len % 2))] overload_fields = {IPv6: {"nh": 43}} def post_build(self, pkt, pay): diff --git a/test/scapy/layers/inet6.uts b/test/scapy/layers/inet6.uts index 16d56d7ff88..9e4f1bb1c9f 100644 --- a/test/scapy/layers/inet6.uts +++ b/test/scapy/layers/inet6.uts @@ -81,6 +81,19 @@ raw(IPv6(src="2048::deca", dst="2047::cafe")/IPv6ExtHdrRouting(addresses=["2001: ########### IPv6ExtHdrSegmentRouting Class ########################### += IPv6ExtHdrRouting Class - Odd length - build and dissect +routing = IPv6ExtHdrRouting(type=253, segleft=0, data=b"12345678") +# Port 5353 would make Scapy parse the payload as mDNS; the point here is the +# routing header, so use a port with no higher-layer binding. +s = raw(IPv6(src="2001:db8::1", dst="2001:db8::2") / routing / + UDP(sport=53000, dport=40000) / Raw(b"policy")) +p = IPv6(s) +assert p[IPv6ExtHdrRouting].len == 1 +assert p[IPv6ExtHdrRouting].addresses == [] +assert p[IPv6ExtHdrRouting].data == b"12345678" +assert UDP in p and p[UDP].dport == 40000 +assert raw(p) == s + = IPv6ExtHdrSegmentRouting Class - default - build & dissect s = raw(IPv6()/IPv6ExtHdrSegmentRouting()/UDP()) assert s == b'`\x00\x00\x00\x00 +@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x11\x02\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x005\x005\x00\x08\xffr'