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.2 1999/07/07 22:51:43 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_text(tree, offset, calc_len(flags_and_ver, 1),
84 "Generic Routing Encapsulation (PPP)");
85 gre_tree = proto_item_add_subtree(ti, ETT_GRE);
86 add_flags_and_ver(gre_tree, flags_and_ver, offset, 1);
90 ti = proto_tree_add_text(tree, offset, calc_len(flags_and_ver, 1),
91 "Generic Routing Encapsulation");
92 gre_tree = proto_item_add_subtree(ti, ETT_GRE);
93 add_flags_and_ver(gre_tree, flags_and_ver, offset, 0);
96 offset += sizeof(flags_and_ver);
98 proto_tree_add_text(gre_tree, offset, sizeof(type),
99 "Protocol Type: %s (%#04x)",
100 val_to_str(type, typevals, "Unknown"), type);
101 offset += sizeof(type);
103 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
104 guint16 checksum = pntohs(pd + offset);
105 proto_tree_add_text(gre_tree, offset, sizeof(checksum),
106 "Checksum: %u", checksum);
107 offset += sizeof(checksum);
110 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) {
111 guint16 rtoffset = pntohs(pd + offset);
112 proto_tree_add_text(gre_tree, offset, sizeof(rtoffset),
113 "Offset: %u", rtoffset);
114 offset += sizeof(rtoffset);
117 if (flags_and_ver & GH_B_K) {
122 paylen = pntohs(pd + offset);
123 proto_tree_add_text(gre_tree, offset, sizeof(paylen),
124 "Payload length: %u", paylen);
125 offset += sizeof(paylen);
127 callid = pntohs(pd + offset);
128 proto_tree_add_text(gre_tree, offset, sizeof(callid),
129 "Call ID: %u", callid);
130 offset += sizeof(callid);
133 guint32 key = pntohl(pd + offset);
134 proto_tree_add_text(gre_tree, offset, sizeof(key),
136 offset += sizeof(key);
140 if (flags_and_ver & GH_B_S) {
141 guint32 seqnum = pntohl(pd + offset);
142 proto_tree_add_text(gre_tree, offset, sizeof(seqnum),
143 "Sequence number: %u", seqnum);
144 offset += sizeof(seqnum);
147 if (is_ppp && flags_and_ver & GH_P_A) {
148 guint32 acknum = pntohl(pd + offset);
149 proto_tree_add_text(gre_tree, offset, sizeof(acknum),
150 "Acknowledgement number: %u", acknum);
151 offset += sizeof(acknum);
154 if (flags_and_ver & GH_B_R) {
155 proto_tree_add_text(gre_tree, offset, sizeof(guint16),
156 "Address family: %u", pntohs(pd + offset));
157 offset += sizeof(guint16);
158 proto_tree_add_text(gre_tree, offset, 1,
159 "SRE offset: %u", pd[offset++]);
160 proto_tree_add_text(gre_tree, offset, 1,
161 "SRE length: %u", pd[offset++]);
166 dissect_payload_ppp(pd, offset, fd, tree);
169 dissect_data(pd, offset, fd, gre_tree);
175 calc_len(guint16 flags_and_ver, int is_ppp) {
179 if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) len += 4;
180 if (flags_and_ver & GH_B_K) len += 4;
181 if (flags_and_ver & GH_B_S) len += 4;
182 if (is_ppp && flags_and_ver & GH_P_A) len += 4;
188 add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) {
191 proto_tree * fv_tree;
192 int nbits = sizeof(flags_and_ver) * 8;
194 ti = proto_tree_add_text(tree, offset, 2,
195 "Flags and version: %#08x", flags_and_ver);
196 fv_tree = proto_item_add_subtree(ti, ETT_GRE_FLAGS);
198 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
199 decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits,
200 "Checksum", "No checksum"));
201 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
202 decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits,
203 "Routing", "No routing"));
204 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
205 decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits,
207 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
208 decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits,
209 "Sequence number", "No sequence number"));
210 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
211 decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits,
212 "Strict source route", "No strict source route"));
213 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
214 decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits,
215 "Recursion control: %u"));
217 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
218 decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits,
219 "Acknowledgment number", "No acknowledgment number"));
220 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
221 decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits,
225 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
226 decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits,
230 proto_tree_add_text(fv_tree, offset, sizeof(flags_and_ver), "%s",
231 decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits,