diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index 58720b79ea3..4e91071bfce 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -996,16 +996,21 @@ class IPv6ExtHdrDestOpt(_IPv6ExtHdr): 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 + ByteField("len", None), # in 8 bytes blocks 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)), + # An odd 'len' leaves 8 bytes over, which is half an address. + StrLenField("pad", b"", + length_from=lambda pkt: 8 * (pkt.len % 2))] overload_fields = {IPv6: {"nh": 43}} def post_build(self, pkt, pay): + if self.len is None: + tmp_len = (len(pkt) - 8) // 8 + pkt = pkt[:1] + struct.pack("B", tmp_len) + pkt[2:] if self.segleft is None: pkt = pkt[:3] + struct.pack("B", len(self.addresses)) + pkt[4:] return _IPv6ExtHdr.post_build(self, pkt, pay) diff --git a/test/scapy/layers/inet6.uts b/test/scapy/layers/inet6.uts index 16d56d7ff88..2a3a5575808 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, pad=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].pad == 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'