On Mon, Dec 12, 2016 at 01:02:55PM +1000, David Gwynne wrote:
> 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?

ok stsp@

> 
> 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;
> 

Reply via email to