]> The Tcpdump Group git mirrors - tcpdump/blob - print-gre.c
Get rid of unneeded includes of <netinet/in_systm.h> and <netinet/ip.h>.
[tcpdump] / print-gre.c
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.14 2002-06-01 23:50:31 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 }