]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Fix checksum calculation for IPv6 Segment Routing (SRv6) traffic
authorAhmed Abdelsalam <[email protected]>
Thu, 22 Nov 2018 18:05:16 +0000 (19:05 +0100)
committerFrancois-Xavier Le Bail <[email protected]>
Fri, 29 Mar 2019 11:04:21 +0000 (12:04 +0100)
The checksum calculation for IPv6 packets is based on a pseudo
header that includes the packet's final Destination Address (DA).

If the IPv6 packet contains a Routing header, the final DA is the
last element of the Routing header [RFC8200].

Currently, tcpdump supports Routing header types 0 and 2.

IPv6 Segment Routing Header (SRH) is a new Routing header type (4).
SRH is defined in draft-ietf-6man-segment-routing-header [1].

This patch fix the checksum calculation for SRv6 packets. It allows
tcpdump to get the final DA value from SRv6 packets.

[1] https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-17

print-ip6.c
tests/TESTLIST
tests/ipv6-srh-insert-cksum.out [new file with mode: 0644]
tests/ipv6-srh-insert-cksum.pcap [new file with mode: 0644]

index b6893cf3998d0e7334db9210cfb071e678d1a486..9f8b4dbf63734ed7cf5f7fc3dd53eaf43723f36e 100644 (file)
@@ -53,6 +53,7 @@ ip6_finddst(netdissect_options *ndo, struct in6_addr *dst,
        const void *dst_addr;
        const struct ip6_rthdr *dp;
        const struct ip6_rthdr0 *dp0;
+       const struct ip6_srh *srh;
        const u_char *p;
        int i, len;
 
@@ -114,6 +115,19 @@ ip6_finddst(netdissect_options *ndo, struct in6_addr *dst,
                                        p += 16;
                                }
                                break;
+                       case IPV6_RTHDR_TYPE_4:
+                               /* IPv6 Segment Routing Header (SRH) */
+                               srh = (const struct ip6_srh *)dp;
+                               if (len % 2 == 1)
+                                       goto trunc;
+                               p = (const u_char *) srh->srh_segments;
+                               /*
+                                * The list of segments are encoded in the reverse order.
+                                * Accordingly, the final DA is encoded in srh_segments[0]
+                                */
+                               ND_TCHECK_16(p);
+                               dst_addr = (const void *)p;
+                               break;
 
                        default:
                                break;
index aaf22aea9d20ad9451609a064a2d772b15d54ef7..ceab4adf2d79cb19825cd1bc3983270567f34071 100644 (file)
@@ -237,6 +237,7 @@ dnssec-vv   dnssec.pcap             dnssec-vv.out           -vv
 ipv6-bad-version       ipv6-bad-version.pcap   ipv6-bad-version.out
 ipv6-routing-header    ipv6-routing-header.pcap        ipv6-routing-header.out -v
 ipv6-srh-ext-header    ipv6-srh-ext-header.pcap        ipv6-srh-ext-header.out -v
+ipv6-srh-insert-cksum  ipv6-srh-insert-cksum.pcap      ipv6-srh-insert-cksum.out -v
 # Loopback/CTP test case
 loopback       loopback.pcap           loopback.out
 
diff --git a/tests/ipv6-srh-insert-cksum.out b/tests/ipv6-srh-insert-cksum.out
new file mode 100644 (file)
index 0000000..1815c66
--- /dev/null
@@ -0,0 +1 @@
+    1  17:59:40.591932 IP6 (flowlabel 0x8f8b8, hlim 64, next-header Routing (43) payload length: 1088) 12::1 > 2::f1:0: srcrt (len=6, type=4, segleft=2, last-entry=2, flags=0x0, tag=0, [0]b2::2, [1]3::d6, [2]2::f1:0) 57745 > 5001: [udp sum ok] UDP, length 1024
diff --git a/tests/ipv6-srh-insert-cksum.pcap b/tests/ipv6-srh-insert-cksum.pcap
new file mode 100644 (file)
index 0000000..daeb55a
Binary files /dev/null and b/tests/ipv6-srh-insert-cksum.pcap differ