]> The Tcpdump Group git mirrors - tcpdump/blob - print-gre.c
Added support for Win32, based on WinPcap.
[tcpdump] / print-gre.c
1 /*
2 * Copyright (c) 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Lawrence Berkeley Laboratory,
11 * Berkeley, CA. The name of the University may not be used to
12 * endorse or promote products derived from this software without
13 * specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * Initial contribution from John Hawkinson <jhawk@bbnplanet.com>
19 *
20 * This module implements support for decoding GRE (Generic Routing
21 * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702.
22 * This code only supports the IP encapsulation thereof.
23 */
24
25 #ifndef lint
26 static const char rcsid[] =
27 "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.16 2002-08-01 08:53:08 risso Exp $";
28 #endif
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <tcpdump-stdinc.h>
35
36 #include <stdio.h>
37
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "extract.h" /* must come after interface.h */
41
42 struct gre {
43 u_int16_t flags;
44 u_int16_t proto;
45 };
46
47 /* RFC 2784 - GRE */
48 #define GRE_CP 0x8000 /* Checksum Present */
49 #define GRE_VER_MASK 0x0007 /* Version */
50
51 /* RFC 2890 - Key and Sequence extensions to GRE */
52 #define GRE_KP 0x2000 /* Key Present */
53 #define GRE_SP 0x1000 /* Sequence Present */
54
55 /* Legacy from RFC 1700 */
56 #define GRE_RP 0x4000 /* Routing Present */
57 #define GRE_sP 0x0800 /* strict source route present */
58 #define GRE_RECUR_MASK 0x0700 /* Recursion Control */
59 #define GRE_RECUR_SHIFT 8
60
61 #define GRE_COP (GRE_RP|GRE_CP) /* Checksum & Offset Present */
62
63 /* "Enhanced GRE" from RFC2637 - PPTP */
64 #define GRE_AP 0x0080 /* Ack present */
65
66 #define GRE_MBZ_MASK 0x0078 /* not defined */
67
68 /*
69 * Deencapsulate and print a GRE-tunneled IP datagram
70 */
71 void
72 gre_print(const u_char *bp, u_int length)
73 {
74 const u_char *cp = bp + 4;
75 const struct gre *gre;
76 u_int16_t flags, proto;
77 u_short ver=0;
78 u_short extracted_ethertype;
79
80 gre = (const struct gre *)bp;
81
82 TCHECK(gre->proto);
83 flags = EXTRACT_16BITS(&gre->flags);
84 proto = EXTRACT_16BITS(&gre->proto);
85 (void)printf("gre ");
86
87 if (flags) {
88 /* Decode the flags */
89 putchar('[');
90 if (flags & GRE_CP)
91 putchar('C');
92 if (flags & GRE_RP)
93 putchar('R');
94 if (flags & GRE_KP)
95 putchar('K');
96 if (flags & GRE_SP)
97 putchar('S');
98 if (flags & GRE_sP)
99 putchar('s');
100 if (flags & GRE_AP)
101 putchar('A');
102 if (flags & GRE_RECUR_MASK)
103 printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT);
104 ver = flags & GRE_VER_MASK;
105 printf("v%u", ver);
106
107 if (flags & GRE_MBZ_MASK)
108 printf("!%x", flags & GRE_MBZ_MASK);
109 fputs("] ", stdout);
110 }
111
112 if (flags & GRE_COP) {
113 int checksum, offset;
114
115 TCHECK2(*cp, 4);
116 checksum = EXTRACT_16BITS(cp);
117 offset = EXTRACT_16BITS(cp + 2);
118
119 if (flags & GRE_CP) {
120 /* Checksum present */
121
122 /* todo: check checksum */
123 if (vflag > 1)
124 printf("C:%04x ", checksum);
125 }
126 if (flags & GRE_RP) {
127 /* Offset present */
128
129 if (vflag > 1)
130 printf("O:%04x ", offset);
131 }
132 cp += 4; /* skip checksum and offset */
133 }
134 if (flags & GRE_KP) {
135 TCHECK2(*cp, 4);
136 if (ver == 1) { /* PPTP */
137 if (vflag > 1)
138 printf("PL:%u ", EXTRACT_16BITS(cp));
139 printf("ID:%04x ", EXTRACT_16BITS(cp+2));
140 }
141 else
142 printf("K:%08x ", EXTRACT_32BITS(cp));
143 cp += 4; /* skip key */
144 }
145 if (flags & GRE_SP) {
146 TCHECK2(*cp, 4);
147 printf("S:%u ", EXTRACT_32BITS(cp));
148 cp += 4; /* skip seq */
149 }
150 if (flags & GRE_AP && ver >= 1) {
151 TCHECK2(*cp, 4);
152 printf("A:%u ", EXTRACT_32BITS(cp));
153 cp += 4; /* skip ack */
154 }
155 /* We don't support routing fields (variable length) now. Punt. */
156 if (flags & GRE_RP)
157 return;
158
159 TCHECK(cp[0]);
160
161 length -= cp - bp;
162 if (ether_encap_print(proto, cp, length, length,
163 &extracted_ethertype) == 0)
164 printf("gre-proto-0x%04X", proto);
165 return;
166
167 trunc:
168 fputs("[|gre]", stdout);
169
170 }