xref: /openbsd-src/usr.sbin/tcpdump/print-gre.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: print-gre.c,v 1.2 2000/10/03 14:31:57 ho Exp $	*/
2 
3 /*
4  * Copyright (c) 1996
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by the University of California, Lawrence Berkeley Laboratory,
13  * Berkeley, CA.  The name of the University may not be used to
14  * endorse or promote products derived from this software without
15  * specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  * Initial contribution from John Hawkinson <jhawk@bbnplanet.com>
21  *
22  * This module implements support for decoding GRE (Generic Routing
23  * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702.
24  * This code only supports the IP encapsulation thereof.
25  */
26 
27 #ifndef lint
28 static const char rcsid[] =
29     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-gre.c,v 1.2 2000/10/03 14:31:57 ho Exp $";
30 #endif
31 
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/uio.h>
35 #include <sys/socket.h>
36 
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
39 #include <netinet/ip.h>
40 
41 #include <netdb.h>
42 #include <stdio.h>
43 
44 #include "interface.h"
45 #include "addrtoname.h"
46 #include "extract.h"		/* must come after interface.h */
47 
48 #define GRE_SIZE (20)
49 
50 struct gre {
51 	u_short flags;
52 	u_short proto;
53 	union {
54 		struct gre_ckof {
55 			u_short cksum;
56 			u_short offset;
57 		}        gre_ckof;
58 		u_int32_t key;
59 		u_int32_t seq;
60 	}     gre_void1;
61 	union {
62 		u_int32_t key;
63 		u_int32_t seq;
64 		u_int32_t routing;
65 	}     gre_void2;
66 	union {
67 		u_int32_t seq;
68 		u_int32_t routing;
69 	}     gre_void3;
70 	union {
71 		u_int32_t routing;
72 	}     gre_void4;
73 };
74 
75 #define GRE_CP		0x8000	/* Checksum Present */
76 #define GRE_RP		0x4000	/* Routing Present */
77 #define GRE_KP		0x2000	/* Key Present */
78 #define GRE_SP		0x1000	/* Sequence Present */
79 
80 
81 #define GREPROTO_IP	0x0800
82 
83 
84 /*
85  * Deencapsulate and print a GRE-tunneled IP datagram
86  */
87 void
88 gre_print(const u_char *bp, u_int length)
89 {
90 	const u_char *cp = bp + 4;
91 	const struct gre *gre;
92 	u_short flags, proto;
93 
94 	gre = (const struct gre *)bp;
95 
96 	if (length < GRE_SIZE) {
97 		goto trunc;
98 	}
99 	flags = EXTRACT_16BITS(&gre->flags);
100 	proto = EXTRACT_16BITS(&gre->proto);
101 
102 	if (vflag) {
103 		/* Decode the flags */
104 		putchar('[');
105 		if (flags & GRE_CP)
106 			putchar('C');
107 		if (flags & GRE_RP)
108 			putchar('R');
109 		if (flags & GRE_KP)
110 			putchar('K');
111 		if (flags & GRE_SP)
112 			putchar('S');
113 		fputs("] ", stdout);
114 	}
115 	/* Checksum & Offset are present */
116 	if ((flags & GRE_CP) | (flags & GRE_RP))
117 		cp += 4;
118 
119 	/* We don't support routing fields (variable length) now. Punt. */
120 	if (flags & GRE_RP)
121 		return;
122 
123 	if (flags & GRE_KP)
124 		cp += 4;
125 	if (flags & GRE_SP)
126 		cp += 4;
127 
128 	switch (proto) {
129 
130 	case GREPROTO_IP:
131 		ip_print(cp, length - ((cp - bp) / sizeof(u_char)));
132 		break;
133 
134 	default:
135 		printf("gre-proto-0x%04X", proto);
136 		break;
137 	}
138 	return;
139 
140 trunc:
141 	fputs("[|gre]", stdout);
142 
143 }
144