xref: /freebsd/contrib/tcpdump/print-gre.c (revision 2a4a1db342263067035ce69a4017c645da63455d)
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.9 2000/12/18 05:41:59 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/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 #define GRE_CP		0x8000	/* Checksum Present */
76 #define GRE_RP		0x4000	/* Routing Present */
77 #define GRE_KP		0x2000	/* Key Present */
78 #define GRE_SP		0x1000	/* Sequence Present */
79 
80 
81 /*
82  * Deencapsulate and print a GRE-tunneled IP datagram
83  */
84 void
85 gre_print(const u_char *bp, u_int length)
86 {
87 	const u_char *cp = bp + 4;
88 	const struct gre *gre;
89 	u_short flags, proto, extracted_ethertype;
90 
91 	gre = (const struct gre *)bp;
92 
93 	if (length < GRE_SIZE) {
94 		goto trunc;
95 	}
96 	flags = EXTRACT_16BITS(&gre->flags);
97 	proto = EXTRACT_16BITS(&gre->proto);
98 
99 	if (vflag) {
100 		/* Decode the flags */
101 		putchar('[');
102 		if (flags & GRE_CP)
103 			putchar('C');
104 		if (flags & GRE_RP)
105 			putchar('R');
106 		if (flags & GRE_KP)
107 			putchar('K');
108 		if (flags & GRE_SP)
109 			putchar('S');
110 		fputs("] ", stdout);
111 	}
112 	/* Checksum & Offset are present */
113 	if ((flags & GRE_CP) | (flags & GRE_RP))
114 		cp += 4;
115 
116 	/* We don't support routing fields (variable length) now. Punt. */
117 	if (flags & GRE_RP)
118 		return;
119 
120 	if (flags & GRE_KP)
121 		cp += 4;
122 	if (flags & GRE_SP)
123 		cp += 4;
124 
125 	length -= cp - bp;
126 	if (ether_encap_print(proto, cp, length, length,
127 	    &extracted_ethertype) == 0)
128  		printf("gre-proto-0x%04X", proto);
129 	return;
130 
131 trunc:
132 	fputs("[|gre]", stdout);
133 
134 }
135