]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-gre.c
This commit was generated by cvs2svn to compensate for changes in r98944,
[FreeBSD/FreeBSD.git] / contrib / 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.13 2001/06/15 22:17:31 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 struct gre {
49         u_int16_t flags;
50         u_int16_t proto;
51 };
52
53 /* RFC 2784 - GRE */
54 #define GRE_CP          0x8000  /* Checksum Present */
55 #define GRE_VER_MASK    0x0007  /* Version */
56
57 /* RFC 2890 - Key and Sequence extensions to GRE */
58 #define GRE_KP          0x2000  /* Key Present */
59 #define GRE_SP          0x1000  /* Sequence Present */
60
61 /* Legacy from RFC 1700 */
62 #define GRE_RP          0x4000  /* Routing Present */
63 #define GRE_sP          0x0800  /* strict source route present */
64 #define GRE_RECUR_MASK  0x0700  /* Recursion Control */
65 #define GRE_RECUR_SHIFT 8
66
67 #define GRE_COP         (GRE_RP|GRE_CP) /* Checksum & Offset Present */
68
69 /* "Enhanced GRE" from RFC2637 - PPTP */
70 #define GRE_AP          0x0080  /* Ack present */
71
72 #define GRE_MBZ_MASK    0x0078  /* not defined */
73
74 /*
75  * Deencapsulate and print a GRE-tunneled IP datagram
76  */
77 void
78 gre_print(const u_char *bp, u_int length)
79 {
80         const u_char *cp = bp + 4;
81         const struct gre *gre;
82         u_int16_t flags, proto;
83         u_short ver=0;
84         u_short extracted_ethertype;
85
86         gre = (const struct gre *)bp;
87
88         TCHECK(gre->proto);
89         flags = EXTRACT_16BITS(&gre->flags);
90         proto = EXTRACT_16BITS(&gre->proto);
91         (void)printf("gre ");
92
93         if (flags) {
94                 /* Decode the flags */
95                 putchar('[');
96                 if (flags & GRE_CP)
97                         putchar('C');
98                 if (flags & GRE_RP)
99                         putchar('R');
100                 if (flags & GRE_KP)
101                         putchar('K');
102                 if (flags & GRE_SP)
103                         putchar('S');
104                 if (flags & GRE_sP)
105                         putchar('s');
106                 if (flags & GRE_AP)
107                         putchar('A');
108                 if (flags & GRE_RECUR_MASK)
109                         printf("R%x", (flags & GRE_RECUR_MASK) >> GRE_RECUR_SHIFT);
110                 ver = flags & GRE_VER_MASK;
111                 printf("v%u", ver);
112                 
113                 if (flags & GRE_MBZ_MASK)
114                         printf("!%x", flags & GRE_MBZ_MASK);
115                 fputs("] ", stdout);
116         }
117
118         if (flags & GRE_COP) {
119                 int checksum, offset;
120
121                 TCHECK2(*cp, 4);
122                 checksum = EXTRACT_16BITS(cp);
123                 offset = EXTRACT_16BITS(cp + 2);
124
125                 if (flags & GRE_CP) {
126                         /* Checksum present */
127
128                         /* todo: check checksum */
129                         if (vflag > 1)
130                                 printf("C:%04x ", checksum);
131                 }
132                 if (flags & GRE_RP) {
133                         /* Offset present */
134
135                         if (vflag > 1)
136                                 printf("O:%04x ", offset);
137                 }
138                 cp += 4;        /* skip checksum and offset */
139         }
140         if (flags & GRE_KP) {
141                 TCHECK2(*cp, 4);
142                 if (ver == 1) {         /* PPTP */
143                         if (vflag > 1)
144                                 printf("PL:%u ", EXTRACT_16BITS(cp));
145                         printf("ID:%04x ", EXTRACT_16BITS(cp+2));
146                 }
147                 else 
148                         printf("K:%08x ", EXTRACT_32BITS(cp));
149                 cp += 4;        /* skip key */
150         }
151         if (flags & GRE_SP) {
152                 TCHECK2(*cp, 4);
153                 printf("S:%u ", EXTRACT_32BITS(cp));
154                 cp += 4;        /* skip seq */
155         }
156         if (flags & GRE_AP && ver >= 1) {
157                 TCHECK2(*cp, 4);
158                 printf("A:%u ", EXTRACT_32BITS(cp));
159                 cp += 4;        /* skip ack */
160         }
161         /* We don't support routing fields (variable length) now. Punt. */
162         if (flags & GRE_RP)
163                 return;
164
165         TCHECK(cp[0]);
166
167         length -= cp - bp;
168         if (ether_encap_print(proto, cp, length, length,
169             &extracted_ethertype) == 0)
170                 printf("gre-proto-0x%04X", proto);
171         return;
172
173 trunc:
174         fputs("[|gre]", stdout);
175
176 }