From ed5fd3e041649568c5633b1c5df900bfc2cf04f4 Mon Sep 17 00:00:00 2001 From: Arnav Das Date: Sun, 16 Mar 2025 12:32:08 +0700 Subject: [PATCH 1/4] Update inet6.py for Destination Option Extension Headers can show weird behavious. Linux's sk_buff considers the IPv6 Payload to be either TCP, UDP or ICMP. It does not consider Extension Headers to be the payload. Following similar architecture, This small modification let's packet flow with Destination Option on both, request and response packets be captured as well. --- scapy/layers/inet6.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index f1ecc210c06..d1d2ee73948 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -481,7 +481,20 @@ def answers(self, other): elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting): # noqa: E501 return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting # noqa: E501 elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt): - return self.payload.answers(other.payload.payload) + # Extension Headers can show weird behavious. + # Linux's sk_buff considers the IPv6 Payload + # to be either TCP, UDP or ICMP. It does not + # consider Extension Headers to be the payload. + # Following similar architecture, This small + # modification let's packet flow with Destination + # Option on both, request and response packets + # be captured as well. + if UDP in self and UDP in other: + return self[UDP].answers(other[UDP]) + elif TCP in self and TCP in other: + return self[TCP].answers(other[TCP]) + else: + return self.payload.answers(other.payload.payload) # Previous Implementation elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance # noqa: E501 return self.payload.payload.answers(other.payload) else: From a49980c0ecbd92a3fae8b8cd966e03ef3a12e81a Mon Sep 17 00:00:00 2001 From: Guillaume Valadon Date: Sat, 14 Feb 2026 11:02:44 +0100 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- scapy/layers/inet6.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index d1d2ee73948..ff8c4df96e9 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -481,12 +481,12 @@ def answers(self, other): elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting): # noqa: E501 return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting # noqa: E501 elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt): - # Extension Headers can show weird behavious. + # Extension Headers can show weird behavior. # Linux's sk_buff considers the IPv6 Payload # to be either TCP, UDP or ICMP. It does not # consider Extension Headers to be the payload. - # Following similar architecture, This small - # modification let's packet flow with Destination + # Following similar architecture, this small + # modification lets packet flow with Destination # Option on both, request and response packets # be captured as well. if UDP in self and UDP in other: From 5b420bfd7fa0d6f00c6084d9b2c8a0cb76ac14a8 Mon Sep 17 00:00:00 2001 From: Guillaume Valadon Date: Sat, 14 Feb 2026 11:22:59 +0100 Subject: [PATCH 3/4] Add tests for IPv6 with Destination Option header (hashret/answers) --- test/scapy/layers/inet6.uts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/scapy/layers/inet6.uts b/test/scapy/layers/inet6.uts index 206ab975c8a..cb0f7c25ac9 100644 --- a/test/scapy/layers/inet6.uts +++ b/test/scapy/layers/inet6.uts @@ -461,6 +461,18 @@ a = IPv6(b'`\x00\x00\x00\x00\x10<\xff\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x0 assert a.hashret() == b.hashret() assert b.answers(a) += IPv6 with DestOpt and UDP +a = IPv6(raw(IPv6(src="2001:db8::1", dst="2001:db8::2")/IPv6ExtHdrDestOpt()/UDP(sport=12345, dport=53))) +b = IPv6(raw(IPv6(src="2001:db8::2", dst="2001:db8::1")/IPv6ExtHdrDestOpt()/UDP(sport=53, dport=12345))) +assert a.hashret() == b.hashret() +assert b.answers(a) + += IPv6 with DestOpt and TCP +a = IPv6(raw(IPv6(src="2001:db8::1", dst="2001:db8::2")/IPv6ExtHdrDestOpt()/TCP(sport=12345, dport=80, flags="S", seq=1000))) +b = IPv6(raw(IPv6(src="2001:db8::2", dst="2001:db8::1")/IPv6ExtHdrDestOpt()/TCP(sport=80, dport=12345, flags="SA", seq=2000, ack=1001))) +assert a.hashret() == b.hashret() +assert b.answers(a) + = ICMPv6EchoRequest and ICMPv6EchoReply - answers() test 8 - (live) use Net6 ~ netaccess ipv6 From 58af5c3c4c99bd0d4436142ac0801e3d8eb46eba Mon Sep 17 00:00:00 2001 From: Guillaume Valadon Date: Sat, 14 Feb 2026 12:07:59 +0100 Subject: [PATCH 4/4] Fix flake8 errors: trailing whitespace and inline comment formatting --- scapy/layers/inet6.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py index ff8c4df96e9..0059c785a83 100644 --- a/scapy/layers/inet6.py +++ b/scapy/layers/inet6.py @@ -485,16 +485,16 @@ def answers(self, other): # Linux's sk_buff considers the IPv6 Payload # to be either TCP, UDP or ICMP. It does not # consider Extension Headers to be the payload. - # Following similar architecture, this small + # Following similar architecture, this small # modification lets packet flow with Destination # Option on both, request and response packets # be captured as well. if UDP in self and UDP in other: return self[UDP].answers(other[UDP]) elif TCP in self and TCP in other: - return self[TCP].answers(other[TCP]) + return self[TCP].answers(other[TCP]) else: - return self.payload.answers(other.payload.payload) # Previous Implementation + return self.payload.answers(other.payload.payload) elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance # noqa: E501 return self.payload.payload.answers(other.payload) else: