X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/536f5125835b031330f472aebed8241a1718b018..ad6df73f5a6c46a409c7629f5588b1b81dff6357:/print-gre.c diff --git a/print-gre.c b/print-gre.c index a97259e7..aa05dc58 100644 --- a/print-gre.c +++ b/print-gre.c @@ -24,7 +24,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.7 2000-09-23 08:54:29 guy Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.14 2002-06-01 23:50:31 guy Exp $"; #endif #ifdef HAVE_CONFIG_H @@ -33,11 +33,9 @@ static const char rcsid[] = #include #include -#include #include #include -#include #include #include @@ -46,38 +44,31 @@ static const char rcsid[] = #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ -#define GRE_SIZE (20) - struct gre { - u_short flags; - u_short proto; - union { - struct gre_ckof { - u_short cksum; - u_short offset; - } gre_ckof; - u_int32_t key; - u_int32_t seq; - } gre_void1; - union { - u_int32_t key; - u_int32_t seq; - u_int32_t routing; - } gre_void2; - union { - u_int32_t seq; - u_int32_t routing; - } gre_void3; - union { - u_int32_t routing; - } gre_void4; + u_int16_t flags; + u_int16_t proto; }; +/* RFC 2784 - GRE */ #define GRE_CP 0x8000 /* Checksum Present */ -#define GRE_RP 0x4000 /* Routing Present */ +#define GRE_VER_MASK 0x0007 /* Version */ + +/* RFC 2890 - Key and Sequence extensions to GRE */ #define GRE_KP 0x2000 /* Key Present */ #define GRE_SP 0x1000 /* Sequence Present */ +/* Legacy from RFC 1700 */ +#define GRE_RP 0x4000 /* Routing Present */ +#define GRE_sP 0x0800 /* strict source route present */ +#define GRE_RECUR_MASK 0x0700 /* Recursion Control */ +#define GRE_RECUR_SHIFT 8 + +#define GRE_COP (GRE_RP|GRE_CP) /* Checksum & Offset Present */ + +/* "Enhanced GRE" from RFC2637 - PPTP */ +#define GRE_AP 0x0080 /* Ack present */ + +#define GRE_MBZ_MASK 0x0078 /* not defined */ /* * Deencapsulate and print a GRE-tunneled IP datagram @@ -87,17 +78,18 @@ gre_print(const u_char *bp, u_int length) { const u_char *cp = bp + 4; const struct gre *gre; - u_short flags, proto; + u_int16_t flags, proto; + u_short ver=0; + u_short extracted_ethertype; gre = (const struct gre *)bp; - if (length < GRE_SIZE) { - goto trunc; - } + TCHECK(gre->proto); flags = EXTRACT_16BITS(&gre->flags); proto = EXTRACT_16BITS(&gre->proto); + (void)printf("gre "); - if (vflag) { + if (flags) { /* Decode the flags */ putchar('['); if (flags & GRE_CP) @@ -108,23 +100,72 @@ gre_print(const u_char *bp, u_int length) putchar('K'); if (flags & GRE_SP) putchar('S'); + if (flags & GRE_sP) + putchar('s'); + if (flags & GRE_AP) + putchar('A'); + if (flags & GRE_RECUR_MASK) + printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT); + ver = flags & GRE_VER_MASK; + printf("v%u", ver); + + if (flags & GRE_MBZ_MASK) + printf("!%x", flags & GRE_MBZ_MASK); fputs("] ", stdout); } - /* Checksum & Offset are present */ - if ((flags & GRE_CP) | (flags & GRE_RP)) - cp += 4; + if (flags & GRE_COP) { + int checksum, offset; + + TCHECK2(*cp, 4); + checksum = EXTRACT_16BITS(cp); + offset = EXTRACT_16BITS(cp + 2); + + if (flags & GRE_CP) { + /* Checksum present */ + + /* todo: check checksum */ + if (vflag > 1) + printf("C:%04x ", checksum); + } + if (flags & GRE_RP) { + /* Offset present */ + + if (vflag > 1) + printf("O:%04x ", offset); + } + cp += 4; /* skip checksum and offset */ + } + if (flags & GRE_KP) { + TCHECK2(*cp, 4); + if (ver == 1) { /* PPTP */ + if (vflag > 1) + printf("PL:%u ", EXTRACT_16BITS(cp)); + printf("ID:%04x ", EXTRACT_16BITS(cp+2)); + } + else + printf("K:%08x ", EXTRACT_32BITS(cp)); + cp += 4; /* skip key */ + } + if (flags & GRE_SP) { + TCHECK2(*cp, 4); + printf("S:%u ", EXTRACT_32BITS(cp)); + cp += 4; /* skip seq */ + } + if (flags & GRE_AP && ver >= 1) { + TCHECK2(*cp, 4); + printf("A:%u ", EXTRACT_32BITS(cp)); + cp += 4; /* skip ack */ + } /* We don't support routing fields (variable length) now. Punt. */ if (flags & GRE_RP) return; - if (flags & GRE_KP) - cp += 4; - if (flags & GRE_SP) - cp += 4; + TCHECK(cp[0]); length -= cp - bp; - if (ether_encap_print(proto, cp, length, length) == 0) + if (ether_encap_print(proto, cp, length, length, + &extracted_ethertype) == 0) printf("gre-proto-0x%04X", proto); return;