Trivial warning fixes
[obnox/wireshark/wip.git] / epan / dissectors / packet-cisco-erspan.c
1 /* packet-erspan.c
2  * Routines for the disassembly of Cisco's ERSPAN protocol
3  *
4  * $Id$
5  *
6  * Copyright 2005 Joerg Mayer (see AUTHORS file)
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
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.
16  *
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.
21  *
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.
25  */
26
27 /*
28  * TODO:
29  *      Find out the Unknown values
30  *
31  * Specs:
32  *      No real specs exist. Some general description can be found at:
33  *      http://www.cisco.com/en/US/products/hw/routers/ps368/products_configuration_guide_chapter09186a008069952a.html
34  *
35  *      For ERSPAN packets, the "protocol type" field value in the GRE header
36  *      is 0x88BE.
37  *
38  * 0000000: d4c3 b2a1 0200 0400 0000 0000 0000 0000 <-- pcap header
39  * 0000010: ffff 0000
40  * 0000010:           7100 0000 <-- 0x71 (DLT_TYPE) = linux_cooked_capture (of course not)
41  * 0000010:                     7507 f845 11d1 0500 <-- pcap record header
42  * 0000020: 7a00 0000 7a00 0000
43  * 0000020:                     0000 030a 0000 0000 <-- unknown
44  * 0000030: 0000 0000
45  * 0000030:           0000 88be <-- GRE header
46  * 0000030:                     1002 0001 0000 0380 <-- ERSPAN header (01: erspan-id)
47  * 0000040: 00d0 b7a7 7480 0015 c721 75c0 0800 4500 <-- Ethernet packet
48  * ...
49  * 
50  *
51  */
52
53 #ifdef HAVE_CONFIG_H
54 #  include "config.h"
55 #endif
56
57 #include <glib.h>
58 #include <epan/packet.h>
59 #include <epan/greproto.h>
60
61 static int proto_erspan = -1;
62
63 static gint ett_erspan = -1;
64
65 static int hf_erspan_unknown1 = -1;
66 static int hf_erspan_vlan = -1;
67 static int hf_erspan_priority = -1;
68 static int hf_erspan_unknown2 = -1;
69 static int hf_erspan_direction = -1;
70 static int hf_erspan_unknown3 = -1;
71 static int hf_erspan_spanid = -1;
72 static int hf_erspan_unknown4 = -1;
73
74 #define PROTO_SHORT_NAME "ERSPAN"
75 #define PROTO_LONG_NAME "ER Switch Packet Analysis"
76
77 #define ERSPAN_DIRECTION_INCOMING 0
78 #define ERSPAN_DIRECTION_OUTGOING 1
79 static const value_string erspan_direction_vals[] = {
80         {ERSPAN_DIRECTION_INCOMING, "Incoming"},
81         {ERSPAN_DIRECTION_OUTGOING, "Outgoing"},
82         {0, NULL},
83 };
84
85 static dissector_handle_t ethnofcs_handle;
86
87 static void
88 dissect_erspan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
89 {
90         proto_item *ti;
91         proto_tree *erspan_tree = NULL;
92         tvbuff_t *eth_tvb;
93         guint32 offset = 0;
94
95         if (check_col(pinfo->cinfo, COL_PROTOCOL))
96                 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
97         if (check_col(pinfo->cinfo, COL_INFO))
98                 col_set_str(pinfo->cinfo, COL_INFO, PROTO_SHORT_NAME ":");
99
100         if (tree) {
101                 ti = proto_tree_add_item(tree, proto_erspan, tvb, offset, -1,
102                     FALSE);
103                 erspan_tree = proto_item_add_subtree(ti, ett_erspan);
104
105                 proto_tree_add_item(erspan_tree, hf_erspan_unknown1, tvb, offset, 2,
106                         FALSE);
107
108                 proto_tree_add_item(erspan_tree, hf_erspan_vlan, tvb, offset, 2,
109                         FALSE);
110                 offset += 2;
111
112                 proto_tree_add_item(erspan_tree, hf_erspan_priority, tvb, offset, 2,
113                         FALSE);
114
115                 proto_tree_add_item(erspan_tree, hf_erspan_unknown2, tvb, offset, 2,
116                         FALSE);
117
118                 proto_tree_add_item(erspan_tree, hf_erspan_direction, tvb, offset, 2,
119                         FALSE);
120
121                 proto_tree_add_item(erspan_tree, hf_erspan_unknown3, tvb, offset, 2,
122                         FALSE);
123
124                 proto_tree_add_item(erspan_tree, hf_erspan_spanid, tvb, offset, 2,
125                         FALSE);
126                 offset += 2;
127
128                 proto_tree_add_item(erspan_tree, hf_erspan_unknown4, tvb, offset, 4,
129                         FALSE);
130                 offset += 4;
131
132                 eth_tvb = tvb_new_subset(tvb, offset, -1, -1);
133                 call_dissector(ethnofcs_handle, eth_tvb, pinfo, tree);
134         }
135 }
136
137 void
138 proto_register_erspan(void)
139 {
140         static hf_register_info hf[] = {
141
142                 { &hf_erspan_unknown1,
143                 { "Unknown1",   "erspan.unknown1", FT_UINT16, BASE_HEX, NULL,
144                         0xf000, "", HFILL }},
145
146                 { &hf_erspan_vlan,
147                 { "Vlan",       "erspan.vlan", FT_UINT16, BASE_DEC, NULL,
148                         0x0fff, "", HFILL }},
149
150                 { &hf_erspan_priority,
151                 { "Priority",   "erspan.priority", FT_UINT16, BASE_DEC, NULL,
152                         0xe000, "", HFILL }},
153
154                 { &hf_erspan_unknown2,
155                 { "Unknown2",   "erspan.unknown2", FT_UINT16, BASE_DEC, NULL,
156                         0x1000, "", HFILL }},
157
158                 { &hf_erspan_direction,
159                 { "Direction",  "erspan.direction", FT_UINT16, BASE_DEC, VALS(erspan_direction_vals),
160                         0x0800, "", HFILL }},
161
162                 { &hf_erspan_unknown3,
163                 { "Unknown3",   "erspan.unknown3", FT_UINT16, BASE_DEC, NULL,
164                         0x0400, "", HFILL }},
165
166                 { &hf_erspan_spanid,
167                 { "SpanID",     "erspan.spanid", FT_UINT16, BASE_DEC, NULL,
168                         0x03ff, "", HFILL }},
169
170                 { &hf_erspan_unknown4,
171                 { "Unknown4",   "erspan.unknown4", FT_BYTES, BASE_NONE, NULL,
172                         0, "", HFILL }},
173
174         };
175         static gint *ett[] = {
176                 &ett_erspan,
177         };
178
179         proto_erspan = proto_register_protocol(PROTO_LONG_NAME,
180             PROTO_SHORT_NAME, "erspan");
181         proto_register_field_array(proto_erspan, hf, array_length(hf));
182         proto_register_subtree_array(ett, array_length(ett));
183 }
184
185 void
186 proto_reg_handoff_erspan(void)
187 {
188         dissector_handle_t erspan_handle;
189
190         ethnofcs_handle = find_dissector("eth_withoutfcs");
191
192         erspan_handle = create_dissector_handle(dissect_erspan, proto_erspan);
193         dissector_add("gre.proto", GRE_ERSPAN, erspan_handle);
194
195 }
196