]> The Tcpdump Group git mirrors - tcpdump/blob - print-gre.c
Move the printer summaries from INSTALL.txt to each printer
[tcpdump] / print-gre.c
1 /* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */
2
3 /*
4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Jason L. Wright
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* \summary: Generic Routing Encapsulation (GRE) printer */
35
36 /*
37 * netdissect printer for GRE - Generic Routing Encapsulation
38 * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
39 */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44
45 #include <netdissect-stdinc.h>
46
47 #include <string.h>
48
49 #include "netdissect.h"
50 #include "addrtostr.h"
51 #include "extract.h"
52 #include "ethertype.h"
53
54 static const char tstr[] = "[|gre]";
55
56 #define GRE_CP 0x8000 /* checksum present */
57 #define GRE_RP 0x4000 /* routing present */
58 #define GRE_KP 0x2000 /* key present */
59 #define GRE_SP 0x1000 /* sequence# present */
60 #define GRE_sP 0x0800 /* source routing */
61 #define GRE_RECRS 0x0700 /* recursion count */
62 #define GRE_AP 0x0080 /* acknowledgment# present */
63
64 static const struct tok gre_flag_values[] = {
65 { GRE_CP, "checksum present"},
66 { GRE_RP, "routing present"},
67 { GRE_KP, "key present"},
68 { GRE_SP, "sequence# present"},
69 { GRE_sP, "source routing present"},
70 { GRE_RECRS, "recursion count"},
71 { GRE_AP, "ack present"},
72 { 0, NULL }
73 };
74
75 #define GRE_VERS_MASK 0x0007 /* protocol version */
76
77 /* source route entry types */
78 #define GRESRE_IP 0x0800 /* IP */
79 #define GRESRE_ASN 0xfffe /* ASN */
80
81 static void gre_print_0(netdissect_options *, const u_char *, u_int);
82 static void gre_print_1(netdissect_options *, const u_char *, u_int);
83 static void gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int);
84 static void gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
85 static void gre_sre_asn_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
86
87 void
88 gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
89 {
90 u_int len = length, vers;
91
92 if (len < 2) {
93 ND_PRINT((ndo, "%s", tstr));
94 return;
95 }
96 vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK;
97 ND_PRINT((ndo, "GREv%u",vers));
98
99 switch(vers) {
100 case 0:
101 gre_print_0(ndo, bp, len);
102 break;
103 case 1:
104 gre_print_1(ndo, bp, len);
105 break;
106 default:
107 ND_PRINT((ndo, " ERROR: unknown-version"));
108 break;
109 }
110 }
111
112 static void
113 gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
114 {
115 u_int len = length;
116 uint16_t flags, prot;
117
118 flags = EXTRACT_16BITS(bp);
119 if (ndo->ndo_vflag)
120 ND_PRINT((ndo, ", Flags [%s]",
121 bittok2str(gre_flag_values,"none",flags)));
122
123 len -= 2;
124 bp += 2;
125
126 if (len < 2)
127 goto trunc;
128 prot = EXTRACT_16BITS(bp);
129 len -= 2;
130 bp += 2;
131
132 if ((flags & GRE_CP) | (flags & GRE_RP)) {
133 if (len < 2)
134 goto trunc;
135 if (ndo->ndo_vflag)
136 ND_PRINT((ndo, ", sum 0x%x", EXTRACT_16BITS(bp)));
137 bp += 2;
138 len -= 2;
139
140 if (len < 2)
141 goto trunc;
142 ND_PRINT((ndo, ", off 0x%x", EXTRACT_16BITS(bp)));
143 bp += 2;
144 len -= 2;
145 }
146
147 if (flags & GRE_KP) {
148 if (len < 4)
149 goto trunc;
150 ND_PRINT((ndo, ", key=0x%x", EXTRACT_32BITS(bp)));
151 bp += 4;
152 len -= 4;
153 }
154
155 if (flags & GRE_SP) {
156 if (len < 4)
157 goto trunc;
158 ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
159 bp += 4;
160 len -= 4;
161 }
162
163 if (flags & GRE_RP) {
164 for (;;) {
165 uint16_t af;
166 uint8_t sreoff;
167 uint8_t srelen;
168
169 if (len < 4)
170 goto trunc;
171 af = EXTRACT_16BITS(bp);
172 sreoff = *(bp + 2);
173 srelen = *(bp + 3);
174 bp += 4;
175 len -= 4;
176
177 if (af == 0 && srelen == 0)
178 break;
179
180 gre_sre_print(ndo, af, sreoff, srelen, bp, len);
181
182 if (len < srelen)
183 goto trunc;
184 bp += srelen;
185 len -= srelen;
186 }
187 }
188
189 if (ndo->ndo_eflag)
190 ND_PRINT((ndo, ", proto %s (0x%04x)",
191 tok2str(ethertype_values,"unknown",prot),
192 prot));
193
194 ND_PRINT((ndo, ", length %u",length));
195
196 if (ndo->ndo_vflag < 1)
197 ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
198 else
199 ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
200
201 switch (prot) {
202 case ETHERTYPE_IP:
203 ip_print(ndo, bp, len);
204 break;
205 case ETHERTYPE_IPV6:
206 ip6_print(ndo, bp, len);
207 break;
208 case ETHERTYPE_MPLS:
209 mpls_print(ndo, bp, len);
210 break;
211 case ETHERTYPE_IPX:
212 ipx_print(ndo, bp, len);
213 break;
214 case ETHERTYPE_ATALK:
215 atalk_print(ndo, bp, len);
216 break;
217 case ETHERTYPE_GRE_ISO:
218 isoclns_print(ndo, bp, len, len);
219 break;
220 case ETHERTYPE_TEB:
221 ether_print(ndo, bp, len, len, NULL, NULL);
222 break;
223 default:
224 ND_PRINT((ndo, "gre-proto-0x%x", prot));
225 }
226 return;
227
228 trunc:
229 ND_PRINT((ndo, "%s", tstr));
230 }
231
232 static void
233 gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length)
234 {
235 u_int len = length;
236 uint16_t flags, prot;
237
238 flags = EXTRACT_16BITS(bp);
239 len -= 2;
240 bp += 2;
241
242 if (ndo->ndo_vflag)
243 ND_PRINT((ndo, ", Flags [%s]",
244 bittok2str(gre_flag_values,"none",flags)));
245
246 if (len < 2)
247 goto trunc;
248 prot = EXTRACT_16BITS(bp);
249 len -= 2;
250 bp += 2;
251
252
253 if (flags & GRE_KP) {
254 uint32_t k;
255
256 if (len < 4)
257 goto trunc;
258 k = EXTRACT_32BITS(bp);
259 ND_PRINT((ndo, ", call %d", k & 0xffff));
260 len -= 4;
261 bp += 4;
262 }
263
264 if (flags & GRE_SP) {
265 if (len < 4)
266 goto trunc;
267 ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
268 bp += 4;
269 len -= 4;
270 }
271
272 if (flags & GRE_AP) {
273 if (len < 4)
274 goto trunc;
275 ND_PRINT((ndo, ", ack %u", EXTRACT_32BITS(bp)));
276 bp += 4;
277 len -= 4;
278 }
279
280 if ((flags & GRE_SP) == 0)
281 ND_PRINT((ndo, ", no-payload"));
282
283 if (ndo->ndo_eflag)
284 ND_PRINT((ndo, ", proto %s (0x%04x)",
285 tok2str(ethertype_values,"unknown",prot),
286 prot));
287
288 ND_PRINT((ndo, ", length %u",length));
289
290 if ((flags & GRE_SP) == 0)
291 return;
292
293 if (ndo->ndo_vflag < 1)
294 ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
295 else
296 ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
297
298 switch (prot) {
299 case ETHERTYPE_PPP:
300 ppp_print(ndo, bp, len);
301 break;
302 default:
303 ND_PRINT((ndo, "gre-proto-0x%x", prot));
304 break;
305 }
306 return;
307
308 trunc:
309 ND_PRINT((ndo, "%s", tstr));
310 }
311
312 static void
313 gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff,
314 uint8_t srelen, const u_char *bp, u_int len)
315 {
316 switch (af) {
317 case GRESRE_IP:
318 ND_PRINT((ndo, ", (rtaf=ip"));
319 gre_sre_ip_print(ndo, sreoff, srelen, bp, len);
320 ND_PRINT((ndo, ")"));
321 break;
322 case GRESRE_ASN:
323 ND_PRINT((ndo, ", (rtaf=asn"));
324 gre_sre_asn_print(ndo, sreoff, srelen, bp, len);
325 ND_PRINT((ndo, ")"));
326 break;
327 default:
328 ND_PRINT((ndo, ", (rtaf=0x%x)", af));
329 }
330 }
331
332 static void
333 gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
334 const u_char *bp, u_int len)
335 {
336 const u_char *up = bp;
337 char buf[INET_ADDRSTRLEN];
338
339 if (sreoff & 3) {
340 ND_PRINT((ndo, ", badoffset=%u", sreoff));
341 return;
342 }
343 if (srelen & 3) {
344 ND_PRINT((ndo, ", badlength=%u", srelen));
345 return;
346 }
347 if (sreoff >= srelen) {
348 ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
349 return;
350 }
351
352 for (;;) {
353 if (len < 4 || srelen == 0)
354 return;
355
356 addrtostr(bp, buf, sizeof(buf));
357 ND_PRINT((ndo, " %s%s",
358 ((bp - up) == sreoff) ? "*" : "", buf));
359
360 bp += 4;
361 len -= 4;
362 srelen -= 4;
363 }
364 }
365
366 static void
367 gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
368 const u_char *bp, u_int len)
369 {
370 const u_char *up = bp;
371
372 if (sreoff & 1) {
373 ND_PRINT((ndo, ", badoffset=%u", sreoff));
374 return;
375 }
376 if (srelen & 1) {
377 ND_PRINT((ndo, ", badlength=%u", srelen));
378 return;
379 }
380 if (sreoff >= srelen) {
381 ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
382 return;
383 }
384
385 for (;;) {
386 if (len < 2 || srelen == 0)
387 return;
388
389 ND_PRINT((ndo, " %s%x",
390 ((bp - up) == sreoff) ? "*" : "",
391 EXTRACT_16BITS(bp)));
392
393 bp += 2;
394 len -= 2;
395 srelen -= 2;
396 }
397 }