blob: 4d7705f80edca018fa25b76862d035582a8306ff [file] [log] [blame]
The Android Open Source Project2949f582009-03-03 19:30:46 -08001/* $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/*
35 * tcpdump filter for GRE - Generic Routing Encapsulation
36 * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
37 */
38
Elliott Hughes892a68b2015-10-19 14:43:53 -070039#define NETDISSECT_REWORKED
The Android Open Source Project2949f582009-03-03 19:30:46 -080040#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <tcpdump-stdinc.h>
45
The Android Open Source Project2949f582009-03-03 19:30:46 -080046#include <string.h>
47
48#include "interface.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080049#include "extract.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080050#include "ethertype.h"
51
Elliott Hughes892a68b2015-10-19 14:43:53 -070052static const char tstr[] = "[|gre]";
53
The Android Open Source Project2949f582009-03-03 19:30:46 -080054#define GRE_CP 0x8000 /* checksum present */
55#define GRE_RP 0x4000 /* routing present */
56#define GRE_KP 0x2000 /* key present */
57#define GRE_SP 0x1000 /* sequence# present */
58#define GRE_sP 0x0800 /* source routing */
59#define GRE_RECRS 0x0700 /* recursion count */
60#define GRE_AP 0x0080 /* acknowledgment# present */
61
JP Abgrall53f17a92014-02-12 14:02:41 -080062static const struct tok gre_flag_values[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -080063 { GRE_CP, "checksum present"},
Elliott Hughes892a68b2015-10-19 14:43:53 -070064 { GRE_RP, "routing present"},
65 { GRE_KP, "key present"},
66 { GRE_SP, "sequence# present"},
The Android Open Source Project2949f582009-03-03 19:30:46 -080067 { GRE_sP, "source routing present"},
68 { GRE_RECRS, "recursion count"},
69 { GRE_AP, "ack present"},
70 { 0, NULL }
71};
72
73#define GRE_VERS_MASK 0x0007 /* protocol version */
74
75/* source route entry types */
76#define GRESRE_IP 0x0800 /* IP */
77#define GRESRE_ASN 0xfffe /* ASN */
78
Elliott Hughes892a68b2015-10-19 14:43:53 -070079static void gre_print_0(netdissect_options *, const u_char *, u_int);
80static void gre_print_1(netdissect_options *, const u_char *, u_int);
81static void gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int);
82static void gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
83static void gre_sre_asn_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
The Android Open Source Project2949f582009-03-03 19:30:46 -080084
85void
Elliott Hughes892a68b2015-10-19 14:43:53 -070086gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -080087{
88 u_int len = length, vers;
89
90 if (len < 2) {
Elliott Hughes892a68b2015-10-19 14:43:53 -070091 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -080092 return;
93 }
94 vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK;
Elliott Hughes892a68b2015-10-19 14:43:53 -070095 ND_PRINT((ndo, "GREv%u",vers));
The Android Open Source Project2949f582009-03-03 19:30:46 -080096
97 switch(vers) {
98 case 0:
Elliott Hughes892a68b2015-10-19 14:43:53 -070099 gre_print_0(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800100 break;
101 case 1:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700102 gre_print_1(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800103 break;
104 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700105 ND_PRINT((ndo, " ERROR: unknown-version"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800106 break;
107 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800108}
109
Elliott Hughes892a68b2015-10-19 14:43:53 -0700110static void
111gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800112{
113 u_int len = length;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700114 uint16_t flags, prot;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800115
116 flags = EXTRACT_16BITS(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700117 if (ndo->ndo_vflag)
118 ND_PRINT((ndo, ", Flags [%s]",
119 bittok2str(gre_flag_values,"none",flags)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800120
121 len -= 2;
122 bp += 2;
123
124 if (len < 2)
125 goto trunc;
126 prot = EXTRACT_16BITS(bp);
127 len -= 2;
128 bp += 2;
129
130 if ((flags & GRE_CP) | (flags & GRE_RP)) {
131 if (len < 2)
132 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700133 if (ndo->ndo_vflag)
134 ND_PRINT((ndo, ", sum 0x%x", EXTRACT_16BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800135 bp += 2;
136 len -= 2;
137
138 if (len < 2)
139 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700140 ND_PRINT((ndo, ", off 0x%x", EXTRACT_16BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800141 bp += 2;
142 len -= 2;
143 }
144
145 if (flags & GRE_KP) {
146 if (len < 4)
147 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700148 ND_PRINT((ndo, ", key=0x%x", EXTRACT_32BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800149 bp += 4;
150 len -= 4;
151 }
152
153 if (flags & GRE_SP) {
154 if (len < 4)
155 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700156 ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800157 bp += 4;
158 len -= 4;
159 }
160
161 if (flags & GRE_RP) {
162 for (;;) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700163 uint16_t af;
164 uint8_t sreoff;
165 uint8_t srelen;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800166
167 if (len < 4)
168 goto trunc;
169 af = EXTRACT_16BITS(bp);
170 sreoff = *(bp + 2);
171 srelen = *(bp + 3);
172 bp += 4;
173 len -= 4;
174
175 if (af == 0 && srelen == 0)
176 break;
177
Elliott Hughes892a68b2015-10-19 14:43:53 -0700178 gre_sre_print(ndo, af, sreoff, srelen, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800179
180 if (len < srelen)
181 goto trunc;
182 bp += srelen;
183 len -= srelen;
184 }
185 }
186
Elliott Hughes892a68b2015-10-19 14:43:53 -0700187 if (ndo->ndo_eflag)
188 ND_PRINT((ndo, ", proto %s (0x%04x)",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800189 tok2str(ethertype_values,"unknown",prot),
Elliott Hughes892a68b2015-10-19 14:43:53 -0700190 prot));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800191
Elliott Hughes892a68b2015-10-19 14:43:53 -0700192 ND_PRINT((ndo, ", length %u",length));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800193
Elliott Hughes892a68b2015-10-19 14:43:53 -0700194 if (ndo->ndo_vflag < 1)
195 ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800196 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700197 ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800198
199 switch (prot) {
200 case ETHERTYPE_IP:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700201 ip_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800202 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800203 case ETHERTYPE_IPV6:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700204 ip6_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800205 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800206 case ETHERTYPE_MPLS:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700207 mpls_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800208 break;
209 case ETHERTYPE_IPX:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700210 ipx_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800211 break;
212 case ETHERTYPE_ATALK:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700213 atalk_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800214 break;
215 case ETHERTYPE_GRE_ISO:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700216 isoclns_print(ndo, bp, len, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800217 break;
JP Abgrall53f17a92014-02-12 14:02:41 -0800218 case ETHERTYPE_TEB:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700219 ether_print(ndo, bp, len, len, NULL, NULL);
JP Abgrall53f17a92014-02-12 14:02:41 -0800220 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800221 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700222 ND_PRINT((ndo, "gre-proto-0x%x", prot));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800223 }
224 return;
225
226trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700227 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800228}
229
Elliott Hughes892a68b2015-10-19 14:43:53 -0700230static void
231gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800232{
233 u_int len = length;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700234 uint16_t flags, prot;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800235
236 flags = EXTRACT_16BITS(bp);
237 len -= 2;
238 bp += 2;
239
Elliott Hughes892a68b2015-10-19 14:43:53 -0700240 if (ndo->ndo_vflag)
241 ND_PRINT((ndo, ", Flags [%s]",
242 bittok2str(gre_flag_values,"none",flags)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800243
244 if (len < 2)
245 goto trunc;
246 prot = EXTRACT_16BITS(bp);
247 len -= 2;
248 bp += 2;
249
250
251 if (flags & GRE_KP) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700252 uint32_t k;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800253
254 if (len < 4)
255 goto trunc;
256 k = EXTRACT_32BITS(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700257 ND_PRINT((ndo, ", call %d", k & 0xffff));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800258 len -= 4;
259 bp += 4;
260 }
261
262 if (flags & GRE_SP) {
263 if (len < 4)
264 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700265 ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800266 bp += 4;
267 len -= 4;
268 }
269
270 if (flags & GRE_AP) {
271 if (len < 4)
272 goto trunc;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700273 ND_PRINT((ndo, ", ack %u", EXTRACT_32BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800274 bp += 4;
275 len -= 4;
276 }
277
278 if ((flags & GRE_SP) == 0)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700279 ND_PRINT((ndo, ", no-payload"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800280
Elliott Hughes892a68b2015-10-19 14:43:53 -0700281 if (ndo->ndo_eflag)
282 ND_PRINT((ndo, ", proto %s (0x%04x)",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800283 tok2str(ethertype_values,"unknown",prot),
Elliott Hughes892a68b2015-10-19 14:43:53 -0700284 prot));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800285
Elliott Hughes892a68b2015-10-19 14:43:53 -0700286 ND_PRINT((ndo, ", length %u",length));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800287
288 if ((flags & GRE_SP) == 0)
289 return;
290
Elliott Hughes892a68b2015-10-19 14:43:53 -0700291 if (ndo->ndo_vflag < 1)
292 ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800293 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700294 ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */
The Android Open Source Project2949f582009-03-03 19:30:46 -0800295
296 switch (prot) {
297 case ETHERTYPE_PPP:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700298 ppp_print(ndo, bp, len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800299 break;
300 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700301 ND_PRINT((ndo, "gre-proto-0x%x", prot));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800302 break;
303 }
304 return;
305
306trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700307 ND_PRINT((ndo, "%s", tstr));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800308}
309
Elliott Hughes892a68b2015-10-19 14:43:53 -0700310static void
311gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff,
312 uint8_t srelen, const u_char *bp, u_int len)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800313{
314 switch (af) {
315 case GRESRE_IP:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700316 ND_PRINT((ndo, ", (rtaf=ip"));
317 gre_sre_ip_print(ndo, sreoff, srelen, bp, len);
318 ND_PRINT((ndo, ") "));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800319 break;
320 case GRESRE_ASN:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700321 ND_PRINT((ndo, ", (rtaf=asn"));
322 gre_sre_asn_print(ndo, sreoff, srelen, bp, len);
323 ND_PRINT((ndo, ") "));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800324 break;
325 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700326 ND_PRINT((ndo, ", (rtaf=0x%x) ", af));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800327 }
328}
Elliott Hughes892a68b2015-10-19 14:43:53 -0700329
330static void
331gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
332 const u_char *bp, u_int len)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800333{
334 struct in_addr a;
335 const u_char *up = bp;
336
337 if (sreoff & 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700338 ND_PRINT((ndo, ", badoffset=%u", sreoff));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800339 return;
340 }
341 if (srelen & 3) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700342 ND_PRINT((ndo, ", badlength=%u", srelen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800343 return;
344 }
345 if (sreoff >= srelen) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700346 ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800347 return;
348 }
349
350 for (;;) {
351 if (len < 4 || srelen == 0)
352 return;
353
354 memcpy(&a, bp, sizeof(a));
Elliott Hughes892a68b2015-10-19 14:43:53 -0700355 ND_PRINT((ndo, " %s%s",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800356 ((bp - up) == sreoff) ? "*" : "",
Elliott Hughes892a68b2015-10-19 14:43:53 -0700357 inet_ntoa(a)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800358
359 bp += 4;
360 len -= 4;
361 srelen -= 4;
362 }
363}
364
Elliott Hughes892a68b2015-10-19 14:43:53 -0700365static void
366gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
367 const u_char *bp, u_int len)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800368{
369 const u_char *up = bp;
370
371 if (sreoff & 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700372 ND_PRINT((ndo, ", badoffset=%u", sreoff));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800373 return;
374 }
375 if (srelen & 1) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700376 ND_PRINT((ndo, ", badlength=%u", srelen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800377 return;
378 }
379 if (sreoff >= srelen) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700380 ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800381 return;
382 }
383
384 for (;;) {
385 if (len < 2 || srelen == 0)
386 return;
387
Elliott Hughes892a68b2015-10-19 14:43:53 -0700388 ND_PRINT((ndo, " %s%x",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800389 ((bp - up) == sreoff) ? "*" : "",
Elliott Hughes892a68b2015-10-19 14:43:53 -0700390 EXTRACT_16BITS(bp)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800391
392 bp += 2;
393 len -= 2;
394 srelen -= 2;
395 }
396}