X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/f555c163f90c9de17ebcef8313f86404c5174ca9..ad6df73f5a6c46a409c7629f5588b1b81dff6357:/print-gre.c diff --git a/print-gre.c b/print-gre.c index 74d02638..aa05dc58 100644 --- a/print-gre.c +++ b/print-gre.c @@ -24,17 +24,18 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.4 1999-10-07 23:47:11 mcr Exp $"; + "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.14 2002-06-01 23:50:31 guy Exp $"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" #endif #include #include -#include #include #include -#include -#include #include #include @@ -43,41 +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 */ -#define GREPROTO_IP 0x0800 +/* "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,31 +100,73 @@ 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; - /* We don't support routing fields (variable length) now. Punt. */ - if (flags & GRE_RP) - return; + if (flags & GRE_COP) { + int checksum, offset; - if (flags & GRE_KP) - cp += 4; - if (flags & GRE_SP) - cp += 4; + TCHECK2(*cp, 4); + checksum = EXTRACT_16BITS(cp); + offset = EXTRACT_16BITS(cp + 2); - switch (proto) { + if (flags & GRE_CP) { + /* Checksum present */ - case GREPROTO_IP: - ip_print(cp, length - ((cp - bp) / sizeof(u_char))); - break; + /* todo: check checksum */ + if (vflag > 1) + printf("C:%04x ", checksum); + } + if (flags & GRE_RP) { + /* Offset present */ - default: - printf("gre-proto-0x%04X", proto); - break; + 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; + + TCHECK(cp[0]); + + length -= cp - bp; + if (ether_encap_print(proto, cp, length, length, + &extracted_ethertype) == 0) + printf("gre-proto-0x%04X", proto); return; trunc: