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.11 1999/12/10 21:27:13 guy 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 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
41 static int proto_gre = -1;
43 static gint ett_gre = -1;
44 static gint ett_gre_flags = -1;
46 /* bit positions for flags in header */
52 #define GH_B_RECUR 0x0700
53 #define GH_P_A 0x0080 /* only in special PPTPized GRE header */
54 #define GH_P_FLAGS 0x0078 /* only in special PPTPized GRE header */
55 #define GH_R_FLAGS 0x00F8
56 #define GH_B_VER 0x0007
58 #define GRE_PPP 0x880B
61 static int calc_len(guint16, int);
62 static void add_flags_and_ver(proto_tree *, guint16, int, int);
65 dissect_gre(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
67 guint16 flags_and_ver = pntohs(pd + offset);
68 guint16 type = pntohs(pd + offset + sizeof(flags_and_ver));
69 static const value_string typevals[] = {
77 if (check_col(fd, COL_PROTOCOL))
78 col_add_str(fd, COL_PROTOCOL, "GRE");
80 if (check_col(fd, COL_INFO)) {
81 col_add_fstr(fd, COL_INFO, "Encapsulated %s",
82 val_to_str(type, typevals, "0x%04X (unknown)"));
85 if (IS_DATA_IN_FRAME(offset) && tree) {
88 proto_tree * gre_tree;
90 is_ppp = (type == GRE_PPP);
92 ti = proto_tree_add_item_format(tree, proto_gre, offset,
93 calc_len(flags_and_ver, type), NULL,
94 "Generic Routing Encapsulation (%s)",
95 val_to_str(type, typevals, "0x%04X - unknown"));
96 gre_tree = proto_item_add_subtree(ti, ett_gre);
97 add_flags_and_ver(gre_tree, flags_and_ver, offset, is_ppp);
99 offset += sizeof(flags_and_ver);
101 proto_tree_add_text(gre_tree, offset, sizeof(type),
102 "Protocol Type: %s (%#04x)",
103 val_to_str(type, typevals, "Unknown"), type);
104 offset += sizeof(type);
106 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
107 guint16 checksum = pntohs(pd + offset);
108 proto_tree_add_text(gre_tree, offset, sizeof(checksum),
109 "Checksum: %u", checksum);
110 offset += sizeof(checksum);
113 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
114 guint16 rtoffset = pntohs(pd + offset);
115 proto_tree_add_text(gre_tree, offset, sizeof(rtoffset),
116 "Offset: %u", rtoffset);
117 offset += sizeof(rtoffset);
120 if (flags_and_ver & GH_B_K) {
125 paylen = pntohs(pd + offset);
126 proto_tree_add_text(gre_tree, offset, sizeof(paylen),
127 "Payload length: %u", paylen);
128 offset += sizeof(paylen);
130 callid = pntohs(pd + offset);
131 proto_tree_add_text(gre_tree, offset, sizeof(callid),
132 "Call ID: %u", callid);
133 offset += sizeof(callid);
136 guint32 key = pntohl(pd + offset);
137 proto_tree_add_text(gre_tree, offset, sizeof(key),
139 offset += sizeof(key);
143 if (flags_and_ver & GH_B_S) {
144 guint32 seqnum = pntohl(pd + offset);
145 proto_tree_add_text(gre_tree, offset, sizeof(seqnum),
146 "Sequence number: %u", seqnum);
147 offset += sizeof(seqnum);
150 if (is_ppp && flags_and_ver & GH_P_A) {
151 guint32 acknum = pntohl(pd + offset);
152 proto_tree_add_text(gre_tree, offset, sizeof(acknum),
153 "Acknowledgement number: %u", acknum);
154 offset += sizeof(acknum);
157 if (flags_and_ver & GH_B_R) {
159 sre_af = pntohs(pd + offset);
160 proto_tree_add_text(gre_tree, offset, sizeof(guint16),
161 "Address family: %u", sre_af);
162 offset += sizeof(guint16);
163 proto_tree_add_text(gre_tree, offset, 1,
164 "SRE offset: %u", pd[offset++]);
165 sre_length = pd[offset];
166 proto_tree_add_text(gre_tree, offset, sizeof(guint8),
167 "SRE length: %u", sre_length);
168 offset += sizeof(guint8);
169 if (sre_af == 0 && sre_length == 0)
171 offset += sre_length;
177 dissect_payload_ppp(pd, offset, fd, tree);
180 dissect_ip(pd, offset, fd, tree);
183 dissect_data(pd, offset, fd, gre_tree);
189 calc_len(guint16 flags_and_ver, int type)
193 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R)
195 if (flags_and_ver & GH_B_K)
197 if (flags_and_ver & GH_B_S)
202 if (flags_and_ver & GH_P_A)
211 add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) {
214 proto_tree * fv_tree;
215 int nbits = sizeof(flags_and_ver) * 8;
217 ti = proto_tree_add_text(tree, offset, 2,
218 "Flags and version: %#04x", flags_and_ver);
219 fv_tree = proto_item_add_subtree(ti, ett_gre_flags);
221 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
222 decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits,
223 "Checksum", "No checksum"));
224 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
225 decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits,
226 "Routing", "No routing"));
227 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
228 decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits,
230 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
231 decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits,
232 "Sequence number", "No sequence number"));
233 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
234 decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits,
235 "Strict source route", "No strict source route"));
236 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
237 decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits,
238 "Recursion control: %u"));
240 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
241 decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits,
242 "Acknowledgment number", "No acknowledgment number"));
243 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
244 decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits,
248 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
249 decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits,
253 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
254 decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits,
259 proto_register_gre(void)
261 /* static hf_register_info hf[] = {
263 { "Name", "gre.abbreviation", TYPE, VALS_POINTER }},
265 static gint *ett[] = {
270 proto_gre = proto_register_protocol("Generic Routing Encapsulation", "gre");
271 /* proto_register_field_array(proto_gre, hf, array_length(hf));*/
272 proto_register_subtree_array(ett, array_length(ett));