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