xref: /freebsd/contrib/tcpdump/print-gre.c (revision ce834215a70ff69e7e222827437116eee2f9ac6f)
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: print-gre.c,v 1.4 96/12/10 23:28:23 leres Exp $";
28 #endif
29 
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/uio.h>
33 #include <sys/socket.h>
34 
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 
39 #include <netdb.h>
40 #include <stdio.h>
41 
42 #include "interface.h"
43 #include "addrtoname.h"
44 #include "extract.h"		/* must come after interface.h */
45 
46 #define GRE_SIZE (20)
47 
48 struct gre {
49 	u_short flags;
50 	u_short proto;
51 	union {
52 		struct gre_ckof {
53 			u_short cksum;
54 			u_short offset;
55 		}        gre_ckof;
56 		u_int32_t key;
57 		u_int32_t seq;
58 	}     gre_void1;
59 	union {
60 		u_int32_t key;
61 		u_int32_t seq;
62 		u_int32_t routing;
63 	}     gre_void2;
64 	union {
65 		u_int32_t seq;
66 		u_int32_t routing;
67 	}     gre_void3;
68 	union {
69 		u_int32_t routing;
70 	}     gre_void4;
71 };
72 
73 #define GRE_CP		0x8000	/* Checksum Present */
74 #define GRE_RP		0x4000	/* Routing Present */
75 #define GRE_KP		0x2000	/* Key Present */
76 #define GRE_SP		0x1000	/* Sequence Present */
77 
78 
79 #define GREPROTO_IP	0x0800
80 
81 
82 /*
83  * Deencapsulate and print a GRE-tunneled IP datagram
84  */
85 void
86 gre_print(const u_char *bp, u_int length)
87 {
88 	const u_char *cp = bp + 4;
89 	const struct gre *gre;
90 	u_short flags, proto;
91 
92 	gre = (const struct gre *)bp;
93 
94 	if (length < GRE_SIZE) {
95 		goto trunc;
96 	}
97 	flags = EXTRACT_16BITS(&gre->flags);
98 	proto = EXTRACT_16BITS(&gre->proto);
99 
100 	if (vflag) {
101 		/* Decode the flags */
102 		putchar('[');
103 		if (flags & GRE_CP)
104 			putchar('C');
105 		if (flags & GRE_RP)
106 			putchar('R');
107 		if (flags & GRE_KP)
108 			putchar('K');
109 		if (flags & GRE_SP)
110 			putchar('S');
111 		fputs("] ", stdout);
112 	}
113 	/* Checksum & Offset are present */
114 	if ((flags & GRE_CP) | (flags & GRE_RP))
115 		cp += 4;
116 
117 	/* We don't support routing fields (variable length) now. Punt. */
118 	if (flags & GRE_RP)
119 		return;
120 
121 	if (flags & GRE_KP)
122 		cp += 4;
123 	if (flags & GRE_SP)
124 		cp += 4;
125 
126 	switch (proto) {
127 
128 	case GREPROTO_IP:
129 		ip_print(cp, length - ((cp - bp) / sizeof(u_char)));
130 		break;
131 
132 	default:
133 		printf("gre-proto-0x%04X", proto);
134 		break;
135 	}
136 	return;
137 
138 trunc:
139 	fputs("[|gre]", stdout);
140 
141 }
142