gre can do more things than tcpdump currently thinks it can.
specifically, gre can be carried by ipv6, and it can encapsulate
more than just ip and ppp packets.
as such, this tells tcpdump to look at gre inside ipv6 packets.
gre uses ethertypes to represent what protocol it contains, so
instead of rolling a gre specific version of ip and ppp protocol
types, just reuse the ether ones.
also tell tcpdump that gre can contains ipv6, ethernet, and mpls.
NVGRE is basically a constrained gre header (ie, must be version
0, must only have the K bit set, must be transether), so this detects
that and prints the NVGRE interpretation of the Key field. that
makes the VSID in NVGRE packets easier to see.
theres some tweaks to output so it looks ok with and without the
-v optarg.
ok?
Index: print-gre.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-gre.c,v
retrieving revision 1.11
diff -u -p -r1.11 print-gre.c
--- print-gre.c 5 Nov 2015 11:55:21 -0000 1.11
+++ print-gre.c 12 Dec 2016 02:48:21 -0000
@@ -39,6 +39,8 @@
#include <netinet/ip.h>
#include <arpa/inet.h>
+#include <net/ethertypes.h>
+
#include <stdio.h>
#include <string.h>
@@ -55,13 +57,15 @@
#define GRE_AP 0x0080 /* acknowledgment# present */
#define GRE_VERS 0x0007 /* protocol version */
-#define GREPROTO_IP 0x0800 /* IP */
-#define GREPROTO_PPP 0x880b /* PPTP */
-
/* source route entry types */
#define GRESRE_IP 0x0800 /* IP */
#define GRESRE_ASN 0xfffe /* ASN */
+#define NVGRE_VSID_MASK 0xffffff00U
+#define NVGRE_VSID_SHIFT 8
+#define NVGRE_FLOWID_MASK 0x000000ffU
+#define NVGRE_FLOWID_SHIFT 0
+
void gre_print_0(const u_char *, u_int);
void gre_print_1(const u_char *, u_int);
void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int);
@@ -82,14 +86,17 @@ gre_print(const u_char *bp, u_int length
}
vers = EXTRACT_16BITS(bp) & GRE_VERS;
- if (vers == 0)
+ switch (vers) {
+ case 0:
gre_print_0(bp, len);
- else if (vers == 1)
+ break;
+ case 1:
gre_print_1(bp, len);
- else
+ break;
+ default:
printf("gre-unknown-version=%u", vers);
- return;
-
+ break;
+ }
}
void
@@ -114,6 +121,8 @@ gre_print_0(const u_char *bp, u_int leng
if (len < 2)
goto trunc;
prot = EXTRACT_16BITS(bp);
+ printf("%s", etherproto_string(prot));
+
len -= 2;
bp += 2;
@@ -121,21 +130,32 @@ gre_print_0(const u_char *bp, u_int leng
if (len < 2)
goto trunc;
if (vflag)
- printf("sum 0x%x ", EXTRACT_16BITS(bp));
+ printf(" sum 0x%x", EXTRACT_16BITS(bp));
bp += 2;
len -= 2;
if (len < 2)
goto trunc;
- printf("off 0x%x ", EXTRACT_16BITS(bp));
+ printf(" off 0x%x", EXTRACT_16BITS(bp));
bp += 2;
len -= 2;
}
if (flags & GRE_KP) {
+ uint32_t key, vsid;
+
if (len < 4)
goto trunc;
- printf("key=0x%x ", EXTRACT_32BITS(bp));
+ key = EXTRACT_32BITS(bp);
+
+ /* maybe NVGRE? */
+ if (flags == (GRE_KP | 0) && prot == ETHERTYPE_TRANSETHER) {
+ vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT;
+ printf(" NVGRE vsid=%u (0x%x)+flowid=0x%02x /",
+ vsid, vsid,
+ (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT);
+ }
+ printf(" key=%u (0x%x)", key, key);
bp += 4;
len -= 4;
}
@@ -143,7 +163,7 @@ gre_print_0(const u_char *bp, u_int leng
if (flags & GRE_SP) {
if (len < 4)
goto trunc;
- printf("seq %u ", EXTRACT_32BITS(bp));
+ printf(" seq %u", EXTRACT_32BITS(bp));
bp += 4;
len -= 4;
}
@@ -174,10 +194,21 @@ gre_print_0(const u_char *bp, u_int leng
}
}
+ printf(": ");
+
switch (prot) {
- case GREPROTO_IP:
+ case ETHERTYPE_IP:
ip_print(bp, len);
break;
+ case ETHERTYPE_IPV6:
+ ip6_print(bp, len);
+ break;
+ case ETHERTYPE_MPLS:
+ mpls_print(bp, len);
+ break;
+ case ETHERTYPE_TRANSETHER:
+ ether_print(bp, len);
+ break;
default:
printf("gre-proto-0x%x", prot);
}
@@ -198,7 +229,7 @@ gre_print_1(const u_char *bp, u_int leng
bp += 2;
if (vflag) {
- printf("[%s%s%s%s%s%s] ",
+ printf("[%s%s%s%s%s%s]",
(flags & GRE_CP) ? "C" : "",
(flags & GRE_RP) ? "R" : "",
(flags & GRE_KP) ? "K" : "",
@@ -214,19 +245,19 @@ gre_print_1(const u_char *bp, u_int leng
bp += 2;
if (flags & GRE_CP) {
- printf("cpset!");
+ printf(" cpset!");
return;
}
if (flags & GRE_RP) {
- printf("rpset!");
+ printf(" rpset!");
return;
}
if ((flags & GRE_KP) == 0) {
- printf("kpunset!");
+ printf(" kpunset!");
return;
}
if (flags & GRE_sP) {
- printf("spset!");
+ printf(" spset!");
return;
}
@@ -236,7 +267,7 @@ gre_print_1(const u_char *bp, u_int leng
if (len < 4)
goto trunc;
k = EXTRACT_32BITS(bp);
- printf("call %d ", k & 0xffff);
+ printf(" call %d", k & 0xffff);
len -= 4;
bp += 4;
}
@@ -244,7 +275,7 @@ gre_print_1(const u_char *bp, u_int leng
if (flags & GRE_SP) {
if (len < 4)
goto trunc;
- printf("seq %u ", EXTRACT_32BITS(bp));
+ printf(" seq %u", EXTRACT_32BITS(bp));
bp += 4;
len -= 4;
}
@@ -252,18 +283,20 @@ gre_print_1(const u_char *bp, u_int leng
if (flags & GRE_AP) {
if (len < 4)
goto trunc;
- printf("ack %u ", EXTRACT_32BITS(bp));
+ printf(" ack %u", EXTRACT_32BITS(bp));
bp += 4;
len -= 4;
}
if ((flags & GRE_SP) == 0) {
- printf("no-payload");
+ printf(" no-payload");
return;
}
+ printf(": ");
+
switch (prot) {
- case GREPROTO_PPP:
+ case ETHERTYPE_PPP:
printf("gre-ppp-payload");
break;
default:
@@ -282,17 +315,17 @@ gre_sre_print(u_int16_t af, u_int8_t sre
{
switch (af) {
case GRESRE_IP:
- printf("(rtaf=ip");
+ printf(" (rtaf=ip");
gre_sre_ip_print(sreoff, srelen, bp, len);
- printf(") ");
+ printf(")");
break;
case GRESRE_ASN:
- printf("(rtaf=asn");
+ printf(" (rtaf=asn");
gre_sre_asn_print(sreoff, srelen, bp, len);
- printf(") ");
+ printf(")");
break;
default:
- printf("(rtaf=0x%x) ", af);
+ printf(" (rtaf=0x%x)", af);
}
}
void
Index: print-ip6.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-ip6.c,v
retrieving revision 1.23
diff -u -p -r1.23 print-ip6.c
--- print-ip6.c 16 Nov 2015 00:16:39 -0000 1.23
+++ print-ip6.c 12 Dec 2016 02:48:21 -0000
@@ -184,6 +184,18 @@ ip6_print(const u_char *bp, u_int length
if (! vflag)
printf(" (encap)");
goto end;
+
+#ifndef IPPROTO_GRE
+#define IPPROTO_GRE 47
+#endif
+ case IPPROTO_GRE:
+ gre_print(cp, len);
+ if (! vflag) {
+ printf(" (gre encap)");
+ goto out;
+ }
+ goto end;
+
case IPPROTO_NONE:
(void)printf("no next header");
goto end;