xref: /freebsd/contrib/tcpdump/print-gre.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
1 /*
2  * Copyright (c) 1996
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Lawrence Berkeley Laboratory,
11  * Berkeley, CA.  The name of the University may not be used to
12  * endorse or promote products derived from this software without
13  * specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Initial contribution from John Hawkinson <jhawk@bbnplanet.com>
19  *
20  * This module implements support for decoding GRE (Generic Routing
21  * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702.
22  * This code only supports the IP encapsulation thereof.
23  */
24 
25 #ifndef lint
26 static const char rcsid[] =
27     "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.13.4.1 2002/06/01 23:51:13 guy Exp $";
28 #endif
29 
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33 
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <sys/socket.h>
37 
38 #include <netinet/in.h>
39 
40 #include <netdb.h>
41 #include <stdio.h>
42 
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "extract.h"		/* must come after interface.h */
46 
47 struct gre {
48 	u_int16_t flags;
49 	u_int16_t proto;
50 };
51 
52 /* RFC 2784 - GRE */
53 #define GRE_CP		0x8000	/* Checksum Present */
54 #define GRE_VER_MASK	0x0007	/* Version */
55 
56 /* RFC 2890 - Key and Sequence extensions to GRE */
57 #define GRE_KP		0x2000	/* Key Present */
58 #define GRE_SP		0x1000	/* Sequence Present */
59 
60 /* Legacy from RFC 1700 */
61 #define GRE_RP		0x4000	/* Routing Present */
62 #define GRE_sP		0x0800	/* strict source route present */
63 #define GRE_RECUR_MASK	0x0700  /* Recursion Control */
64 #define GRE_RECUR_SHIFT	8
65 
66 #define GRE_COP		(GRE_RP|GRE_CP)	/* Checksum & Offset Present */
67 
68 /* "Enhanced GRE" from RFC2637 - PPTP */
69 #define GRE_AP		0x0080	/* Ack present */
70 
71 #define GRE_MBZ_MASK	0x0078	/* not defined */
72 
73 /*
74  * Deencapsulate and print a GRE-tunneled IP datagram
75  */
76 void
77 gre_print(const u_char *bp, u_int length)
78 {
79 	const u_char *cp = bp + 4;
80 	const struct gre *gre;
81 	u_int16_t flags, proto;
82 	u_short ver=0;
83 	u_short extracted_ethertype;
84 
85 	gre = (const struct gre *)bp;
86 
87 	TCHECK(gre->proto);
88 	flags = EXTRACT_16BITS(&gre->flags);
89 	proto = EXTRACT_16BITS(&gre->proto);
90 	(void)printf("gre ");
91 
92 	if (flags) {
93 		/* Decode the flags */
94 		putchar('[');
95 		if (flags & GRE_CP)
96 			putchar('C');
97 		if (flags & GRE_RP)
98 			putchar('R');
99 		if (flags & GRE_KP)
100 			putchar('K');
101 		if (flags & GRE_SP)
102 			putchar('S');
103 		if (flags & GRE_sP)
104 			putchar('s');
105 		if (flags & GRE_AP)
106 			putchar('A');
107 		if (flags & GRE_RECUR_MASK)
108 			printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT);
109 		ver = flags & GRE_VER_MASK;
110 		printf("v%u", ver);
111 
112 		if (flags & GRE_MBZ_MASK)
113 			printf("!%x", flags & GRE_MBZ_MASK);
114 		fputs("] ", stdout);
115 	}
116 
117 	if (flags & GRE_COP) {
118 		int checksum, offset;
119 
120 		TCHECK2(*cp, 4);
121 		checksum = EXTRACT_16BITS(cp);
122 		offset = EXTRACT_16BITS(cp + 2);
123 
124 		if (flags & GRE_CP) {
125 			/* Checksum present */
126 
127 			/* todo: check checksum */
128 			if (vflag > 1)
129 				printf("C:%04x ", checksum);
130 		}
131 		if (flags & GRE_RP) {
132 			/* Offset present */
133 
134 			if (vflag > 1)
135 				printf("O:%04x ", offset);
136 		}
137 		cp += 4;	/* skip checksum and offset */
138 	}
139 	if (flags & GRE_KP) {
140 		TCHECK2(*cp, 4);
141 		if (ver == 1) { 	/* PPTP */
142 			if (vflag > 1)
143 				printf("PL:%u ", EXTRACT_16BITS(cp));
144 			printf("ID:%04x ", EXTRACT_16BITS(cp+2));
145 		}
146 		else
147 			printf("K:%08x ", EXTRACT_32BITS(cp));
148 		cp += 4;	/* skip key */
149 	}
150 	if (flags & GRE_SP) {
151 		TCHECK2(*cp, 4);
152 		printf("S:%u ", EXTRACT_32BITS(cp));
153 		cp += 4;	/* skip seq */
154 	}
155 	if (flags & GRE_AP && ver >= 1) {
156 		TCHECK2(*cp, 4);
157 		printf("A:%u ", EXTRACT_32BITS(cp));
158 		cp += 4;	/* skip ack */
159 	}
160 	/* We don't support routing fields (variable length) now. Punt. */
161 	if (flags & GRE_RP)
162 		return;
163 
164 	TCHECK(cp[0]);
165 
166 	length -= cp - bp;
167 	if (ether_encap_print(proto, cp, length, length,
168 	    &extracted_ethertype) == 0)
169  		printf("gre-proto-0x%04X", proto);
170 	return;
171 
172 trunc:
173 	fputs("[|gre]", stdout);
174 
175 }
176