]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Add support for IPv6 routing header type 4 660/head
authorAhmed Abdelsalam <[email protected]>
Fri, 29 Dec 2017 16:43:35 +0000 (17:43 +0100)
committerAhmed Abdelsalam <[email protected]>
Fri, 29 Dec 2017 16:43:35 +0000 (17:43 +0100)
IPv6 routing header type 4 is known as Segment Routing Header (SRH).
It is used by Segment Routing (SR) to steer a packet through a
controlled set of instructions, called segments. It is described in
https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-07

An extension is added to allow tcpdump to print SRH information.

ip6.h
print-rt6.c
tests/TESTLIST
tests/ipv6-srh-ext-header.out [new file with mode: 0644]
tests/ipv6-srh-ext-header.pcap [new file with mode: 0644]

diff --git a/ip6.h b/ip6.h
index 35f12e42764b8de3285f16c13f3102b810d2b1e6..9ed1499cfea599b3e6dab8e5b91f82caf212b8df 100644 (file)
--- a/ip6.h
+++ b/ip6.h
@@ -174,6 +174,7 @@ struct ip6_rthdr {
 
 #define IPV6_RTHDR_TYPE_0 0
 #define IPV6_RTHDR_TYPE_2 2
+#define IPV6_RTHDR_TYPE_4 4
 
 /* Type 0 Routing header */
 /* Also used for Type 2 */
@@ -186,6 +187,21 @@ struct ip6_rthdr0 {
        struct in6_addr ip6r0_addr[1];  /* up to 23 addresses */
 };
 
+/**
+ * Type 4 Routing header
+ * known as Segment Routing Header 'SRH'
+ */
+struct ip6_srh {
+       nd_uint8_t      srh_nxt;                /* next header */
+       nd_uint8_t      srh_len;                /* length in units of 8 octets */
+       nd_uint8_t      srh_type;               /* Routing Type 4 */
+       nd_uint8_t      srh_segleft;            /* segments left */
+       nd_uint8_t      srh_last_ent;           /* Last Entry*/
+       nd_uint8_t      srh_flags;              /* Flags */
+       nd_uint16_t     srh_tag;                /* Tag */
+       struct in6_addr srh_segments[1];        /* SRH segments list*/
+};
+
 /* Fragment header */
 struct ip6_frag {
        nd_uint8_t  ip6f_nxt;           /* next header */
index 269496aaecfc98ccfd107b626e4cf83be2a03a95..af74fa0a76ae1de0c1abb078c76c67628faab502 100644 (file)
@@ -40,6 +40,7 @@ rt6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2 _U_)
 {
        const struct ip6_rthdr *dp;
        const struct ip6_rthdr0 *dp0;
+       const struct ip6_srh *srh;
        const u_char *ep;
        u_int i, len, type;
        const struct in6_addr *addr;
@@ -83,6 +84,33 @@ rt6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2 _U_)
                ND_PRINT((ndo, ") "));
                return((EXTRACT_U_1(dp0->ip6r0_len) + 1) << 3);
                break;
+       case IPV6_RTHDR_TYPE_4:
+               srh = (const struct ip6_srh *)dp;
+               ND_PRINT((ndo, ", last-entry=%u", EXTRACT_U_1(srh->srh_last_ent)));
+
+               ND_TCHECK(srh->srh_flags);
+               if (EXTRACT_U_1(srh->srh_flags) || ndo->ndo_vflag) {
+                       ND_PRINT((ndo, ", flags=0x%0x",
+                               EXTRACT_U_1(srh->srh_flags)));
+               }
+
+               ND_PRINT((ndo, ", tag=%x", EXTRACT_BE_U_2(srh->srh_tag)));
+
+               if (len % 2 == 1)
+                       goto trunc;
+               len >>= 1;
+               addr = &srh->srh_segments[0];
+               for (i = 0; i < len; i++) {
+                       if ((const u_char *)(addr + 1) > ep)
+                               goto trunc;
+
+                       ND_PRINT((ndo, ", [%d]%s", i, ip6addr_string(ndo, addr)));
+                       addr++;
+               }
+               /*(*/
+               ND_PRINT((ndo, ") "));
+               return((EXTRACT_U_1(srh->srh_len) + 1) << 3);
+               break;
        default:
                goto trunc;
                break;
index ecc93da8fd2994cf3ed497715e84f99b2d300295..1e2a850815330e0f20797beeceae10fd7337564e 100644 (file)
@@ -222,7 +222,7 @@ dnssec-vv   dnssec.pcap             dnssec-vv.out           -vv
 #IPv6 tests
 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
 # Loopback/CTP test case
 loopback       loopback.pcap           loopback.out
 
diff --git a/tests/ipv6-srh-ext-header.out b/tests/ipv6-srh-ext-header.out
new file mode 100644 (file)
index 0000000..bca97ea
--- /dev/null
@@ -0,0 +1 @@
+IP6 (flowlabel 0x889ad, hlim 64, next-header Routing (43) payload length: 144) a:b:c:12::1 > a:b:c:2::f1:0: srcrt (len=4, type=4, segleft=1, last-entry=1, flags=0x0, tag=0, [0]a:b:c:3::d6, [1]a:b:c:2::f1:0) IP6 (flowlabel 0x889ad, hlim 64, next-header ICMPv6 (58) payload length: 64) a:b:c:12::1 > b2::2: [icmp6 sum ok] ICMP6, echo request, seq 1
diff --git a/tests/ipv6-srh-ext-header.pcap b/tests/ipv6-srh-ext-header.pcap
new file mode 100644 (file)
index 0000000..871b9e4
Binary files /dev/null and b/tests/ipv6-srh-ext-header.pcap differ