xref: /openbsd/usr.sbin/tcpdump/print-gre.c (revision 404b540a)
1 /*	$OpenBSD: print-gre.c,v 1.7 2003/06/03 00:21:04 jason 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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * tcpdump filter for GRE - Generic Routing Encapsulation
31  * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
32  */
33 
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <sys/uio.h>
37 #include <sys/socket.h>
38 
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <arpa/inet.h>
43 
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h"
50 
51 #define	GRE_CP		0x8000		/* checksum present */
52 #define	GRE_RP		0x4000		/* routing present */
53 #define	GRE_KP		0x2000		/* key present */
54 #define	GRE_SP		0x1000		/* sequence# present */
55 #define	GRE_sP		0x0800		/* source routing */
56 #define	GRE_RECRS	0x0700		/* recursion count */
57 #define	GRE_AP		0x0080		/* acknowledgment# present */
58 #define	GRE_VERS	0x0007		/* protocol version */
59 
60 #define	GREPROTO_IP	0x0800		/* IP */
61 #define	GREPROTO_PPP	0x880b		/* PPTP */
62 
63 /* source route entry types */
64 #define	GRESRE_IP	0x0800		/* IP */
65 #define	GRESRE_ASN	0xfffe		/* ASN */
66 
67 void gre_print_0(const u_char *, u_int);
68 void gre_print_1(const u_char *, u_int);
69 void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int);
70 void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int);
71 void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int);
72 
73 void
74 gre_print(const u_char *bp, u_int length)
75 {
76 	u_int len = length, vers;
77 
78 	if (len < 2) {
79 		printf("[|gre]");
80 		return;
81 	}
82 	vers = EXTRACT_16BITS(bp) & 7;
83 
84 	if (vers == 0)
85 		gre_print_0(bp, len);
86 	else if (vers == 1)
87 		gre_print_1(bp, len);
88 	else
89 		printf("gre-unknown-version=%u", vers);
90 	return;
91 
92 }
93 
94 void
95 gre_print_0(const u_char *bp, u_int length)
96 {
97 	u_int len = length;
98 	u_int16_t flags, prot;
99 
100 	flags = EXTRACT_16BITS(bp);
101 	if (vflag) {
102 		printf("[%s%s%s%s%s] ",
103 		    (flags & GRE_CP) ? "C" : "",
104 		    (flags & GRE_RP) ? "R" : "",
105 		    (flags & GRE_KP) ? "K" : "",
106 		    (flags & GRE_SP) ? "S" : "",
107 		    (flags & GRE_sP) ? "s" : "");
108 	}
109 
110 	len -= 2;
111 	bp += 2;
112 
113 	if (len < 2)
114 		goto trunc;
115 	prot = EXTRACT_16BITS(bp);
116 	len -= 2;
117 	bp += 2;
118 
119 	if ((flags & GRE_CP) | (flags & GRE_RP)) {
120 		if (len < 2)
121 			goto trunc;
122 		if (vflag)
123 			printf("sum 0x%x ", EXTRACT_16BITS(bp));
124 		bp += 2;
125 		len -= 2;
126 
127 		if (len < 2)
128 			goto trunc;
129 		printf("off 0x%x ", EXTRACT_16BITS(bp));
130 		bp += 2;
131 		len -= 2;
132 	}
133 
134 	if (flags & GRE_KP) {
135 		if (len < 4)
136 			goto trunc;
137 		printf("key=0x%x ", EXTRACT_32BITS(bp));
138 		bp += 4;
139 		len -= 4;
140 	}
141 
142 	if (flags & GRE_SP) {
143 		if (len < 4)
144 			goto trunc;
145 		printf("seq %u ", EXTRACT_32BITS(bp));
146 		bp += 4;
147 		len -= 4;
148 	}
149 
150 	if (flags & GRE_RP) {
151 		for (;;) {
152 			u_int16_t af;
153 			u_int8_t sreoff;
154 			u_int8_t srelen;
155 
156 			if (len < 4)
157 				goto trunc;
158 			af = EXTRACT_16BITS(bp);
159 			sreoff = *(bp + 2);
160 			srelen = *(bp + 3);
161 			bp += 4;
162 			len -= 4;
163 
164 			if (af == 0 && srelen == 0)
165 				break;
166 
167 			gre_sre_print(af, sreoff, srelen, bp, len);
168 
169 			if (len < srelen)
170 				goto trunc;
171 			bp += srelen;
172 			len -= srelen;
173 		}
174 	}
175 
176 	switch (prot) {
177 	case GREPROTO_IP:
178 		ip_print(bp, len);
179 		break;
180 	default:
181 		printf("gre-proto-0x%x", prot);
182 	}
183 	return;
184 
185 trunc:
186 	printf("[|gre]");
187 }
188 
189 void
190 gre_print_1(const u_char *bp, u_int length)
191 {
192 	u_int len = length;
193 	u_int16_t flags, prot;
194 
195 	flags = EXTRACT_16BITS(bp);
196 	len -= 2;
197 	bp += 2;
198 
199 	if (vflag) {
200 		printf("[%s%s%s%s%s%s] ",
201 		    (flags & GRE_CP) ? "C" : "",
202 		    (flags & GRE_RP) ? "R" : "",
203 		    (flags & GRE_KP) ? "K" : "",
204 		    (flags & GRE_SP) ? "S" : "",
205 		    (flags & GRE_sP) ? "s" : "",
206 		    (flags & GRE_AP) ? "A" : "");
207 	}
208 
209 	if (len < 2)
210 		goto trunc;
211 	prot = EXTRACT_16BITS(bp);
212 	len -= 2;
213 	bp += 2;
214 
215 	if (flags & GRE_CP) {
216 		printf("cpset!");
217 		return;
218 	}
219 	if (flags & GRE_RP) {
220 		printf("rpset!");
221 		return;
222 	}
223 	if ((flags & GRE_KP) == 0) {
224 		printf("kpunset!");
225 		return;
226 	}
227 	if (flags & GRE_sP) {
228 		printf("spset!");
229 		return;
230 	}
231 
232 	if (flags & GRE_KP) {
233 		u_int32_t k;
234 
235 		if (len < 4)
236 			goto trunc;
237 		k = EXTRACT_32BITS(bp);
238 		printf("call %d ", k & 0xffff);
239 		len -= 4;
240 		bp += 4;
241 	}
242 
243 	if (flags & GRE_SP) {
244 		if (len < 4)
245 			goto trunc;
246 		printf("seq %u ", EXTRACT_32BITS(bp));
247 		bp += 4;
248 		len -= 4;
249 	}
250 
251 	if (flags & GRE_AP) {
252 		if (len < 4)
253 			goto trunc;
254 		printf("ack %u ", EXTRACT_32BITS(bp));
255 		bp += 4;
256 		len -= 4;
257 	}
258 
259 	if ((flags & GRE_SP) == 0) {
260 		printf("no-payload");
261 		return;
262 	}
263 
264 	switch (prot) {
265 	case GREPROTO_PPP:
266 		printf("gre-ppp-payload");
267 		break;
268 	default:
269 		printf("gre-proto-0x%x", prot);
270 		break;
271 	}
272 	return;
273 
274 trunc:
275 	printf("[|gre]");
276 }
277 
278 void
279 gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen,
280     const u_char *bp, u_int len)
281 {
282 	switch (af) {
283 	case GRESRE_IP:
284 		printf("(rtaf=ip");
285 		gre_sre_ip_print(sreoff, srelen, bp, len);
286 		printf(") ");
287 		break;
288 	case GRESRE_ASN:
289 		printf("(rtaf=asn");
290 		gre_sre_asn_print(sreoff, srelen, bp, len);
291 		printf(") ");
292 		break;
293 	default:
294 		printf("(rtaf=0x%x) ", af);
295 	}
296 }
297 void
298 gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
299 {
300 	struct in_addr a;
301 	const u_char *up = bp;
302 
303 	if (sreoff & 3) {
304 		printf(" badoffset=%u", sreoff);
305 		return;
306 	}
307 	if (srelen & 3) {
308 		printf(" badlength=%u", srelen);
309 		return;
310 	}
311 	if (sreoff >= srelen) {
312 		printf(" badoff/len=%u/%u", sreoff, srelen);
313 		return;
314 	}
315 
316 	for (;;) {
317 		if (len < 4 || srelen == 0)
318 			return;
319 
320 		memcpy(&a, bp, sizeof(a));
321 		printf(" %s%s",
322 		    ((bp - up) == sreoff) ? "*" : "",
323 		    inet_ntoa(a));
324 
325 		bp += 4;
326 		len -= 4;
327 		srelen -= 4;
328 	}
329 }
330 
331 void
332 gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
333 {
334 	const u_char *up = bp;
335 
336 	if (sreoff & 1) {
337 		printf(" badoffset=%u", sreoff);
338 		return;
339 	}
340 	if (srelen & 1) {
341 		printf(" badlength=%u", srelen);
342 		return;
343 	}
344 	if (sreoff >= srelen) {
345 		printf(" badoff/len=%u/%u", sreoff, srelen);
346 		return;
347 	}
348 
349 	for (;;) {
350 		if (len < 2 || srelen == 0)
351 			return;
352 
353 		printf(" %s%x",
354 		    ((bp - up) == sreoff) ? "*" : "",
355 		    EXTRACT_16BITS(bp));
356 
357 		bp += 2;
358 		len -= 2;
359 		srelen -= 2;
360 	}
361 }
362