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.8 1999/12/08 21:38:14 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
60 static int calc_len(guint16, int);
61 static void add_flags_and_ver(proto_tree *, guint16, int, int);
64 dissect_gre(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
66 guint16 flags_and_ver = pntohs(pd + offset);
67 guint16 type = pntohs(pd + offset + sizeof(flags_and_ver));
68 static const value_string typevals[] = {
73 if (check_col(fd, COL_PROTOCOL))
74 col_add_str(fd, COL_PROTOCOL, "GRE");
76 if (check_col(fd, COL_INFO)) {
78 col_add_str(fd, COL_INFO, "Encapsulated PPP");
80 col_add_str(fd, COL_INFO, "Encapsulated unknown");
83 if (IS_DATA_IN_FRAME(offset) && tree) {
86 proto_tree * gre_tree;
88 if (type == GRE_PPP) {
90 ti = proto_tree_add_item_format(tree, proto_gre, offset, calc_len(flags_and_ver, 1),
91 NULL, "Generic Routing Encapsulation (PPP)");
92 gre_tree = proto_item_add_subtree(ti, ett_gre);
93 add_flags_and_ver(gre_tree, flags_and_ver, offset, 1);
97 ti = proto_tree_add_item(tree, proto_gre, offset, calc_len(flags_and_ver, 1), NULL);
98 gre_tree = proto_item_add_subtree(ti, ett_gre);
99 add_flags_and_ver(gre_tree, flags_and_ver, offset, 0);
102 offset += sizeof(flags_and_ver);
104 proto_tree_add_text(gre_tree, offset, sizeof(type),
105 "Protocol Type: %s (%#04x)",
106 val_to_str(type, typevals, "Unknown"), type);
107 offset += sizeof(type);
109 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
110 guint16 checksum = pntohs(pd + offset);
111 proto_tree_add_text(gre_tree, offset, sizeof(checksum),
112 "Checksum: %u", checksum);
113 offset += sizeof(checksum);
116 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
117 guint16 rtoffset = pntohs(pd + offset);
118 proto_tree_add_text(gre_tree, offset, sizeof(rtoffset),
119 "Offset: %u", rtoffset);
120 offset += sizeof(rtoffset);
123 if (flags_and_ver & GH_B_K) {
128 paylen = pntohs(pd + offset);
129 proto_tree_add_text(gre_tree, offset, sizeof(paylen),
130 "Payload length: %u", paylen);
131 offset += sizeof(paylen);
133 callid = pntohs(pd + offset);
134 proto_tree_add_text(gre_tree, offset, sizeof(callid),
135 "Call ID: %u", callid);
136 offset += sizeof(callid);
139 guint32 key = pntohl(pd + offset);
140 proto_tree_add_text(gre_tree, offset, sizeof(key),
142 offset += sizeof(key);
146 if (flags_and_ver & GH_B_S) {
147 guint32 seqnum = pntohl(pd + offset);
148 proto_tree_add_text(gre_tree, offset, sizeof(seqnum),
149 "Sequence number: %u", seqnum);
150 offset += sizeof(seqnum);
153 if (is_ppp && flags_and_ver & GH_P_A) {
154 guint32 acknum = pntohl(pd + offset);
155 proto_tree_add_text(gre_tree, offset, sizeof(acknum),
156 "Acknowledgement number: %u", acknum);
157 offset += sizeof(acknum);
160 if (flags_and_ver & GH_B_R) {
161 proto_tree_add_text(gre_tree, offset, sizeof(guint16),
162 "Address family: %u", pntohs(pd + offset));
163 offset += sizeof(guint16);
164 proto_tree_add_text(gre_tree, offset, 1,
165 "SRE offset: %u", pd[offset++]);
166 proto_tree_add_text(gre_tree, offset, 1,
167 "SRE length: %u", pd[offset++]);
172 dissect_payload_ppp(pd, offset, fd, tree);
175 dissect_data(pd, offset, fd, gre_tree);
181 calc_len(guint16 flags_and_ver, int is_ppp) {
185 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) len += 4;
186 if (flags_and_ver & GH_B_K) len += 4;
187 if (flags_and_ver & GH_B_S) len += 4;
188 if (is_ppp && flags_and_ver & GH_P_A) len += 4;
194 add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) {
197 proto_tree * fv_tree;
198 int nbits = sizeof(flags_and_ver) * 8;
200 ti = proto_tree_add_text(tree, offset, 2,
201 "Flags and version: %#08x", flags_and_ver);
202 fv_tree = proto_item_add_subtree(ti, ett_gre_flags);
204 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
205 decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits,
206 "Checksum", "No checksum"));
207 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
208 decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits,
209 "Routing", "No routing"));
210 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
211 decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits,
213 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
214 decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits,
215 "Sequence number", "No sequence number"));
216 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
217 decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits,
218 "Strict source route", "No strict source route"));
219 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
220 decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits,
221 "Recursion control: %u"));
223 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
224 decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits,
225 "Acknowledgment number", "No acknowledgment number"));
226 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
227 decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits,
231 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
232 decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits,
236 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
237 decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits,
242 proto_register_gre(void)
244 /* static hf_register_info hf[] = {
246 { "Name", "gre.abbreviation", TYPE, VALS_POINTER }},
248 static gint *ett[] = {
253 proto_gre = proto_register_protocol("Generic Routing Encapsulation", "gre");
254 /* proto_register_field_array(proto_gre, hf, array_length(hf));*/
255 proto_register_subtree_array(ett, array_length(ett));