]> The Tcpdump Group git mirrors - tcpdump/blob - print-gre.c
Update GRE printer from RFC 2784 (GRE), 2890 (Key and Sequence extensions).
[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.10 2001-02-03 20:21:28 fenner 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/uio.h>
37 #include <sys/socket.h>
38
39 #include <netinet/in.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 /* RFC 2784 - GRE */
76 #define GRE_CP 0x8000 /* Checksum Present */
77 #define GRE_VER_MASK 0x0007 /* Version */
78
79 /* RFC 2890 - Key and Sequence extensions to GRE */
80 #define GRE_KP 0x2000 /* Key Present */
81 #define GRE_SP 0x1000 /* Sequence Present */
82
83 /* Legacy from RFC 1700 */
84 #define GRE_RP 0x4000 /* Routing Present */
85 #define GRE_sP 0x0800 /* strict source route present */
86 #define GRE_RECUR_MASK 0x0700 /* Recursion Control */
87 #define GRE_RECUR_SHIFT 8
88
89 /* "Enhanced GRE" from RFC2637 - PPTP */
90 #define GRE_AP 0x0080 /* Ack present */
91
92 #define GRE_MBZ_MASK 0x0078 /* not defined */
93
94 /*
95 * Deencapsulate and print a GRE-tunneled IP datagram
96 *
97 * XXX PPTP needs to interpret the "key" field...
98 */
99 void
100 gre_print(const u_char *bp, u_int length)
101 {
102 const u_char *cp = bp + 4;
103 const struct gre *gre;
104 u_short flags, proto, extracted_ethertype;
105
106 gre = (const struct gre *)bp;
107
108 TCHECK(gre->proto);
109 flags = EXTRACT_16BITS(&gre->flags);
110 proto = EXTRACT_16BITS(&gre->proto);
111
112 if (flags) {
113 /* Decode the flags */
114 putchar('[');
115 if (flags & GRE_CP)
116 putchar('C');
117 if (flags & GRE_RP)
118 putchar('R');
119 if (flags & GRE_KP)
120 putchar('K');
121 if (flags & GRE_SP)
122 putchar('S');
123 if (flags & GRE_sP)
124 putchar('s');
125 if (flags & GRE_AP)
126 putchar('A');
127 if (flags & GRE_RECUR_MASK)
128 printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT);
129 if (flags & GRE_VER_MASK)
130 printf("v%x", flags & GRE_VER_MASK);
131 if (flags & GRE_MBZ_MASK)
132 printf("!%x", flags & GRE_MBZ_MASK);
133 fputs("] ", stdout);
134 }
135 /* Checksum & Offset are present */
136 if ((flags & GRE_CP) | (flags & GRE_RP))
137 cp += 4;
138
139 /* We don't support routing fields (variable length) now. Punt. */
140 if (flags & GRE_RP)
141 return;
142
143 if (flags & GRE_KP) {
144 TCHECK2(*cp, 4);
145 if (vflag > 1)
146 printf("K:%08x ", EXTRACT_32BITS(cp));
147 cp += 4; /* skip key */
148 }
149 if (flags & GRE_SP) {
150 TCHECK2(*cp, 4);
151 if (vflag > 1)
152 printf("S:%08x ", EXTRACT_32BITS(cp));
153 cp += 4; /* skip seq */
154 }
155 if (flags & GRE_AP && (flags & GRE_VER_MASK) >= 1) {
156 TCHECK2(*cp, 4);
157 if (vflag > 1)
158 printf("A:%08x ", EXTRACT_32BITS(cp));
159 cp += 4; /* skip ack */
160 }
161
162 TCHECK(cp[0]);
163
164 length -= cp - bp;
165 if (ether_encap_print(proto, cp, length, length,
166 &extracted_ethertype) == 0)
167 printf("gre-proto-0x%04X", proto);
168 return;
169
170 trunc:
171 fputs("[|gre]", stdout);
172
173 }