GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-gre.c Lines: 0 182 0.0 %
Date: 2017-11-07 Branches: 0 107 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-gre.c,v 1.12 2016/12/13 06:40:21 dlg 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/time.h>
35
#include <sys/uio.h>
36
#include <sys/socket.h>
37
38
#include <netinet/in.h>
39
#include <netinet/ip.h>
40
#include <arpa/inet.h>
41
42
#include <net/ethertypes.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
/* source route entry types */
61
#define	GRESRE_IP	0x0800		/* IP */
62
#define	GRESRE_ASN	0xfffe		/* ASN */
63
64
#define NVGRE_VSID_MASK		0xffffff00U
65
#define NVGRE_VSID_SHIFT	8
66
#define NVGRE_FLOWID_MASK	0x000000ffU
67
#define NVGRE_FLOWID_SHIFT	0
68
69
void gre_print_0(const u_char *, u_int);
70
void gre_print_1(const u_char *, u_int);
71
void gre_sre_print(u_int16_t, u_int8_t, u_int8_t, const u_char *, u_int);
72
void gre_sre_ip_print(u_int8_t, u_int8_t, const u_char *, u_int);
73
void gre_sre_asn_print(u_int8_t, u_int8_t, const u_char *, u_int);
74
75
void
76
gre_print(const u_char *bp, u_int length)
77
{
78
	u_int len = length, vers;
79
80
	if (bp + len > snapend)
81
		len = snapend - bp;
82
83
	if (len < 2) {
84
		printf("[|gre]");
85
		return;
86
	}
87
	vers = EXTRACT_16BITS(bp) & GRE_VERS;
88
89
	switch (vers) {
90
	case 0:
91
		gre_print_0(bp, len);
92
		break;
93
	case 1:
94
		gre_print_1(bp, len);
95
		break;
96
	default:
97
		printf("gre-unknown-version=%u", vers);
98
		break;
99
	}
100
}
101
102
void
103
gre_print_0(const u_char *bp, u_int length)
104
{
105
	u_int len = length;
106
	u_int16_t flags, prot;
107
108
	flags = EXTRACT_16BITS(bp);
109
	if (vflag) {
110
		printf("[%s%s%s%s%s] ",
111
		    (flags & GRE_CP) ? "C" : "",
112
		    (flags & GRE_RP) ? "R" : "",
113
		    (flags & GRE_KP) ? "K" : "",
114
		    (flags & GRE_SP) ? "S" : "",
115
		    (flags & GRE_sP) ? "s" : "");
116
	}
117
118
	len -= 2;
119
	bp += 2;
120
121
	if (len < 2)
122
		goto trunc;
123
	prot = EXTRACT_16BITS(bp);
124
	printf("%s", etherproto_string(prot));
125
126
	len -= 2;
127
	bp += 2;
128
129
	if ((flags & GRE_CP) | (flags & GRE_RP)) {
130
		if (len < 2)
131
			goto trunc;
132
		if (vflag)
133
			printf(" sum 0x%x", EXTRACT_16BITS(bp));
134
		bp += 2;
135
		len -= 2;
136
137
		if (len < 2)
138
			goto trunc;
139
		printf(" off 0x%x", EXTRACT_16BITS(bp));
140
		bp += 2;
141
		len -= 2;
142
	}
143
144
	if (flags & GRE_KP) {
145
		uint32_t key, vsid;
146
147
		if (len < 4)
148
			goto trunc;
149
		key = EXTRACT_32BITS(bp);
150
151
		/* maybe NVGRE? */
152
		if (flags == (GRE_KP | 0) && prot == ETHERTYPE_TRANSETHER) {
153
			vsid = (key & NVGRE_VSID_MASK) >> NVGRE_VSID_SHIFT;
154
			printf(" NVGRE vsid=%u (0x%x)+flowid=0x%02x /",
155
			    vsid, vsid,
156
			    (key & NVGRE_FLOWID_MASK) >> NVGRE_FLOWID_SHIFT);
157
		}
158
		printf(" key=%u (0x%x)", key, key);
159
		bp += 4;
160
		len -= 4;
161
	}
162
163
	if (flags & GRE_SP) {
164
		if (len < 4)
165
			goto trunc;
166
		printf(" seq %u", EXTRACT_32BITS(bp));
167
		bp += 4;
168
		len -= 4;
169
	}
170
171
	if (flags & GRE_RP) {
172
		for (;;) {
173
			u_int16_t af;
174
			u_int8_t sreoff;
175
			u_int8_t srelen;
176
177
			if (len < 4)
178
				goto trunc;
179
			af = EXTRACT_16BITS(bp);
180
			sreoff = *(bp + 2);
181
			srelen = *(bp + 3);
182
			bp += 4;
183
			len -= 4;
184
185
			if (af == 0 && srelen == 0)
186
				break;
187
188
			gre_sre_print(af, sreoff, srelen, bp, len);
189
190
			if (len < srelen)
191
				goto trunc;
192
			bp += srelen;
193
			len -= srelen;
194
		}
195
	}
196
197
	printf(": ");
198
199
	switch (prot) {
200
	case ETHERTYPE_IP:
201
		ip_print(bp, len);
202
		break;
203
	case ETHERTYPE_IPV6:
204
		ip6_print(bp, len);
205
		break;
206
	case ETHERTYPE_MPLS:
207
		mpls_print(bp, len);
208
		break;
209
	case ETHERTYPE_TRANSETHER:
210
		ether_print(bp, len);
211
		break;
212
	default:
213
		printf("gre-proto-0x%x", prot);
214
	}
215
	return;
216
217
trunc:
218
	printf("[|gre]");
219
}
220
221
void
222
gre_print_1(const u_char *bp, u_int length)
223
{
224
	u_int len = length;
225
	u_int16_t flags, prot;
226
227
	flags = EXTRACT_16BITS(bp);
228
	len -= 2;
229
	bp += 2;
230
231
	if (vflag) {
232
		printf("[%s%s%s%s%s%s]",
233
		    (flags & GRE_CP) ? "C" : "",
234
		    (flags & GRE_RP) ? "R" : "",
235
		    (flags & GRE_KP) ? "K" : "",
236
		    (flags & GRE_SP) ? "S" : "",
237
		    (flags & GRE_sP) ? "s" : "",
238
		    (flags & GRE_AP) ? "A" : "");
239
	}
240
241
	if (len < 2)
242
		goto trunc;
243
	prot = EXTRACT_16BITS(bp);
244
	len -= 2;
245
	bp += 2;
246
247
	if (flags & GRE_CP) {
248
		printf(" cpset!");
249
		return;
250
	}
251
	if (flags & GRE_RP) {
252
		printf(" rpset!");
253
		return;
254
	}
255
	if ((flags & GRE_KP) == 0) {
256
		printf(" kpunset!");
257
		return;
258
	}
259
	if (flags & GRE_sP) {
260
		printf(" spset!");
261
		return;
262
	}
263
264
	if (flags & GRE_KP) {
265
		u_int32_t k;
266
267
		if (len < 4)
268
			goto trunc;
269
		k = EXTRACT_32BITS(bp);
270
		printf(" call %d", k & 0xffff);
271
		len -= 4;
272
		bp += 4;
273
	}
274
275
	if (flags & GRE_SP) {
276
		if (len < 4)
277
			goto trunc;
278
		printf(" seq %u", EXTRACT_32BITS(bp));
279
		bp += 4;
280
		len -= 4;
281
	}
282
283
	if (flags & GRE_AP) {
284
		if (len < 4)
285
			goto trunc;
286
		printf(" ack %u", EXTRACT_32BITS(bp));
287
		bp += 4;
288
		len -= 4;
289
	}
290
291
	if ((flags & GRE_SP) == 0) {
292
		printf(" no-payload");
293
		return;
294
	}
295
296
	printf(": ");
297
298
	switch (prot) {
299
	case ETHERTYPE_PPP:
300
		printf("gre-ppp-payload");
301
		break;
302
	default:
303
		printf("gre-proto-0x%x", prot);
304
		break;
305
	}
306
	return;
307
308
trunc:
309
	printf("[|gre]");
310
}
311
312
void
313
gre_sre_print(u_int16_t af, u_int8_t sreoff, u_int8_t srelen,
314
    const u_char *bp, u_int len)
315
{
316
	switch (af) {
317
	case GRESRE_IP:
318
		printf(" (rtaf=ip");
319
		gre_sre_ip_print(sreoff, srelen, bp, len);
320
		printf(")");
321
		break;
322
	case GRESRE_ASN:
323
		printf(" (rtaf=asn");
324
		gre_sre_asn_print(sreoff, srelen, bp, len);
325
		printf(")");
326
		break;
327
	default:
328
		printf(" (rtaf=0x%x)", af);
329
	}
330
}
331
void
332
gre_sre_ip_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
333
{
334
	struct in_addr a;
335
	const u_char *up = bp;
336
337
	if (sreoff & 3) {
338
		printf(" badoffset=%u", sreoff);
339
		return;
340
	}
341
	if (srelen & 3) {
342
		printf(" badlength=%u", srelen);
343
		return;
344
	}
345
	if (sreoff >= srelen) {
346
		printf(" badoff/len=%u/%u", sreoff, srelen);
347
		return;
348
	}
349
350
	for (;;) {
351
		if (len < 4 || srelen == 0)
352
			return;
353
354
		memcpy(&a, bp, sizeof(a));
355
		printf(" %s%s",
356
		    ((bp - up) == sreoff) ? "*" : "",
357
		    inet_ntoa(a));
358
359
		bp += 4;
360
		len -= 4;
361
		srelen -= 4;
362
	}
363
}
364
365
void
366
gre_sre_asn_print(u_int8_t sreoff, u_int8_t srelen, const u_char *bp, u_int len)
367
{
368
	const u_char *up = bp;
369
370
	if (sreoff & 1) {
371
		printf(" badoffset=%u", sreoff);
372
		return;
373
	}
374
	if (srelen & 1) {
375
		printf(" badlength=%u", srelen);
376
		return;
377
	}
378
	if (sreoff >= srelen) {
379
		printf(" badoff/len=%u/%u", sreoff, srelen);
380
		return;
381
	}
382
383
	for (;;) {
384
		if (len < 2 || srelen == 0)
385
			return;
386
387
		printf(" %s%x",
388
		    ((bp - up) == sreoff) ? "*" : "",
389
		    EXTRACT_16BITS(bp));
390
391
		bp += 2;
392
		len -= 2;
393
		srelen -= 2;
394
	}
395
}