2 * Routines for the Generic Routing Encapsulation (GRE) protocol
3 * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
5 * $Id: packet-gre.c,v 1.1 1999/06/11 15:30:37 gram Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
9 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
35 #include <netinet/in.h>
39 /* bit positions for flags in header */
45 #define GH_B_RECUR 0x0700
46 #define GH_P_A 0x0080 /* only in special PPTPized GRE header */
47 #define GH_P_FLAGS 0x0078 /* only in special PPTPized GRE header */
48 #define GH_R_FLAGS 0x00F8
49 #define GH_B_VER 0x0007
51 #define GRE_PPP 0x880B
53 static int calc_len(guint16, int);
54 static void add_flags_and_ver(proto_tree *, guint16, int, int);
57 dissect_gre(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
59 guint16 flags_and_ver = pntohs(pd + offset);
60 guint16 type = pntohs(pd + offset + sizeof(flags_and_ver));
61 static const value_string typevals[] = {
66 if (check_col(fd, COL_PROTOCOL))
67 col_add_str(fd, COL_PROTOCOL, "GRE");
69 if (check_col(fd, COL_INFO)) {
71 col_add_str(fd, COL_INFO, "Encapsulated PPP");
73 col_add_str(fd, COL_INFO, "Encapsulated unknown");
76 if (fd->cap_len > offset && tree) {
79 proto_tree * gre_tree;
81 if (type == GRE_PPP) {
83 ti = proto_tree_add_item(tree, offset, calc_len(flags_and_ver, 1),
84 "Generic Routing Encapsulation (PPP)");
85 gre_tree = proto_tree_new();
86 proto_item_add_subtree(ti, gre_tree, ETT_GRE);
87 add_flags_and_ver(gre_tree, flags_and_ver, offset, 1);
91 ti = proto_tree_add_item(tree, offset, calc_len(flags_and_ver, 1),
92 "Generic Routing Encapsulation");
93 gre_tree = proto_tree_new();
94 proto_item_add_subtree(ti, gre_tree, ETT_GRE);
95 add_flags_and_ver(gre_tree, flags_and_ver, offset, 0);
98 offset += sizeof(flags_and_ver);
100 proto_tree_add_item(gre_tree, offset, sizeof(type),
101 "Protocol Type: %s (%#04x)",
102 val_to_str(type, typevals, "Unknown"), type);
103 offset += sizeof(type);
105 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
106 guint16 checksum = pntohs(pd + offset);
107 proto_tree_add_item(gre_tree, offset, sizeof(checksum),
108 "Checksum: %u", checksum);
109 offset += sizeof(checksum);
112 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
113 guint16 rtoffset = pntohs(pd + offset);
114 proto_tree_add_item(gre_tree, offset, sizeof(rtoffset),
115 "Offset: %u", rtoffset);
116 offset += sizeof(rtoffset);
119 if (flags_and_ver & GH_B_K) {
124 paylen = pntohs(pd + offset);
125 proto_tree_add_item(gre_tree, offset, sizeof(paylen),
126 "Payload length: %u", paylen);
127 offset += sizeof(paylen);
129 callid = pntohs(pd + offset);
130 proto_tree_add_item(gre_tree, offset, sizeof(callid),
131 "Call ID: %u", callid);
132 offset += sizeof(callid);
135 guint32 key = pntohl(pd + offset);
136 proto_tree_add_item(gre_tree, offset, sizeof(key),
138 offset += sizeof(key);
142 if (flags_and_ver & GH_B_S) {
143 guint32 seqnum = pntohl(pd + offset);
144 proto_tree_add_item(gre_tree, offset, sizeof(seqnum),
145 "Sequence number: %u", seqnum);
146 offset += sizeof(seqnum);
149 if (is_ppp && flags_and_ver & GH_P_A) {
150 guint32 acknum = pntohl(pd + offset);
151 proto_tree_add_item(gre_tree, offset, sizeof(acknum),
152 "Acknowledgement number: %u", acknum);
153 offset += sizeof(acknum);
156 if (flags_and_ver & GH_B_R) {
157 proto_tree_add_item(gre_tree, offset, sizeof(guint16),
158 "Address family: %u", pntohs(pd + offset));
159 offset += sizeof(guint16);
160 proto_tree_add_item(gre_tree, offset, 1,
161 "SRE offset: %u", pd[offset++]);
162 proto_tree_add_item(gre_tree, offset, 1,
163 "SRE length: %u", pd[offset++]);
168 dissect_payload_ppp(pd, offset, fd, tree);
171 dissect_data(pd, offset, fd, gre_tree);
177 calc_len(guint16 flags_and_ver, int is_ppp) {
181 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) len += 4;
182 if (flags_and_ver & GH_B_K) len += 4;
183 if (flags_and_ver & GH_B_S) len += 4;
184 if (is_ppp && flags_and_ver & GH_P_A) len += 4;
190 add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) {
193 proto_tree * fv_tree;
194 int nbits = sizeof(flags_and_ver) * 8;
196 ti = proto_tree_add_item(tree, offset, 2,
197 "Flags and version: %#08x", flags_and_ver);
198 fv_tree = proto_tree_new();
199 proto_item_add_subtree(ti, fv_tree, ETT_GRE_FLAGS);
201 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
202 decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits,
203 "Checksum", "No checksum"));
204 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
205 decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits,
206 "Routing", "No routing"));
207 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
208 decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits,
210 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
211 decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits,
212 "Sequence number", "No sequence number"));
213 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
214 decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits,
215 "Strict source route", "No strict source route"));
216 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
217 decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits,
218 "Recursion control: %u"));
220 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
221 decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits,
222 "Acknowledgment number", "No acknowledgment number"));
223 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
224 decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits,
228 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
229 decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits,
233 proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s",
234 decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits,