xref: /netbsd/external/bsd/tcpdump/dist/print-gre.c (revision 6550d01e)
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 /*
35  * tcpdump filter for GRE - Generic Routing Encapsulation
36  * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
37  */
38 
39 #include <sys/cdefs.h>
40 #ifndef lint
41 #if 0
42 static const char rcsid[] _U_ =
43     "@(#) Header: /tcpdump/master/tcpdump/print-gre.c,v 1.28 2005-04-06 21:32:39 mcr Exp (LBL)";
44 #else
45 __RCSID("$NetBSD: print-gre.c,v 1.2 2010/12/05 05:11:30 christos Exp $");
46 #endif
47 #endif
48 
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52 
53 #include <tcpdump-stdinc.h>
54 
55 #include <stdio.h>
56 #include <string.h>
57 
58 #include "interface.h"
59 #include "addrtoname.h"
60 #include "extract.h"
61 
62 #include "ip.h"
63 #include "ethertype.h"
64 
65 #define	GRE_CP		0x8000		/* checksum present */
66 #define	GRE_RP		0x4000		/* routing present */
67 #define	GRE_KP		0x2000		/* key present */
68 #define	GRE_SP		0x1000		/* sequence# present */
69 #define	GRE_sP		0x0800		/* source routing */
70 #define	GRE_RECRS	0x0700		/* recursion count */
71 #define	GRE_AP		0x0080		/* acknowledgment# present */
72 
73 struct tok gre_flag_values[] = {
74     { GRE_CP, "checksum present"},
75     { GRE_RP, "routing present"},
76     { GRE_KP, "key present"},
77     { GRE_SP, "sequence# present"},
78     { GRE_sP, "source routing present"},
79     { GRE_RECRS, "recursion count"},
80     { GRE_AP, "ack present"},
81     { 0, NULL }
82 };
83 
84 #define	GRE_VERS_MASK	0x0007		/* protocol version */
85 
86 /* source route entry types */
87 #define	GRESRE_IP	0x0800		/* IP */
88 #define	GRESRE_ASN	0xfffe		/* ASN */
89 
90 void gre_print_0(const u_char *, u_int);
91 void gre_print_1(const u_char *, u_int);
92 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int);
93 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int);
94 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int);
95 
96 void
97 gre_print(const u_char *bp, u_int length)
98 {
99 	u_int len = length, vers;
100 
101 	if (len < 2) {
102 		printf("[|gre]");
103 		return;
104 	}
105 	vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK;
106         printf("GREv%u",vers);
107 
108         switch(vers) {
109         case 0:
110             gre_print_0(bp, len);
111             break;
112         case 1:
113             gre_print_1(bp, len);
114             break;
115 	default:
116             printf(" ERROR: unknown-version");
117             break;
118         }
119 	return;
120 
121 }
122 
123 void
124 gre_print_0(const u_char *bp, u_int length)
125 {
126 	u_int len = length;
127 	u_int16_t flags, prot;
128 
129 	flags = EXTRACT_16BITS(bp);
130         if (vflag)
131             printf(", Flags [%s]",
132                    bittok2str(gre_flag_values,"none",flags));
133 
134 	len -= 2;
135 	bp += 2;
136 
137 	if (len < 2)
138 		goto trunc;
139 	prot = EXTRACT_16BITS(bp);
140 	len -= 2;
141 	bp += 2;
142 
143 	if ((flags & GRE_CP) | (flags & GRE_RP)) {
144 		if (len < 2)
145 			goto trunc;
146 		if (vflag)
147 			printf(", sum 0x%x", EXTRACT_16BITS(bp));
148 		bp += 2;
149 		len -= 2;
150 
151 		if (len < 2)
152 			goto trunc;
153 		printf(", off 0x%x", EXTRACT_16BITS(bp));
154 		bp += 2;
155 		len -= 2;
156 	}
157 
158 	if (flags & GRE_KP) {
159 		if (len < 4)
160 			goto trunc;
161 		printf(", key=0x%x", EXTRACT_32BITS(bp));
162 		bp += 4;
163 		len -= 4;
164 	}
165 
166 	if (flags & GRE_SP) {
167 		if (len < 4)
168 			goto trunc;
169 		printf(", seq %u", EXTRACT_32BITS(bp));
170 		bp += 4;
171 		len -= 4;
172 	}
173 
174 	if (flags & GRE_RP) {
175 		for (;;) {
176 			u_int16_t af;
177 			u_int8_t sreoff;
178 			u_int8_t srelen;
179 
180 			if (len < 4)
181 				goto trunc;
182 			af = EXTRACT_16BITS(bp);
183 			sreoff = *(bp + 2);
184 			srelen = *(bp + 3);
185 			bp += 4;
186 			len -= 4;
187 
188 			if (af == 0 && srelen == 0)
189 				break;
190 
191 			gre_sre_print(af, sreoff, srelen, bp, len);
192 
193 			if (len < srelen)
194 				goto trunc;
195 			bp += srelen;
196 			len -= srelen;
197 		}
198 	}
199 
200         if (eflag)
201             printf(", proto %s (0x%04x)",
202                    tok2str(ethertype_values,"unknown",prot),
203                    prot);
204 
205         printf(", length %u",length);
206 
207         if (vflag < 1)
208             printf(": "); /* put in a colon as protocol demarc */
209         else
210             printf("\n\t"); /* if verbose go multiline */
211 
212 	switch (prot) {
213 	case ETHERTYPE_IP:
214 	        ip_print(gndo, bp, len);
215 		break;
216 #ifdef INET6
217 	case ETHERTYPE_IPV6:
218 		ip6_print(bp, len);
219 		break;
220 #endif
221 	case ETHERTYPE_MPLS:
222 		mpls_print(bp, len);
223 		break;
224 	case ETHERTYPE_IPX:
225 		ipx_print(bp, len);
226 		break;
227 	case ETHERTYPE_ATALK:
228 		atalk_print(bp, len);
229 		break;
230 	case ETHERTYPE_GRE_ISO:
231 		isoclns_print(bp, len, len);
232 		break;
233 	case ETHERTYPE_TEB:
234 		ether_print(bp, len, len, NULL, NULL);
235 		break;
236 	default:
237 		printf("gre-proto-0x%x", prot);
238 	}
239 	return;
240 
241 trunc:
242 	printf("[|gre]");
243 }
244 
245 void
246 gre_print_1(const u_char *bp, u_int length)
247 {
248 	u_int len = length;
249 	u_int16_t flags, prot;
250 
251 	flags = EXTRACT_16BITS(bp);
252 	len -= 2;
253 	bp += 2;
254 
255 	if (vflag)
256             printf(", Flags [%s]",
257                    bittok2str(gre_flag_values,"none",flags));
258 
259 	if (len < 2)
260 		goto trunc;
261 	prot = EXTRACT_16BITS(bp);
262 	len -= 2;
263 	bp += 2;
264 
265 
266 	if (flags & GRE_KP) {
267 		u_int32_t k;
268 
269 		if (len < 4)
270 			goto trunc;
271 		k = EXTRACT_32BITS(bp);
272 		printf(", call %d", k & 0xffff);
273 		len -= 4;
274 		bp += 4;
275 	}
276 
277 	if (flags & GRE_SP) {
278 		if (len < 4)
279 			goto trunc;
280 		printf(", seq %u", EXTRACT_32BITS(bp));
281 		bp += 4;
282 		len -= 4;
283 	}
284 
285 	if (flags & GRE_AP) {
286 		if (len < 4)
287 			goto trunc;
288 		printf(", ack %u", EXTRACT_32BITS(bp));
289 		bp += 4;
290 		len -= 4;
291 	}
292 
293 	if ((flags & GRE_SP) == 0)
294 		printf(", no-payload");
295 
296         if (eflag)
297             printf(", proto %s (0x%04x)",
298                    tok2str(ethertype_values,"unknown",prot),
299                    prot);
300 
301         printf(", length %u",length);
302 
303         if ((flags & GRE_SP) == 0)
304             return;
305 
306         if (vflag < 1)
307             printf(": "); /* put in a colon as protocol demarc */
308         else
309             printf("\n\t"); /* if verbose go multiline */
310 
311 	switch (prot) {
312 	case ETHERTYPE_PPP:
313                 ppp_print(bp, len);
314 		break;
315 	default:
316 		printf("gre-proto-0x%x", prot);
317 		break;
318 	}
319 	return;
320 
321 trunc:
322 	printf("[|gre]");
323 }
324 
325 void
326 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen,
327     const u_char *bp, u_int len)
328 {
329 	switch (af) {
330 	case GRESRE_IP:
331 		printf(", (rtaf=ip");
332 		gre_sre_ip_print(sreoff, srelen, bp, len);
333 		printf(") ");
334 		break;
335 	case GRESRE_ASN:
336 		printf(", (rtaf=asn");
337 		gre_sre_asn_print(sreoff, srelen, bp, len);
338 		printf(") ");
339 		break;
340 	default:
341 		printf(", (rtaf=0x%x) ", af);
342 	}
343 }
344 void
345 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
346 {
347 	struct in_addr a;
348 	const u_char *up = bp;
349 
350 	if (sreoff & 3) {
351 		printf(", badoffset=%u", sreoff);
352 		return;
353 	}
354 	if (srelen & 3) {
355 		printf(", badlength=%u", srelen);
356 		return;
357 	}
358 	if (sreoff >= srelen) {
359 		printf(", badoff/len=%u/%u", sreoff, srelen);
360 		return;
361 	}
362 
363 	for (;;) {
364 		if (len < 4 || srelen == 0)
365 			return;
366 
367 		memcpy(&a, bp, sizeof(a));
368 		printf(" %s%s",
369 		    ((bp - up) == sreoff) ? "*" : "",
370 		    inet_ntoa(a));
371 
372 		bp += 4;
373 		len -= 4;
374 		srelen -= 4;
375 	}
376 }
377 
378 void
379 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
380 {
381 	const u_char *up = bp;
382 
383 	if (sreoff & 1) {
384 		printf(", badoffset=%u", sreoff);
385 		return;
386 	}
387 	if (srelen & 1) {
388 		printf(", badlength=%u", srelen);
389 		return;
390 	}
391 	if (sreoff >= srelen) {
392 		printf(", badoff/len=%u/%u", sreoff, srelen);
393 		return;
394 	}
395 
396 	for (;;) {
397 		if (len < 2 || srelen == 0)
398 			return;
399 
400 		printf(" %s%x",
401 		    ((bp - up) == sreoff) ? "*" : "",
402 		    EXTRACT_16BITS(bp));
403 
404 		bp += 2;
405 		len -= 2;
406 		srelen -= 2;
407 	}
408 }
409