8d7f7d0a092623452fde8fee306b7f59826d26d3
[metze/wireshark/wip.git] / epan / dissectors / packet-ismp.c
1 /* packet-ismp.c
2  * Routines for ISMP dissection
3  * Enterasys Networks Home: http://www.enterasys.com/
4  * Copyright 2003, Joshua Craig Douglas <jdouglas@enterasys.com>
5  *
6  * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #include "config.h"
28
29 #include <glib.h>
30
31 #include <epan/packet.h>
32 #include <epan/strutil.h>
33 #include <epan/etypes.h>
34
35
36 /* Initialize the protocol and registered fields */
37 static int proto_ismp = -1;
38 static int hf_ismp_version = -1;
39 static int hf_ismp_message_type = -1;
40 static int hf_ismp_seq_num = -1;
41 static int hf_ismp_code_length = -1;
42 static int hf_ismp_auth_data = -1;
43
44 /* Enterasys/Cabletron Dicovery Protocol fields*/
45 static int hf_ismp_edp = -1;
46 static int hf_ismp_edp_version = -1;
47 static int hf_ismp_edp_module_ip = -1;
48 static int hf_ismp_edp_module_mac = -1;
49 static int hf_ismp_edp_module_port = -1;
50 static int hf_ismp_edp_chassis_mac =-1;
51 static int hf_ismp_edp_chassis_ip = -1;
52 static int hf_ismp_edp_device_type = -1;
53 static int hf_ismp_edp_module_rev = -1;
54 static int hf_ismp_edp_options = -1;
55 static int hf_ismp_edp_sfs_option_unused1 = -1;
56 static int hf_ismp_edp_sfs_option_sfssup = -1;
57 static int hf_ismp_edp_sfs_option_lsp = -1;
58 static int hf_ismp_edp_sfs_option_flood = -1;
59 static int hf_ismp_edp_sfs_option_resolve = -1;
60 static int hf_ismp_edp_sfs_option_unused2 = -1;
61 static int hf_ismp_edp_sfs_option_tagflood = -1;
62 static int hf_ismp_edp_sfs_option_calltap = -1;
63 static int hf_ismp_edp_sfs_option_conmsg = -1;
64 static int hf_ismp_edp_sfs_option_redun = -1;
65 static int hf_ismp_edp_sfs_option_isolated = -1;
66 static int hf_ismp_edp_sfs_option_uplink_switch = -1;
67 static int hf_ismp_edp_sfs_option_uplink_core = -1;
68 static int hf_ismp_edp_sfs_option_uplink_port = -1;
69 static int hf_ismp_edp_sfs_option_uplink_flood = -1;
70 static int hf_ismp_edp_rtr_option_ssr = -1;
71 static int hf_ismp_edp_rtr_option_igmp = -1;
72 static int hf_ismp_edp_rtr_option_rip = -1;
73 static int hf_ismp_edp_rtr_option_bgp = -1;
74 static int hf_ismp_edp_rtr_option_ospf = -1;
75 static int hf_ismp_edp_rtr_option_dvmrp = -1;
76 static int hf_ismp_edp_rtr_option_8021q = -1;
77 static int hf_ismp_edp_rtr_option_gvrp = -1;
78 static int hf_ismp_edp_rtr_option_gmrp = -1;
79 static int hf_ismp_edp_rtr_option_igmp_snoop = -1;
80 static int hf_ismp_edp_rtr_option_route = -1;
81 static int hf_ismp_edp_rtr_option_trans = -1;
82 static int hf_ismp_edp_rtr_option_level1 = -1;
83 static int hf_ismp_edp_switch_option_8021q = -1;
84 static int hf_ismp_edp_switch_option_gvrp = -1;
85 static int hf_ismp_edp_switch_option_gmrp = -1;
86 static int hf_ismp_edp_switch_option_igmp = -1;
87 static int hf_ismp_edp_switch_option_route = -1;
88 static int hf_ismp_edp_switch_option_trans = -1;
89 static int hf_ismp_edp_switch_option_level1 = -1;
90 static int hf_ismp_edp_end_station_option_dhcp = -1;
91 static int hf_ismp_edp_end_station_option_dns = -1;
92 static int hf_ismp_edp_end_station_option_ad = -1;
93 static int hf_ismp_edp_num_neighbors = -1;
94 static int hf_ismp_edp_neighbors = -1;
95 static int hf_ismp_edp_num_tuples = -1;
96 static int hf_ismp_edp_tuples = -1;
97
98
99 /* Initialize the subtree pointers */
100 static gint ett_ismp = -1;
101 static gint ett_ismp_edp = -1;
102 static gint ett_ismp_edp_options = -1;
103 static gint ett_ismp_edp_neighbors = -1;
104 static gint ett_ismp_edp_neighbors_leaf = -1;
105 static gint ett_ismp_edp_tuples = -1;
106 static gint ett_ismp_edp_tuples_leaf = -1;
107
108 /* ISMP TYPES */
109 #define ISMPTYPE_EDP    2
110
111
112 /* EDP DEVICE TYPES */
113 #define EDP_DEVICE_TYPE_SFS17           1
114 #define EDP_DEVICE_TYPE_SFS18           2
115 #define EDP_DEVICE_TYPE_ROUTER          3
116 #define EDP_DEVICE_TYPE_BRIDGE          4
117 #define EDP_DEVICE_TYPE_VLANMAN         5
118 #define EDP_DEVICE_TYPE_NTSERVER        6
119 #define EDP_DEVICE_TYPE_NTCLIENT        7
120 #define EDP_DEVICE_TYPE_WIN95           8
121 #define EDP_DEVICE_TYPE_WIN98           9
122 #define EDP_DEVICE_TYPE_UNIXSERVER      10
123 #define EDP_DEVICE_TYPE_UNIXCLIENT      11
124 #define EDP_DEVICE_TYPE_ACCESSPOINT     12
125
126
127 static const value_string edp_device_types[] = {
128         { EDP_DEVICE_TYPE_SFS17,       "Network Switch running SecureFast version 1.7 or lower" },
129         { EDP_DEVICE_TYPE_SFS18,         "Network Switch running SecureFast version 1.8 or greater" },
130         { EDP_DEVICE_TYPE_ROUTER,         "Router" },
131         { EDP_DEVICE_TYPE_BRIDGE,         "Bridge" },
132         { EDP_DEVICE_TYPE_VLANMAN,         "Cabletron VLAN Manager" },
133         { EDP_DEVICE_TYPE_NTSERVER,         "Network Server (NT)" },
134         { EDP_DEVICE_TYPE_NTCLIENT,    "Network Workstation (NT)" },
135         { EDP_DEVICE_TYPE_WIN95,     "Windows95" },
136         { EDP_DEVICE_TYPE_WIN98,        "Windows98" },
137         { EDP_DEVICE_TYPE_UNIXSERVER,       "UNIX Server" },
138         { EDP_DEVICE_TYPE_UNIXCLIENT, "UNIX Workstation" },
139         { EDP_DEVICE_TYPE_ACCESSPOINT,     "Roamabout wireless access point" },
140         { 0,                    NULL },
141 };
142
143
144 /* EDP SFS Options */
145 #define EDP_SFS_OPTION_UNUSED1          0x1
146 #define EDP_SFS_OPTION_SFSSUP           0x2
147 #define EDP_SFS_OPTION_LSP              0x4
148 #define EDP_SFS_OPTION_FLOOD            0x8
149 #define EDP_SFS_OPTION_RESOLVE          0x10
150 #define EDP_SFS_OPTION_UNUSED2          0x20
151 #define EDP_SFS_OPTION_TAGFLOOD         0x40
152 #define EDP_SFS_OPTION_CALLTAP          0x80
153 #define EDP_SFS_OPTION_CONMSG           0x100
154 #define EDP_SFS_OPTION_REDUN            0x200
155 #define EDP_SFS_OPTION_ISOLATED         0x400
156 #define EDP_SFS_OPTION_UPLINK_SWITCH    0x800
157 #define EDP_SFS_OPTION_UPLINK_CORE      0x1000
158 #define EDP_SFS_OPTION_UPLINK_PORT      0x2000
159 #define EDP_SFS_OPTION_UPLINK_FLOOD     0x4000
160
161 /* EDP Router Options */
162 #define EDP_RTR_OPTION_SSR              0x1
163 #define EDP_RTR_OPTION_IGMP             0x2
164 #define EDP_RTR_OPTION_RIP              0x4
165 #define EDP_RTR_OPTION_BGP              0x8
166 #define EDP_RTR_OPTION_OSPF             0x10
167 #define EDP_RTR_OPTION_DVMRP            0x20
168 #define EDP_RTR_OPTION_8021Q            0x40
169 #define EDP_RTR_OPTION_GVRP             0x80
170 #define EDP_RTR_OPTION_GMRP             0x100
171 #define EDP_RTR_OPTION_IGMP_SNOOP       0x200
172 #define EDP_RTR_OPTION_ROUTE            0x400
173 #define EDP_RTR_OPTION_TRANS            0x800
174 #define EDP_RTR_OPTION_LEVEL1           0x1000
175
176 /* EDP Switch Options */
177 #define EDP_SWITCH_OPTION_8021Q         0x1
178 #define EDP_SWITCH_OPTION_GVRP          0x2
179 #define EDP_SWITCH_OPTION_GMRP          0x4
180 #define EDP_SWITCH_OPTION_IGMP          0x8
181 #define EDP_SWITCH_OPTION_ROUTE         0x10
182 #define EDP_SWITCH_OPTION_TRANS         0x20
183 #define EDP_SWITCH_OPTION_LEVEL1        0x40
184
185 /* EDP End Station and Server Options */
186 #define EDP_END_STATION_OPTION_DHCP     0x1
187 #define EDP_END_STATION_OPTION_DNS      0x2
188 #define EDP_END_STATION_OPTION_AD       0x4
189
190 /* EDP Tuple Types */
191 #define EDP_TUPLE_UNKNOWN               0
192 #define EDP_TUPLE_HOLD                  1
193 #define EDP_TUPLE_INT_NAME              2
194 #define EDP_TUPLE_SYS_DESCRIPT  3
195 #define EDP_TUPLE_IPX_ADDR              4
196
197 static const value_string edp_tuple_types[] =
198 {
199         { EDP_TUPLE_UNKNOWN,"Unknown" },
200         { EDP_TUPLE_HOLD,"Hold Time" },
201         { EDP_TUPLE_INT_NAME,"Interface Name" },
202         { EDP_TUPLE_SYS_DESCRIPT,"System Description" },
203         { EDP_TUPLE_IPX_ADDR,"IPX Address" },
204         { 0,NULL }
205 };
206
207 /* Is value set? */
208 static const true_false_string is_set = {
209         "set",
210         "not set"
211 };
212
213
214 /* Function to dissect EDP portion of ISMP message */
215 static void
216 dissect_ismp_edp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *ismp_tree)
217 {
218         /* local variables used for EDP dissection */
219         int neighbors_count = 0;
220         int tuples_count = 0;
221         guint16 device_type = 0;
222         guint32 options = 0;
223         guint16 num_neighbors = 0;
224         guint16 num_tuples = 0;
225         guint16 tuple_type = 0;
226         guint16 tuple_length = 0;
227
228         /* Set up structures needed to add the protocol subtree and manage it */
229         proto_item *edp_ti;
230         proto_tree *edp_tree;
231
232         proto_item *edp_options_ti;
233         proto_tree *edp_options_tree;
234
235         proto_item *edp_neighbors_ti;
236         proto_tree *edp_neighbors_tree;
237
238         proto_item *edp_neighbors_leaf_ti;
239         proto_tree *edp_neighbors_leaf_tree;
240
241         proto_item *edp_tuples_ti;
242         proto_tree *edp_tuples_tree;
243
244         proto_item *edp_tuples_leaf_ti;
245         proto_tree *edp_tuples_leaf_tree;
246
247         /* add column iformation marking this as EDP (Enterasys Discover Protocol */
248         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP.EDP");
249         col_clear(pinfo->cinfo, COL_INFO);
250
251         /* create display subtree for EDP */
252         if (ismp_tree) {
253                 edp_ti  = proto_tree_add_item(ismp_tree, hf_ismp_edp, tvb, offset,
254                         tvb_length_remaining(tvb, offset), ENC_NA);
255                 edp_tree = proto_item_add_subtree(edp_ti, ett_ismp_edp);
256
257                 col_add_fstr(pinfo->cinfo, COL_INFO, "MIP %s, MMAC %s, ifIdx %d",
258                         tvb_ip_to_str(tvb, offset+2),
259                         tvb_ether_to_str(tvb, offset+6),
260                         tvb_get_ntohl(tvb, offset+12));
261
262                 proto_tree_add_item(edp_tree, hf_ismp_edp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
263                 offset += 2;
264                 proto_tree_add_item(edp_tree, hf_ismp_edp_module_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
265                 offset += 4;
266                 proto_tree_add_item(edp_tree, hf_ismp_edp_module_mac, tvb, offset, 6, ENC_NA);
267                 offset += 6;
268                 proto_tree_add_item(edp_tree, hf_ismp_edp_module_port, tvb, offset, 4, ENC_BIG_ENDIAN);
269                 offset += 4;
270                 proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_mac, tvb, offset, 6, ENC_NA);
271                 offset += 6;
272                 proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
273                 offset += 4;
274                 device_type = tvb_get_ntohs(tvb, offset);
275                 proto_tree_add_item(edp_tree, hf_ismp_edp_device_type, tvb, offset, 2, ENC_BIG_ENDIAN);
276                 offset += 2;
277                 proto_tree_add_uint_format_value(edp_tree, hf_ismp_edp_module_rev, tvb, offset, 4, tvb_get_ntohl(tvb, offset),
278                         "%02x.%02x.%02x.%02x", tvb_get_guint8(tvb, offset),
279                         tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3));
280                 offset += 4;
281
282                 /* create display subtree for EDP options */
283                 options = tvb_get_ntohl(tvb, offset);
284                 edp_options_ti = proto_tree_add_uint_format(edp_tree, hf_ismp_edp_options, tvb, offset, 4,
285                         options,"Options: 0x%08x",options);
286                 edp_options_tree = proto_item_add_subtree(edp_options_ti, ett_ismp_edp_options);
287
288                 /* depending on device_type, show the appropriate options */
289                 switch (device_type) {
290                         case EDP_DEVICE_TYPE_SFS17:
291                         case EDP_DEVICE_TYPE_SFS18:
292                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_flood, tvb, offset, 4, ENC_BIG_ENDIAN);
293                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_port, tvb, offset, 4, ENC_BIG_ENDIAN);
294                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_core, tvb, offset, 4, ENC_BIG_ENDIAN);
295                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_switch, tvb, offset, 4, ENC_BIG_ENDIAN);
296                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_isolated, tvb, offset, 4, ENC_BIG_ENDIAN);
297                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_redun, tvb, offset, 4, ENC_BIG_ENDIAN);
298                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_conmsg, tvb, offset, 4, ENC_BIG_ENDIAN);
299                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_calltap, tvb, offset, 4, ENC_BIG_ENDIAN);
300                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_tagflood, tvb, offset, 4, ENC_BIG_ENDIAN);
301                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused2, tvb, offset, 4, ENC_BIG_ENDIAN);
302                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_resolve, tvb, offset, 4, ENC_BIG_ENDIAN);
303                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_flood, tvb, offset, 4, ENC_BIG_ENDIAN);
304                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_lsp, tvb, offset, 4, ENC_BIG_ENDIAN);
305                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_sfssup, tvb, offset, 4, ENC_BIG_ENDIAN);
306                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused1, tvb, offset, 4, ENC_BIG_ENDIAN);
307                                 break;
308                         case EDP_DEVICE_TYPE_ROUTER:
309                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_level1, tvb, offset, 4, ENC_BIG_ENDIAN);
310                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_trans, tvb, offset, 4, ENC_BIG_ENDIAN);
311                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_route, tvb, offset, 4, ENC_BIG_ENDIAN);
312                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp_snoop, tvb, offset, 4, ENC_BIG_ENDIAN);
313                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gmrp, tvb, offset, 4, ENC_BIG_ENDIAN);
314                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gvrp, tvb, offset, 4, ENC_BIG_ENDIAN);
315                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_8021q, tvb, offset, 4, ENC_BIG_ENDIAN);
316                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_dvmrp, tvb, offset, 4, ENC_BIG_ENDIAN);
317                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ospf, tvb, offset, 4, ENC_BIG_ENDIAN);
318                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_bgp, tvb, offset, 4, ENC_BIG_ENDIAN);
319                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_rip, tvb, offset, 4, ENC_BIG_ENDIAN);
320                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp, tvb, offset, 4, ENC_BIG_ENDIAN);
321                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ssr, tvb, offset, 4, ENC_BIG_ENDIAN);
322                                 break;
323                         case EDP_DEVICE_TYPE_BRIDGE:
324                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_level1, tvb, offset, 4, ENC_BIG_ENDIAN);
325                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_trans, tvb, offset, 4, ENC_BIG_ENDIAN);
326                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_route, tvb, offset, 4, ENC_BIG_ENDIAN);
327                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_igmp, tvb, offset, 4, ENC_BIG_ENDIAN);
328                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gmrp, tvb, offset, 4, ENC_BIG_ENDIAN);
329                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gvrp, tvb, offset, 4, ENC_BIG_ENDIAN);
330                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_8021q, tvb, offset, 4, ENC_BIG_ENDIAN);
331                                 break;
332                         case EDP_DEVICE_TYPE_VLANMAN:
333                                 break;
334                         case EDP_DEVICE_TYPE_NTSERVER:
335                         case EDP_DEVICE_TYPE_NTCLIENT:
336                         case EDP_DEVICE_TYPE_WIN95:
337                         case EDP_DEVICE_TYPE_WIN98:
338                         case EDP_DEVICE_TYPE_UNIXSERVER:
339                         case EDP_DEVICE_TYPE_UNIXCLIENT:
340                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_ad, tvb, offset, 4, ENC_BIG_ENDIAN);
341                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dns, tvb, offset, 4, ENC_BIG_ENDIAN);
342                                 proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dhcp, tvb, offset, 4, ENC_BIG_ENDIAN);
343                                 break;
344                         case EDP_DEVICE_TYPE_ACCESSPOINT:
345                         default:
346                                 break;
347                 }
348                 offset += 4;
349
350                 /* determine the number of neighbors and create EDP neighbors subtree */
351                 num_neighbors = tvb_get_ntohs(tvb, offset);
352                 proto_tree_add_item(edp_tree, hf_ismp_edp_num_neighbors, tvb, offset, 2, ENC_BIG_ENDIAN);
353                 offset += 2;
354                 if (num_neighbors > 0)
355                 {
356                         edp_neighbors_ti = proto_tree_add_item(edp_tree, hf_ismp_edp_neighbors, tvb,
357                                                                                 offset, num_neighbors*10, ENC_NA);
358                         edp_neighbors_tree = proto_item_add_subtree(edp_neighbors_ti, ett_ismp_edp_neighbors);
359                         while ( neighbors_count < num_neighbors && tvb_reported_length_remaining(tvb, offset) >= 10)
360                         {
361                                 edp_neighbors_leaf_ti = proto_tree_add_text(edp_neighbors_tree, tvb, offset, 10,
362                                                                                 "Neighbor%d", (neighbors_count+1));
363                                 edp_neighbors_leaf_tree = proto_item_add_subtree(edp_neighbors_leaf_ti, ett_ismp_edp_neighbors_leaf);
364
365                                 proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 6,
366                                         "MAC Address: %s", tvb_ether_to_str(tvb, offset));
367                                 proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 4,
368                                         "Assigned Neighbor State 0x%04x", tvb_get_ntohl(tvb, offset));
369                                 offset += 10;
370                                 neighbors_count++;
371                         }
372                         if (neighbors_count != num_neighbors)
373                         {
374                                 proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
375                                 "MALFORMED PACKET");
376                                 return;
377                         }
378                 }
379
380                 /* determine data remains, if so, count tuples
381                    and create EDP tuples subtree */
382                 if (tvb_reported_length_remaining(tvb, offset) != 0 &&
383                         tvb_reported_length_remaining(tvb, offset) >= 2)
384                 {
385                         num_tuples = tvb_get_ntohs(tvb, offset);
386                         proto_tree_add_item(edp_tree, hf_ismp_edp_num_tuples, tvb, offset, 2, ENC_BIG_ENDIAN);
387                         offset += 2;
388                 }
389                 else if (tvb_reported_length_remaining(tvb, offset) > 0) {
390                         proto_tree_add_text(edp_tree, tvb, offset,
391                                 tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
392                         return;
393                 }
394                 else
395                 {
396                         return;
397                 }
398
399                 /* start populating tuple information */
400                 if (num_tuples && tvb_reported_length_remaining(tvb, offset) >= 4)
401                 {
402                         edp_tuples_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_tuples, tvb,
403                                 offset, tvb_reported_length_remaining(tvb, offset), NULL, "Tuples");
404                         edp_tuples_tree = proto_item_add_subtree(edp_tuples_ti, ett_ismp_edp_tuples);
405
406                         while ( (tuples_count < num_tuples) && (tvb_reported_length_remaining(tvb, offset) >= 4) )
407                         {
408
409                                 tuple_length = tvb_get_ntohs(tvb, offset+2);
410                                 edp_tuples_leaf_ti = proto_tree_add_text(edp_tuples_tree, tvb, offset, tuple_length,
411                                         "Tuple%d", tuples_count+1);
412
413                                 edp_tuples_leaf_tree = proto_item_add_subtree(edp_tuples_leaf_ti, ett_ismp_edp_tuples_leaf);
414
415                                 tuple_type = tvb_get_ntohs(tvb, offset);
416                                 proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
417                                         "Tuple Type: %s(%d)", val_to_str_const( tuple_type, edp_tuple_types, "Unknown"), tuple_type );
418                                 offset += 2;
419                                 proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
420                                         "Tuple Length: %d", tuple_length);
421                                 offset += 2;
422
423                                 if (tvb_reported_length_remaining(tvb, offset) >= tuple_length)
424                                 {
425                                         tvb_ensure_bytes_exist(tvb, offset, tuple_length);
426                                         switch (tuple_type)
427                                         {
428                                                 case EDP_TUPLE_HOLD:
429                                                         proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
430                                                                 "Hold Time = %d", tvb_get_ntohs(tvb, offset));
431                                                         break;
432                                                 case EDP_TUPLE_INT_NAME:
433                                                         proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
434                                                                 "Interface Name = %s", tvb_format_text(tvb, offset, tuple_length));
435                                                         col_append_fstr(pinfo->cinfo, COL_INFO, ", ifName %s",
436                                                                 tvb_format_text(tvb, offset, tuple_length));
437                                                         break;
438                                                 case EDP_TUPLE_SYS_DESCRIPT:
439                                                         proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
440                                                                 "System Description = %s", tvb_format_text(tvb, offset, tuple_length));
441                                                         break;
442                                                 case EDP_TUPLE_IPX_ADDR:
443                                                         proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
444                                                                 "Interface IPX_address = %s",
445                                                                 ipx_addr_to_str(tvb_get_ntohl(tvb, offset),
446                                                                 tvb_get_string(wmem_packet_scope(), tvb, offset+4, tuple_length-4)));
447                                                         break;
448                                                 case EDP_TUPLE_UNKNOWN:
449                                                 default:
450                                                         proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
451                                                                 "Unknown Tuple Data %s", tvb_format_text(tvb, offset, tuple_length));
452                                                         break;
453                                         }
454                                 }
455                                 offset += tuple_length;
456
457                                 tuples_count++;
458                         }
459                         if (tuples_count != num_tuples)
460                         {
461                                 proto_tree_add_text(edp_tree, tvb, offset,
462                                         tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
463                                 return;
464                         }
465                         else
466                         {
467                                 return;
468                         }
469                 }
470
471         }
472
473
474 }
475
476
477 /* Code to actually dissect the packets */
478 static void
479 dissect_ismp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
480 {
481         int offset = 0;
482         guint16 message_type = 0;
483         guint8 code_length = 0;
484         guint8 weird_stuff[3] = { 0x42, 0x42, 0x03 };
485
486 /* Set up structures needed to add the protocol subtree and manage it */
487         proto_item *ti;
488         proto_tree *ismp_tree;
489
490 /* Make entries in Protocol column and Info column on summary display */
491         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP");
492         col_clear(pinfo->cinfo, COL_INFO);
493
494         /*
495          * XXX - I've seen captures with packets that have the ISMP
496          * Ethernet frame type, but with the payload being 0x42 0x42 0x03
497          * followed by what appears to be an ISMP frame.
498          *
499          * 0x4242 is not a valid ISMP version number.
500          */
501         if (tvb_memeql(tvb, offset, weird_stuff, sizeof weird_stuff) == 0)
502                 offset += 3;    /* skip the weird stuff, for now */
503         if (tree) {
504                 /* create display subtree for ismp */
505                 ti = proto_tree_add_item(tree, proto_ismp, tvb, offset, -1, ENC_NA);
506
507                 ismp_tree = proto_item_add_subtree(ti, ett_ismp);
508
509                 /* add an items to the subtree */
510                 proto_tree_add_item(ismp_tree, hf_ismp_version, tvb, offset, 2, ENC_BIG_ENDIAN);
511                 offset += 2;
512                 message_type = tvb_get_ntohs(tvb, offset);
513                 proto_tree_add_item(ismp_tree, hf_ismp_message_type, tvb, offset, 2, ENC_BIG_ENDIAN);
514                 offset += 2;
515                 proto_tree_add_item(ismp_tree, hf_ismp_seq_num, tvb, offset, 2, ENC_BIG_ENDIAN);
516                 offset += 2;
517                 code_length = tvb_get_guint8(tvb, offset);
518                 proto_tree_add_item(ismp_tree, hf_ismp_code_length, tvb, offset, 1, ENC_BIG_ENDIAN);
519                 offset += 1;
520                 proto_tree_add_item(ismp_tree, hf_ismp_auth_data, tvb, offset, code_length, ENC_NA);
521                 offset += code_length;
522
523                 /* if Enterasys Discover Protocol, dissect it */
524                 if(message_type == ISMPTYPE_EDP)
525                         dissect_ismp_edp(tvb, pinfo, offset, tree);
526         }
527
528 }
529
530
531 /* Register this protocol with Wireshark */
532 void
533 proto_register_ismp(void)
534 {
535
536 /* Setup list of header fields  See Section 1.6.1 for details*/
537         static hf_register_info hf[] = {
538 #if 0
539                 { &hf_ismp,
540                         { "ISMP", "ismp",
541                         FT_PROTOCOL, BASE_NONE, NULL, 0x0,
542                         "Inter Switch Message Protocol", HFILL }
543                 },
544 #endif
545                 { &hf_ismp_version,
546                         { "Version",           "ismp.version",
547                         FT_UINT16, BASE_DEC, NULL, 0x0,
548                         NULL, HFILL }
549                 },
550                 { &hf_ismp_message_type,
551                         { "Message Type", "ismp.msgtype",
552                         FT_UINT16, BASE_DEC, NULL, 0x0,
553                         NULL, HFILL }
554                 },
555                 { &hf_ismp_seq_num,
556                         { "Sequence Number", "ismp.seqnum",
557                         FT_UINT16, BASE_DEC, NULL, 0x0,
558                         NULL, HFILL }
559                 },
560                 { &hf_ismp_code_length,
561                         { "Auth Code Length", "ismp.codelen",
562                         FT_UINT8, BASE_DEC, NULL, 0x0,
563                         NULL, HFILL }
564                 },
565                 { &hf_ismp_auth_data,
566                         { "Auth Data", "ismp.authdata",
567                         FT_BYTES, BASE_NONE, NULL, 0x0,
568                         NULL, HFILL }
569                 },
570                 { &hf_ismp_edp,
571                         { "EDP", "ismp.edp",
572                         FT_PROTOCOL, BASE_NONE, NULL, 0x0,
573                         "Enterasys Discovery Protocol", HFILL }
574                 },
575                 { &hf_ismp_edp_version,
576                         { "Version", "ismp.edp.version",
577                         FT_UINT16, BASE_DEC, NULL, 0x0,
578                         NULL, HFILL }
579                 },
580                 { &hf_ismp_edp_module_ip,
581                         { "Module IP Address", "ismp.edp.modip",
582                         FT_IPv4, BASE_NONE, NULL, 0x0,
583                         NULL, HFILL }
584                 },
585                 { &hf_ismp_edp_module_mac,
586                         { "Module MAC Address", "ismp.edp.modmac",
587                         FT_ETHER, BASE_NONE, NULL, 0x0,
588                         NULL, HFILL }
589                 },
590                 { &hf_ismp_edp_module_port,
591                         { "Module Port (ifIndex num)", "ismp.edp.modport",
592                         FT_UINT32, BASE_DEC, NULL, 0x0,
593                         NULL, HFILL }
594                 },
595                 { &hf_ismp_edp_chassis_mac,
596                         { "Chassis MAC Address", "ismp.edp.chassismac",
597                         FT_ETHER, BASE_NONE, NULL, 0x0,
598                         NULL, HFILL }
599                 },
600                 { &hf_ismp_edp_chassis_ip,
601                         { "Chassis IP Address", "ismp.edp.chassisip",
602                         FT_IPv4, BASE_NONE, NULL, 0x0,
603                         NULL, HFILL }
604                 },
605                 { &hf_ismp_edp_device_type,
606                         { "Device Type", "ismp.edp.devtype",
607                         FT_UINT16, BASE_DEC, edp_device_types, 0x0,
608                         NULL, HFILL }
609                 },
610                 { &hf_ismp_edp_module_rev,
611                         { "Module Firmware Revision", "ismp.edp.rev",
612                         FT_UINT32, BASE_DEC, NULL, 0x0,
613                         NULL, HFILL }
614                 },
615                 { &hf_ismp_edp_options,
616                         { "Device Options", "ismp.edp.options",
617                         FT_UINT32, BASE_DEC, NULL, 0x0,
618                         NULL, HFILL }
619                 },
620                 { &hf_ismp_edp_sfs_option_unused1,
621                         { "Unused", "ismp.edp.sfs_option_unused1",
622                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UNUSED1,
623                         NULL, HFILL }
624                 },
625                 { &hf_ismp_edp_sfs_option_sfssup,
626                         { "SFS Support", "ismp.edp.sfs_option_sfssup",
627                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_SFSSUP,
628                         NULL, HFILL }
629                 },
630                 { &hf_ismp_edp_sfs_option_lsp,
631                         { "LSP Support", "ismp.edp.sfs_option_lsp",
632                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_LSP,
633                         NULL, HFILL }
634                 },
635                 { &hf_ismp_edp_sfs_option_flood,
636                         { "Flood Path Support", "ismp.edp.sfs_option_flood",
637                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_FLOOD,
638                         NULL, HFILL }
639                 },
640                 { &hf_ismp_edp_sfs_option_resolve,
641                         { "Resolve Support", "ismp.edp.sfs_option_resolve",
642                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_RESOLVE,
643                         NULL, HFILL }
644                 },
645                 { &hf_ismp_edp_sfs_option_unused2,
646                         { "Unused", "ismp.edp.sfs_option_unused2",
647                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UNUSED2,
648                         NULL, HFILL }
649                 },
650                 { &hf_ismp_edp_sfs_option_tagflood,
651                         { "Tagged Flood Support", "ismp.edp.sfs_option_tagflood",
652                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_TAGFLOOD,
653                         NULL, HFILL }
654                 },
655                 { &hf_ismp_edp_sfs_option_calltap,
656                         { "Call Tap Support", "ismp.edp.sfs_option_calltap",
657                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_CALLTAP,
658                         NULL, HFILL }
659                 },
660                 { &hf_ismp_edp_sfs_option_conmsg,
661                         { "Connection Message Support", "ismp.edp.sfs_option_conmsg",
662                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_CONMSG,
663                         NULL, HFILL }
664                 },
665                 { &hf_ismp_edp_sfs_option_redun,
666                         { "Redundant Access Support", "ismp.edp.sfs_option_redun",
667                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_REDUN,
668                         NULL, HFILL }
669                 },
670                 { &hf_ismp_edp_sfs_option_isolated,
671                         { "Isolated Switch", "ismp.edp.sfs_option_isolated",
672                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_ISOLATED,
673                         NULL, HFILL }
674                 },
675                 { &hf_ismp_edp_sfs_option_uplink_switch,
676                         { "Uplink Switch", "ismp.edp.sfs_option_uplink_switch",
677                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_SWITCH,
678                         NULL, HFILL }
679                 },
680                 { &hf_ismp_edp_sfs_option_uplink_core,
681                         { "Uplink Core", "ismp.edp.sfs_option_uplink_core",
682                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_CORE,
683                         NULL, HFILL }
684                 },
685                 { &hf_ismp_edp_sfs_option_uplink_port,
686                         { "Uplink Port", "ismp.edp.sfs_option_uplink_port",
687                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_PORT,
688                         NULL, HFILL }
689                 },
690                 { &hf_ismp_edp_sfs_option_uplink_flood,
691                         { "Uplink Flood Support", "ismp.edp.sfs_option_uplink_flood",
692                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SFS_OPTION_UPLINK_FLOOD,
693                         NULL, HFILL }
694                 },
695                 { &hf_ismp_edp_rtr_option_ssr,
696                         { "SSR Type Device", "ismp.edp.rtr_option_ssr",
697                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_SSR,
698                         NULL, HFILL }
699                 },
700                 { &hf_ismp_edp_rtr_option_igmp,
701                         { "IGMP Active", "ismp.edp.rtr_option_igmp",
702                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_IGMP,
703                         NULL, HFILL }
704                 },
705                 { &hf_ismp_edp_rtr_option_rip,
706                         { "RIP Active", "ismp.edp.rtr_option_rip",
707                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_RIP,
708                         NULL, HFILL }
709                 },
710                 { &hf_ismp_edp_rtr_option_bgp,
711                         { "BGP Active", "ismp.edp.rtr_option_bgp",
712                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_BGP,
713                         NULL, HFILL }
714                 },
715                 { &hf_ismp_edp_rtr_option_ospf,
716                         { "OSPF Active", "ismp.edp.rtr_option_ospf",
717                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_OSPF,
718                         NULL, HFILL }
719                 },
720                 { &hf_ismp_edp_rtr_option_dvmrp,
721                         { "DVMRP Active", "ismp.edp.rtr_option_dvmrp",
722                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_DVMRP,
723                         NULL, HFILL }
724                 },
725                 { &hf_ismp_edp_rtr_option_8021q,
726                         { "802.1Q Support", "ismp.edp.rtr_option_8021q",
727                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_8021Q,
728                         NULL, HFILL }
729                 },
730                 { &hf_ismp_edp_rtr_option_gvrp,
731                         { "GVRP Support", "ismp.edp.rtr_option_gvrp",
732                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_GVRP,
733                         NULL, HFILL }
734                 },
735                 { &hf_ismp_edp_rtr_option_gmrp,
736                         { "GMRP Support", "ismp.edp.rtr_option_gmrp",
737                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_GMRP,
738                         NULL, HFILL }
739                 },
740                 { &hf_ismp_edp_rtr_option_igmp_snoop,
741                         { "IGMP Snooping Support", "ismp.edp.rtr_option_igmp_snoop",
742                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_IGMP_SNOOP,
743                         NULL, HFILL }
744                 },
745                 { &hf_ismp_edp_rtr_option_route,
746                         { "Route Bridging", "ismp.edp.rtr_option_route",
747                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_ROUTE,
748                         NULL, HFILL }
749                 },
750                 { &hf_ismp_edp_rtr_option_trans,
751                         { "Transparent Bridging", "ismp.edp.rtr_option_trans",
752                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_TRANS,
753                         NULL, HFILL }
754                 },
755                 { &hf_ismp_edp_rtr_option_level1,
756                         { "Level 1 Functionality", "ismp.edp.rtr_option_level1",
757                         FT_BOOLEAN, 32, TFS(&is_set), EDP_RTR_OPTION_LEVEL1,
758                         NULL, HFILL }
759                 },
760                 { &hf_ismp_edp_switch_option_8021q,
761                         { "802.1Q Support", "ismp.edp.switch_option_8021q",
762                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_8021Q,
763                         NULL, HFILL }
764                 },
765                 { &hf_ismp_edp_switch_option_gvrp,
766                         { "GVRP Support", "ismp.edp.switch_option_gvrp",
767                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_GVRP,
768                         NULL, HFILL }
769                 },
770                 { &hf_ismp_edp_switch_option_gmrp,
771                         { "GMRP Support", "ismp.edp.switch_option_gmrp",
772                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_GMRP,
773                         NULL, HFILL }
774                 },
775                 { &hf_ismp_edp_switch_option_igmp,
776                         { "IGMP Snooping Support", "ismp.edp.switch_option_igmp",
777                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_IGMP,
778                         NULL, HFILL }
779                 },
780                 { &hf_ismp_edp_switch_option_route,
781                         { "Route Bridging", "ismp.edp.switch_option_route",
782                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_ROUTE,
783                         NULL, HFILL }
784                 },
785                 { &hf_ismp_edp_switch_option_trans,
786                         { "Transparent Bridging", "ismp.edp.switch_option_trans",
787                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_TRANS,
788                         NULL, HFILL }
789                 },
790                 { &hf_ismp_edp_switch_option_level1,
791                         { "Level 1 Functionality", "ismp.edp.switch_option_level1",
792                         FT_BOOLEAN, 32, TFS(&is_set), EDP_SWITCH_OPTION_LEVEL1,
793                         NULL, HFILL }
794                 },
795                 { &hf_ismp_edp_end_station_option_dhcp,
796                         { "DHCP Enabled", "ismp.edp.end_station_option_dhcp",
797                         FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_DHCP,
798                         NULL, HFILL }
799                 },
800                 { &hf_ismp_edp_end_station_option_dns,
801                         { "DNS Enabled", "ismp.edp.end_station_option_dns",
802                         FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_DNS,
803                         NULL, HFILL }
804                 },
805                 { &hf_ismp_edp_end_station_option_ad,
806                         { "Active Directory Enabled", "ismp.edp.end_station_option_ad",
807                         FT_BOOLEAN, 32, TFS(&is_set), EDP_END_STATION_OPTION_AD,
808                         NULL, HFILL }
809                 },
810                 { &hf_ismp_edp_num_neighbors,
811                         { "Number of Known Neighbors", "ismp.edp.maccount",
812                         FT_UINT16, BASE_DEC, NULL, 0x0,
813                         NULL, HFILL }
814                 },
815                 { &hf_ismp_edp_neighbors,
816                         { "Neighbors", "ismp.edp.nbrs",
817                         FT_BYTES, BASE_NONE, NULL, 0x0,
818                         NULL, HFILL }
819                 },
820                 { &hf_ismp_edp_num_tuples,
821                         { "Number of Tuples", "ismp.edp.numtups",
822                         FT_UINT16, BASE_DEC, NULL, 0x0,
823                         NULL, HFILL }
824                 },
825                 { &hf_ismp_edp_tuples,
826                         { "Number of Tuples", "ismp.edp.tups",
827                         FT_BYTES, BASE_NONE, NULL, 0x0,
828                         NULL, HFILL }
829                 },
830         };
831
832 /* Setup protocol subtree array */
833         static gint *ett[] = {
834                 &ett_ismp,
835                 &ett_ismp_edp,
836                 &ett_ismp_edp_options,
837                 &ett_ismp_edp_neighbors,
838                 &ett_ismp_edp_neighbors_leaf,
839                 &ett_ismp_edp_tuples,
840                 &ett_ismp_edp_tuples_leaf,
841         };
842
843 /* Register the protocol name and description */
844         proto_ismp = proto_register_protocol("InterSwitch Message Protocol",
845             "ISMP", "ismp");
846
847 /* Required function calls to register the header fields and subtrees used */
848         proto_register_field_array(proto_ismp, hf, array_length(hf));
849         proto_register_subtree_array(ett, array_length(ett));
850 }
851
852
853 /* If this dissector uses sub-dissector registration add a registration routine.
854    This format is required because a script is used to find these routines and
855    create the code that calls these routines.
856 */
857 void
858 proto_reg_handoff_ismp(void)
859 {
860         dissector_handle_t ismp_handle;
861
862         ismp_handle = create_dissector_handle(dissect_ismp,
863             proto_ismp);
864         dissector_add_uint("ethertype", ETHERTYPE_ISMP, ismp_handle);
865 }