Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-extreme.c
1 /* packet-extreme.c
2  * Routines for the disassembly of Extreme Networks specific
3  * protocols (EDP/ESRP/EAPS(including ESL)/ELSM)
4  *
5  * $Id$
6  *
7  * Copyright 2005 Joerg Mayer (see AUTHORS file)
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28 /*
29   TODO:
30   - General
31    EAPS v2 is not supported (no spec)
32    Some stuff in the EDP Info field (no spec)
33   - Things seen in traces
34    Flags in the EDP Vlan field (value 0x01)
35   - TLV type 0x0e (ESL) shared link managemnt
36    TLV type 0x15 (XOS only?)
37    EAPS type 0x10 (ESL?)
38    ESRP state 0x03
39
40 Specs:
41
42 EAPS v1 is specified in RFC3619
43
44 The following information is taken from the Extreme knowledge base
45 (login required). Search for ESRP.
46 Note: The information seems to be incorrect in at least one place
47       (position of edp.vlan.id).
48
49 ================================ snip ================================
50
51 ESRP Packet Format:
52 -------------------
53
54  0                               1
55  0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0000
57 |                       SOURCE MAC ADDRESS                      |
58 +-------------------------------+-------------------------------+ 0004
59 |   SOURCE MAC ADDRESS (CONT)   |        DEST MAC ADDRESS       |
60 +-------------------------------+-------------------------------+ 0008
61 |                    DEST MAC ADDRESS (CONT)                    |
62 +-------------------------------+---------------+---------------+ 000C
63 |            LENGTH             |  DSAP = AA    |  SSAP = AA    |
64 +---------------+---------------+---------------+---------------+ 0010
65 | LLC TYPE = UI |                  UID = 00E02B                 |
66 +---------------+---------------+---------------+---------------+ 0014
67 |         SNAP TYPE = 00BB      |   EDP VERSION |   RESERVED    |
68 +-------------------------------+---------------+---------------+ 0018
69 |            LENGTH             |           CHECKSUM            |
70 +-------------------------------+-------------------------------+ 001C
71 |        SEQUENCE NUMBER        |          MACHINE ID           |
72 +-------------------------------+-------------------------------+ 0020
73 |                      MACHINE ID (CONT.)                       |
74 +-------------------------------+---------------+---------------+ 0024
75 |      MACHINE ID (CONT.)       | MARKER=99(EDP)| TYPE=08 (ESRP)|
76 +-------------------------------+---------------+---------------+ 0028
77 |         LENGTH = 001C         |0=IP 1=IPX 2=L2|   GROUP = 0   |
78 +-------------------------------+-------------------------------+ 002C
79 |           PRIORITY            |  STATE: 0=?? 1=MSTR 2=SLAVE   |
80 +-------------------------------+-------------------------------+ 0030
81 |    NUMBER OF ACTIVE PORTS     |      VIRTUAL IP ADDRESS       |
82 +-------------------------------+-------------------------------+ 0034
83 |  VIRTUAL IP ADDRESS (CONT)    |     SYSTEM MAC ADDRESS        |
84 +-------------------------------+-------------------------------+ 0038
85 |                   SYSTEM MAC ADDRESS (CONT.)                  |
86 +-------------------------------+-------------------------------+ 003C
87 |         HELLO TIMER           |           RESERVED            |
88 +-------------------------------+-------------------------------+ 0040
89
90
91 ******************************************************************************
92
93
94 EDP is a SNAP encapsulated frame.  The top level looks like this:
95 The top level format is like this:
96 [ SNAP header ] [ EDP header] [ TLV 0 ] [ TLV 1 ] ... [ TLV N ]
97
98 Header format:
99 1 octet: EDP version
100 1 octet: reserved
101 2 octets: length
102 2 octets: checksum
103 2 octets: sequence #
104 8 octets: device id (currently 2 0 octets followed by system mac address)
105
106 TLV stands for Type, Length, Value.
107 Format of a TLV entry:
108 marker ( 1 octet): Hex 99
109 type ( 1 octet):
110         The following types are used:
111               Null (used as an end signal): 0
112               Display (Mib II display string): 1
113               Info (Basic system information): 2
114               Vlan Info                      : 5
115               ESRP                           : 8
116 Length: Length of subsequent data(2 octets)
117 Value: Length octets of data.
118
119 Format for Info TLV:
120 two octets: originating slot #
121 two octets: originating port #
122 two octets: Virtual Chassis Id (If originating port is connected to a virtual chassis).
123 six octets: reserved
124 four octets: software version
125 16 octets: Virtual Chassis Id connections
126
127 Format for Vlan info:
128 octet 0: Flags (bit 8 = 1 means this vlan has an IP interface)
129 octets 1,2,3: reserved.
130 octets 4,5: vlan Id (0 if untagged)
131 octets 6,7: reserved.
132 octets 8 - 11: Vlan IP address.
133 Rest of value: VLAN name.
134
135 Display string is merely length octets of the MIBII display string.
136
137 These are the structures you will see most often in EDP frames.
138
139 ================================ snap ================================
140
141  */
142
143 #ifdef HAVE_CONFIG_H
144 #  include "config.h"
145 #endif
146
147 #include <string.h>
148 #include <glib.h>
149 #include <epan/packet.h>
150 #include <epan/strutil.h>
151 #include <epan/in_cksum.h>
152 #include "packet-llc.h"
153 #include <epan/oui.h>
154
155 static int hf_llc_extreme_pid = -1;
156
157 static int proto_edp = -1;
158 /* EDP header */
159 static int hf_edp_version = -1;
160 static int hf_edp_reserved = -1;
161 static int hf_edp_length = -1;
162 static int hf_edp_checksum = -1;
163 static int hf_edp_checksum_good = -1;
164 static int hf_edp_checksum_bad = -1;
165
166 static int hf_edp_seqno = -1;
167 static int hf_edp_midtype = -1;
168 static int hf_edp_midmac = -1;
169 /* TLV header */
170 static int hf_edp_tlv_marker = -1;
171 static int hf_edp_tlv_type = -1;
172 static int hf_edp_tlv_length = -1;
173 /* Display string */
174 static int hf_edp_display = -1;
175 static int hf_edp_display_string = -1;
176 /* Info element */
177 static int hf_edp_info = -1;
178 static int hf_edp_info_slot = -1;
179 static int hf_edp_info_port = -1;
180 static int hf_edp_info_vchassid = -1;
181 static int hf_edp_info_reserved = -1;
182 static int hf_edp_info_version = -1;
183 static int hf_edp_info_version_major1 = -1;
184 static int hf_edp_info_version_major2 = -1;
185 static int hf_edp_info_version_sustaining = -1;
186 static int hf_edp_info_version_internal = -1;
187 static int hf_edp_info_vchassconn = -1;
188 /* Vlan element */
189 static int hf_edp_vlan = -1;
190 static int hf_edp_vlan_flags = -1;
191 static int hf_edp_vlan_flags_ip = -1;
192 static int hf_edp_vlan_flags_reserved = -1;
193 static int hf_edp_vlan_flags_unknown = -1;
194 static int hf_edp_vlan_reserved1 = -1;
195 static int hf_edp_vlan_id = -1;
196 static int hf_edp_vlan_reserved2 = -1;
197 static int hf_edp_vlan_ip = -1;
198 static int hf_edp_vlan_name = -1;
199 /* ESRP element */
200 static int hf_edp_esrp = -1;
201 static int hf_edp_esrp_proto = -1;
202 static int hf_edp_esrp_group = -1;
203 static int hf_edp_esrp_prio = -1;
204 static int hf_edp_esrp_state = -1;
205 static int hf_edp_esrp_ports = -1;
206 static int hf_edp_esrp_virtip = -1;
207 static int hf_edp_esrp_sysmac = -1;
208 static int hf_edp_esrp_hello = -1;
209 static int hf_edp_esrp_reserved = -1;
210 /* EAPS element */
211 static int hf_edp_eaps = -1;
212 static int hf_edp_eaps_ver = -1;
213 static int hf_edp_eaps_type = -1;
214 static int hf_edp_eaps_ctrlvlanid = -1;
215 static int hf_edp_eaps_reserved0 = -1;
216 static int hf_edp_eaps_sysmac = -1;
217 static int hf_edp_eaps_hello = -1;
218 static int hf_edp_eaps_fail = -1;
219 static int hf_edp_eaps_state = -1;
220 static int hf_edp_eaps_reserved1 = -1;
221 static int hf_edp_eaps_helloseq = -1;
222 static int hf_edp_eaps_reserved2 = -1;
223 /* ESL element */
224 static int hf_edp_esl = -1;
225 static int hf_edp_esl_ver = -1;
226 static int hf_edp_esl_type = -1;
227 static int hf_edp_esl_ctrlvlanid = -1;
228 static int hf_edp_esl_reserved0 = -1;
229 static int hf_edp_esl_sysmac = -1;
230 static int hf_edp_esl_reserved1 = -1;
231 static int hf_edp_esl_state = -1;
232 static int hf_edp_esl_linkrole = -1;
233 static int hf_edp_esl_linkid1 = -1;
234 static int hf_edp_esl_failed1 = -1;
235 static int hf_edp_esl_failed2 = -1;
236 static int hf_edp_esl_reserved4 = -1;
237 static int hf_edp_esl_linkid2 = -1;
238 static int hf_edp_esl_reserved5 = -1;
239 static int hf_edp_esl_numlinks = -1;
240 static int hf_edp_esl_linklist = -1;
241 static int hf_edp_esl_rest = -1;
242 /* ELSM (Extreme Link Status Monitoring) */
243 static int hf_edp_elsm = -1;
244 static int hf_edp_elsm_type = -1;
245 static int hf_edp_elsm_subtype = -1;
246 static int hf_edp_elsm_magic = -1;
247 /* ELRP (Extreme Loop Recognition Protocol)*/
248 static int hf_edp_elrp = -1;
249 static int hf_edp_elrp_unknown = -1;
250 /* Unknown element */
251 static int hf_edp_unknown = -1;
252 static int hf_edp_unknown_data = -1;
253 /* Null element */
254 static int hf_edp_null = -1;
255
256 static gint ett_edp = -1;
257 static gint ett_edp_checksum = -1;
258 static gint ett_edp_tlv_header = -1;
259 static gint ett_edp_display = -1;
260 static gint ett_edp_info = -1;
261 static gint ett_edp_info_version = -1;
262 static gint ett_edp_vlan = -1;
263 static gint ett_edp_vlan_flags = -1;
264 static gint ett_edp_esrp = -1;
265 static gint ett_edp_eaps = -1;
266 static gint ett_edp_esl = -1;
267 static gint ett_edp_elrp = -1;
268 static gint ett_edp_elsm = -1;
269 static gint ett_edp_unknown = -1;
270 static gint ett_edp_null = -1;
271
272 #define PROTO_SHORT_NAME "EDP"
273 #define PROTO_LONG_NAME "Extreme Discovery Protocol"
274
275 static const value_string extreme_pid_vals[] = {
276         { 0x00bb,       "EDP" },
277
278         { 0,            NULL }
279 };
280
281 static const value_string esrp_proto_vals[] = {
282         { 0,    "IP" },
283         { 1,    "IPX" },
284         { 2,    "L2" },
285
286         { 0, NULL }
287 };
288
289 static const value_string esrp_state_vals[] = {
290         { 0,    "??" },
291         { 1,    "Master" },
292         { 2,    "Slave" },
293
294         { 0, NULL }
295 };
296
297 typedef enum {
298         EDP_TYPE_NULL = 0,
299         EDP_TYPE_DISPLAY,
300         EDP_TYPE_INFO,
301         EDP_TYPE_VLAN = 5,
302         EDP_TYPE_ESRP = 8,
303         EDP_TYPE_EAPS = 0xb,
304         EDP_TYPE_ELRP = 0xd,
305         EDP_TYPE_ESL,
306         EDP_TYPE_ELSM
307 } edp_type_t;
308
309 static const value_string edp_type_vals[] = {
310         { EDP_TYPE_NULL,        "Null"},
311         { EDP_TYPE_DISPLAY,     "Display"},
312         { EDP_TYPE_INFO,        "Info"},
313         { EDP_TYPE_VLAN,        "VL"},
314         { EDP_TYPE_ESRP,        "ESRP"},
315         { EDP_TYPE_EAPS,        "EAPS"},
316         { EDP_TYPE_ELRP,        "ELRP"},
317         { EDP_TYPE_ESL,         "ESL"},
318         { EDP_TYPE_ELSM,        "ELSM"},
319
320         { 0,    NULL }
321 };
322
323 static const value_string edp_midtype_vals[] = {
324         { 0,    "MAC" },
325
326         { 0,    NULL }
327 };
328
329 static const value_string eaps_type_vals[] = {
330         { 5,    "Health" },
331         { 6,    "Ring up flush fdb" },
332         { 7,    "Ring down flush fdb" },
333         { 8,    "Link down" },
334
335         { 0,    NULL }
336 };
337
338 static const value_string eaps_state_vals[] = {
339         { 0,    "Idle" },
340         { 1,    "Complete" },
341         { 2,    "Failed" },
342         { 3,    "Links up" },
343         { 4,    "Links down" },
344         { 5,    "Pre Forwarding" },
345
346         { 0,    NULL }
347 };
348
349 static const value_string esl_role_vals[] = {
350         { 1,    "Controller" },
351         { 2,    "Partner" },
352
353         { 0,    NULL }
354 };
355
356 static const value_string esl_state_vals[] = {
357         { 1,    "Ready" },
358         { 2,    "Blocking" },
359
360         { 0,    NULL }
361 };
362
363 static const value_string esl_type_vals[] = {
364         { 1,    "Segment Health" },
365
366         { 0,    NULL }
367 };
368
369 static const value_string elsm_type_vals[] = {
370         { 0x01,         "Hello" },
371
372         { 0,            NULL }
373 };
374
375 static const value_string elsm_subtype_vals[] = {
376         { 0x00,         "-" },
377         { 0x01,         "+" },
378
379         { 0,            NULL }
380 };
381
382 static int
383 dissect_tlv_header(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, int length _U_, proto_tree *tree)
384 {
385         proto_item      *tlv_item;
386         proto_tree      *tlv_tree;
387         guint8          tlv_marker;
388         guint8          tlv_type;
389         guint16         tlv_length;
390
391         tlv_marker = tvb_get_guint8(tvb, offset),
392         tlv_type = tvb_get_guint8(tvb, offset + 1);
393         tlv_length = tvb_get_ntohs(tvb, offset + 2);
394
395         tlv_item = proto_tree_add_text(tree, tvb, offset, 4,
396                 "Marker 0x%02x, length %d, type %d = %s",
397                 tlv_marker, tlv_length, tlv_type,
398                 val_to_str(tlv_type, edp_type_vals, "Unknown (0x%02x)"));
399
400         tlv_tree = proto_item_add_subtree(tlv_item, ett_edp_tlv_header);
401         proto_tree_add_item(tlv_tree, hf_edp_tlv_marker, tvb, offset, 1,
402                 ENC_BIG_ENDIAN);
403         offset += 1;
404
405         proto_tree_add_uint(tlv_tree, hf_edp_tlv_type, tvb, offset, 1,
406                 tlv_type);
407         offset += 1;
408
409         proto_tree_add_uint(tlv_tree, hf_edp_tlv_length, tvb, offset, 2,
410                 tlv_length);
411         offset += 2;
412
413         return offset;
414 }
415
416 static void
417 dissect_display_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
418 {
419         proto_item      *display_item;
420         proto_tree      *display_tree;
421         guint8          *display_name;
422
423         display_item = proto_tree_add_item(tree, hf_edp_display,
424                 tvb, offset, length, ENC_BIG_ENDIAN);
425
426         display_tree = proto_item_add_subtree(display_item, ett_edp_display);
427
428         dissect_tlv_header(tvb, pinfo, offset, 4, display_tree);
429         offset += 4;
430         length -= 4;
431
432         display_name = tvb_get_ephemeral_string(tvb, offset, length);
433         proto_item_append_text(display_item, ": \"%s\"",
434                 format_text(display_name, strlen(display_name)));
435         proto_tree_add_string(display_tree, hf_edp_display_string, tvb, offset, length,
436                 display_name);
437 }
438
439 static int
440 dissect_null_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length _U_, proto_tree *tree)
441 {
442         proto_item      *null_item;
443         proto_tree      *null_tree;
444
445         null_item = proto_tree_add_protocol_format(tree, hf_edp_null,
446                 tvb, offset, length, "Null");
447
448         null_tree = proto_item_add_subtree(null_item, ett_edp_null);
449
450         dissect_tlv_header(tvb, pinfo, offset, 4, null_tree);
451         offset += 4;
452
453         return offset;
454 }
455
456 static int
457 dissect_info_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
458 {
459         proto_item *ver_item;
460         proto_tree *ver_tree;
461         guint8 major1, major2, sustaining, internal;
462         guint16 port, slot;
463         proto_item      *info_item;
464         proto_tree      *info_tree;
465
466         /* The slot and port numbers printed on the chassis are 1
467            bigger than the transmitted values indicate */
468         slot = tvb_get_ntohs(tvb, offset + 0 + 4) + 1;
469         port = tvb_get_ntohs(tvb, offset + 2 + 4) + 1;
470
471         /* version */
472         major1 = tvb_get_guint8(tvb, offset + 12 + 4);
473         major2 = tvb_get_guint8(tvb, offset + 13 + 4);
474         sustaining = tvb_get_guint8(tvb, offset + 14 + 4);
475         internal = tvb_get_guint8(tvb, offset + 15 + 4);
476
477         info_item = proto_tree_add_protocol_format(tree, hf_edp_info,
478                 tvb, offset, length,
479                 "Info: Slot/Port: %d/%d, Version: %d.%d.%d.%d",
480                 slot, port, major1, major2, sustaining, internal);
481
482         info_tree = proto_item_add_subtree(info_item, ett_edp_info);
483
484         dissect_tlv_header(tvb, pinfo, offset, 4, info_tree);
485         offset += 4;
486
487         proto_tree_add_uint(info_tree, hf_edp_info_slot, tvb, offset, 2,
488                 slot);
489         offset += 2;
490
491         proto_tree_add_uint(info_tree, hf_edp_info_port, tvb, offset, 2,
492                 port);
493         offset += 2;
494
495         proto_tree_add_item(info_tree, hf_edp_info_vchassid, tvb, offset, 2,
496                 ENC_BIG_ENDIAN);
497         offset += 2;
498
499         proto_tree_add_item(info_tree, hf_edp_info_reserved, tvb, offset, 6,
500                 ENC_NA);
501         offset += 6;
502
503         /* Begin version subtree */
504         ver_item = proto_tree_add_text(info_tree, tvb, offset, 4,
505                 "Version: %u.%u.%u Internal: %u", major1, major2,
506                 sustaining, internal);
507
508         ver_tree = proto_item_add_subtree(ver_item, ett_edp_info_version);
509
510         proto_tree_add_item(ver_tree, hf_edp_info_version, tvb, offset, 4,
511                 ENC_BIG_ENDIAN);
512
513         proto_tree_add_uint(ver_tree, hf_edp_info_version_major1, tvb, offset, 1,
514                 major1);
515         offset += 1;
516
517         proto_tree_add_uint(ver_tree, hf_edp_info_version_major2, tvb, offset, 1,
518                 major2);
519         offset += 1;
520
521         proto_tree_add_uint(ver_tree, hf_edp_info_version_sustaining, tvb, offset, 1,
522                 sustaining);
523         offset += 1;
524
525         proto_tree_add_uint(ver_tree, hf_edp_info_version_internal, tvb, offset, 1,
526                 internal);
527         offset += 1;
528         /* End of version subtree */
529
530         proto_tree_add_item(info_tree, hf_edp_info_vchassconn, tvb, offset, 16,
531                 ENC_NA);
532         offset += 16;
533
534         return offset;
535 }
536
537 static int
538 dissect_vlan_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
539 {
540         proto_item      *flags_item;
541         proto_tree      *flags_tree;
542         proto_item      *vlan_item;
543         proto_tree      *vlan_tree;
544         proto_item      *too_short_item;
545         guint16         vlan_id;
546         guint8          *vlan_name;
547
548         vlan_item = proto_tree_add_item(tree, hf_edp_vlan, tvb,
549                 offset, length, ENC_BIG_ENDIAN);
550
551         vlan_tree = proto_item_add_subtree(vlan_item, ett_edp_vlan);
552
553         dissect_tlv_header(tvb, pinfo, offset, 4, vlan_tree);
554         offset += 4;
555         length -= 4;
556
557         /* Begin flags subtree */
558         if (length < 1) {
559                 too_short_item = proto_tree_add_text(vlan_tree, tvb, 0, 0,
560                     "TLV is too short");
561                 PROTO_ITEM_SET_GENERATED(too_short_item);
562                 return offset;
563         }
564         flags_item = proto_tree_add_item(vlan_tree, hf_edp_vlan_flags, tvb, offset, 1,
565                 ENC_BIG_ENDIAN);
566
567         flags_tree = proto_item_add_subtree(flags_item, ett_edp_vlan_flags);
568
569         proto_tree_add_item(flags_tree, hf_edp_vlan_flags_ip, tvb, offset, 1,
570                 ENC_BIG_ENDIAN);
571         proto_tree_add_item(flags_tree, hf_edp_vlan_flags_reserved, tvb, offset, 1,
572                 ENC_BIG_ENDIAN);
573         proto_tree_add_item(flags_tree, hf_edp_vlan_flags_unknown, tvb, offset, 1,
574                 ENC_BIG_ENDIAN);
575         offset += 1;
576         length -= 1;
577         /* End of flags subtree */
578
579         if (length < 1) {
580                 too_short_item = proto_tree_add_text(vlan_tree, tvb, 0, 0,
581                     "TLV is too short");
582                 PROTO_ITEM_SET_GENERATED(too_short_item);
583                 return offset;
584         }
585         proto_tree_add_item(vlan_tree, hf_edp_vlan_reserved1, tvb, offset, 1,
586                 ENC_NA);
587         offset += 1;
588         length -= 1;
589
590         if (length < 2) {
591                 too_short_item = proto_tree_add_text(vlan_tree, tvb, 0, 0,
592                     "TLV is too short");
593                 PROTO_ITEM_SET_GENERATED(too_short_item);
594                 return offset;
595         }
596         vlan_id = tvb_get_ntohs(tvb, offset);
597         if (check_col(pinfo->cinfo, COL_INFO))
598                 col_append_fstr(pinfo->cinfo, COL_INFO, "%d", vlan_id);
599         proto_item_append_text(vlan_item, ": ID %d", vlan_id);
600         proto_tree_add_uint(vlan_tree, hf_edp_vlan_id, tvb, offset, 2,
601                 vlan_id);
602         offset += 2;
603         length -= 2;
604
605         if (length < 4) {
606                 too_short_item = proto_tree_add_text(vlan_tree, tvb, 0, 0,
607                     "TLV is too short");
608                 PROTO_ITEM_SET_GENERATED(too_short_item);
609                 return offset;
610         }
611         proto_tree_add_item(vlan_tree, hf_edp_vlan_reserved2, tvb, offset, 4,
612                 ENC_NA);
613         offset += 4;
614         length -= 4;
615
616         if (length < 4) {
617                 too_short_item = proto_tree_add_text(vlan_tree, tvb, 0, 0,
618                     "TLV is too short");
619                 PROTO_ITEM_SET_GENERATED(too_short_item);
620                 return offset;
621         }
622         proto_tree_add_item(vlan_tree, hf_edp_vlan_ip, tvb, offset, 4,
623                 ENC_BIG_ENDIAN);
624         offset += 4;
625         length -= 4;
626
627         vlan_name = tvb_get_ephemeral_string(tvb, offset, length);
628         proto_item_append_text(vlan_item, ", Name \"%s\"",
629                 format_text(vlan_name, strlen(vlan_name)));
630         proto_tree_add_string(vlan_tree, hf_edp_vlan_name, tvb, offset, length,
631                 vlan_name);
632         offset += length;
633
634
635         return offset;
636 }
637
638 static int
639 dissect_esrp_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
640 {
641         proto_item      *esrp_item;
642         proto_tree      *esrp_tree;
643         guint16         group;
644
645         group = tvb_get_guint8(tvb, offset + 1 + 4);
646         esrp_item = proto_tree_add_protocol_format(tree, hf_edp_esrp,
647                 tvb, offset, length, "ESRP: Group %d", group);
648
649         esrp_tree = proto_item_add_subtree(esrp_item, ett_edp_esrp);
650
651         dissect_tlv_header(tvb, pinfo, offset, 4, esrp_tree);
652         offset += 4;
653
654         proto_tree_add_item(esrp_tree, hf_edp_esrp_proto, tvb, offset, 1,
655                 ENC_BIG_ENDIAN);
656         offset += 1;
657
658         proto_tree_add_item(esrp_tree, hf_edp_esrp_group, tvb, offset, 1,
659                 ENC_BIG_ENDIAN);
660         offset += 1;
661
662         proto_tree_add_item(esrp_tree, hf_edp_esrp_prio, tvb, offset, 2,
663                 ENC_BIG_ENDIAN);
664         offset += 2;
665
666         proto_tree_add_item(esrp_tree, hf_edp_esrp_state, tvb, offset, 2,
667                 ENC_BIG_ENDIAN);
668         offset += 2;
669
670         proto_tree_add_item(esrp_tree, hf_edp_esrp_ports, tvb, offset, 2,
671                 ENC_BIG_ENDIAN);
672         offset += 2;
673
674         proto_tree_add_item(esrp_tree, hf_edp_esrp_virtip, tvb, offset, 4,
675                 ENC_BIG_ENDIAN);
676         offset += 4;
677
678         proto_tree_add_item(esrp_tree, hf_edp_esrp_sysmac, tvb, offset, 6,
679                 ENC_NA);
680         offset += 6;
681
682         proto_tree_add_item(esrp_tree, hf_edp_esrp_hello, tvb, offset, 2,
683                 ENC_BIG_ENDIAN);
684         offset += 2;
685
686         proto_tree_add_item(esrp_tree, hf_edp_esrp_reserved, tvb, offset, 2,
687                 ENC_NA);
688         offset += 2;
689
690         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESRP");
691
692         return offset;
693 }
694
695 static int
696 dissect_eaps_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length _U_, proto_tree *tree)
697 {
698         proto_item      *eaps_item;
699         proto_tree      *eaps_tree;
700         guint16         ctrlvlanid;
701         const gchar     *sysmac_str;
702
703         ctrlvlanid = tvb_get_ntohs(tvb, offset + 1 + 1 + 4);
704         sysmac_str = tvb_ether_to_str(tvb, offset + 12);
705
706         eaps_item = proto_tree_add_protocol_format(tree, hf_edp_eaps,
707                 tvb, offset, length, "EAPS: Ctrlvlan %d, Sysmac %s",
708                         ctrlvlanid, sysmac_str);
709
710         eaps_tree = proto_item_add_subtree(eaps_item, ett_edp_eaps);
711
712         dissect_tlv_header(tvb, pinfo, offset, 4, eaps_tree);
713         offset += 4;
714
715         proto_tree_add_item(eaps_tree, hf_edp_eaps_ver, tvb, offset, 1,
716                 ENC_BIG_ENDIAN);
717         offset += 1;
718
719         proto_tree_add_item(eaps_tree, hf_edp_eaps_type, tvb, offset, 1,
720                 ENC_BIG_ENDIAN);
721         offset += 1;
722
723         proto_tree_add_item(eaps_tree, hf_edp_eaps_ctrlvlanid, tvb, offset, 2,
724                 ENC_BIG_ENDIAN);
725         offset += 2;
726
727         proto_tree_add_item(eaps_tree, hf_edp_eaps_reserved0, tvb, offset, 4,
728                 ENC_NA);
729         offset += 4;
730
731         proto_tree_add_item(eaps_tree, hf_edp_eaps_sysmac, tvb, offset, 6,
732                 ENC_NA);
733         offset += 6;
734
735         proto_tree_add_item(eaps_tree, hf_edp_eaps_hello, tvb, offset, 2,
736                 ENC_BIG_ENDIAN);
737         offset += 2;
738
739         proto_tree_add_item(eaps_tree, hf_edp_eaps_fail, tvb, offset, 2,
740                 ENC_BIG_ENDIAN);
741         offset += 2;
742
743         proto_tree_add_item(eaps_tree, hf_edp_eaps_state, tvb, offset, 1,
744                 ENC_BIG_ENDIAN);
745         offset += 1;
746
747         proto_tree_add_item(eaps_tree, hf_edp_eaps_reserved1, tvb, offset, 1,
748                 ENC_NA);
749         offset += 1;
750
751         proto_tree_add_item(eaps_tree, hf_edp_eaps_helloseq, tvb, offset, 2,
752                 ENC_BIG_ENDIAN);
753         offset += 2;
754
755         proto_tree_add_item(eaps_tree, hf_edp_eaps_reserved2, tvb, offset, 38,
756                 ENC_NA);
757         offset += 38;
758
759         col_set_str(pinfo->cinfo, COL_PROTOCOL, "EAPS");
760         if (check_col(pinfo->cinfo, COL_INFO))
761                 col_append_fstr(pinfo->cinfo, COL_INFO, " ID: %d, MAC: %s",
762                         ctrlvlanid, sysmac_str);
763
764         return offset;
765 }
766
767 static int
768 dissect_esl_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
769 {
770         proto_item      *esl_item;
771         proto_tree      *esl_tree;
772         guint16         ctrlvlanid;
773         guint16         numlinks;
774         const gchar     *sysmac_str;
775
776         ctrlvlanid = tvb_get_ntohs(tvb, offset + 2 + 4);
777         sysmac_str = tvb_ether_to_str(tvb, offset + 12);
778
779         esl_item = proto_tree_add_protocol_format(tree, hf_edp_esl,
780                 tvb, offset, length, "ESL: Ctrlvlan %d, Sysmac %s",
781                         ctrlvlanid, sysmac_str);
782
783         esl_tree = proto_item_add_subtree(esl_item, ett_edp_esl);
784
785         dissect_tlv_header(tvb, pinfo, offset, 4, esl_tree);
786         offset += 4;
787         length -= 4;
788
789         proto_tree_add_item(esl_tree, hf_edp_esl_ver, tvb, offset, 1,
790                 ENC_BIG_ENDIAN);
791         offset += 1;
792         length -= 1;
793
794         proto_tree_add_item(esl_tree, hf_edp_esl_type, tvb, offset, 1,
795                 ENC_BIG_ENDIAN);
796         offset += 1;
797         length -= 1;
798
799         proto_tree_add_item(esl_tree, hf_edp_esl_ctrlvlanid, tvb, offset, 2,
800                 ENC_BIG_ENDIAN);
801         offset += 2;
802         length -= 2;
803
804         proto_tree_add_item(esl_tree, hf_edp_esl_reserved0, tvb, offset, 4,
805                 ENC_NA);
806         offset += 4;
807         length -= 4;
808
809         proto_tree_add_item(esl_tree, hf_edp_esl_sysmac, tvb, offset, 6,
810                 ENC_NA);
811         offset += 6;
812         length -= 6;
813
814         proto_tree_add_item(esl_tree, hf_edp_esl_reserved1, tvb, offset, 4,
815                 ENC_NA);
816         offset += 4;
817         length -= 4;
818
819         proto_tree_add_item(esl_tree, hf_edp_esl_state, tvb, offset, 1,
820                 ENC_BIG_ENDIAN);
821         offset += 1;
822         length -= 1;
823
824         proto_tree_add_item(esl_tree, hf_edp_esl_linkrole, tvb, offset, 1,
825                 ENC_BIG_ENDIAN);
826         offset += 1;
827         length -= 1;
828
829         proto_tree_add_item(esl_tree, hf_edp_esl_linkid1, tvb, offset, 2,
830                 ENC_BIG_ENDIAN);
831         offset += 2;
832         length -= 2;
833
834         proto_tree_add_item(esl_tree, hf_edp_esl_failed1, tvb, offset, 2,
835                 ENC_BIG_ENDIAN);
836         offset += 2;
837         length -= 2;
838
839         proto_tree_add_item(esl_tree, hf_edp_esl_failed2, tvb, offset, 2,
840                 ENC_BIG_ENDIAN);
841         offset += 2;
842         length -= 2;
843
844         proto_tree_add_item(esl_tree, hf_edp_esl_reserved4, tvb, offset, 2,
845                 ENC_NA);
846         offset += 2;
847         length -= 2;
848
849         proto_tree_add_item(esl_tree, hf_edp_esl_linkid2, tvb, offset, 2,
850                 ENC_BIG_ENDIAN);
851         offset += 2;
852         length -= 2;
853
854         proto_tree_add_item(esl_tree, hf_edp_esl_reserved5, tvb, offset, 2,
855                 ENC_NA);
856         offset += 2;
857         length -= 2;
858
859         numlinks = tvb_get_ntohs(tvb, offset);
860         proto_tree_add_item(esl_tree, hf_edp_esl_numlinks, tvb, offset, 2,
861                 ENC_BIG_ENDIAN);
862         offset += 2;
863         length -= 2;
864
865         for (; numlinks > 0 && length >= 2; numlinks--) {
866                 proto_tree_add_item(esl_tree, hf_edp_esl_linklist, tvb, offset, 2,
867                         ENC_BIG_ENDIAN);
868                 offset += 2;
869                 length -= 2;
870         }
871
872         proto_tree_add_item(esl_tree, hf_edp_esl_rest, tvb, offset, length,
873                 ENC_NA);
874         offset += length;
875
876         col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESL");
877         if (check_col(pinfo->cinfo, COL_INFO))
878                 col_append_fstr(pinfo->cinfo, COL_INFO, " ID: %d, MAC: %s",
879                         ctrlvlanid, sysmac_str);
880
881         return offset;
882 }
883
884 static int
885 dissect_elsm_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length,
886         proto_tree *tree, guint16 seqno)
887 {
888         proto_item      *elsm_item;
889         proto_tree      *elsm_tree;
890         guint8          type, subtype;
891
892         type = tvb_get_guint8(tvb, offset + 4);
893         subtype = tvb_get_guint8(tvb, offset + 4 + 1);
894
895         if (check_col(pinfo->cinfo, COL_INFO))
896                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s%s (#%d)",
897                         val_to_str(type, elsm_type_vals, "Unknown (0x%02x)"),
898                         val_to_str(subtype, elsm_subtype_vals, " Unknown (0x%02x)"),
899                         seqno);
900
901         elsm_item = proto_tree_add_protocol_format(tree, hf_edp_elsm,
902                 tvb, offset, length, "ELSM %s%s(#%d)",
903                         val_to_str(type, elsm_type_vals, "Unknown (0x%02x)"),
904                         val_to_str(subtype, elsm_subtype_vals, " Unknown (0x%02x)"),
905                         seqno);
906
907         elsm_tree = proto_item_add_subtree(elsm_item, ett_edp_elsm);
908
909         dissect_tlv_header(tvb, pinfo, offset, 4, elsm_tree);
910         offset += 4;
911
912         /* The rest is actually guesswork */
913         proto_tree_add_item(elsm_tree, hf_edp_elsm_type, tvb, offset, 1,
914                 ENC_BIG_ENDIAN);
915         offset += 1;
916
917         proto_tree_add_item(elsm_tree, hf_edp_elsm_subtype, tvb, offset, 1,
918                 ENC_BIG_ENDIAN);
919         offset += 1;
920
921         proto_tree_add_item(elsm_tree, hf_edp_elsm_magic, tvb, offset, 2,
922                 ENC_NA);
923         offset += 2;
924
925         return offset;
926 }
927
928 static void
929 dissect_elrp_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
930 {
931         proto_item      *elrp_item;
932         proto_tree      *elrp_tree;
933
934         elrp_item = proto_tree_add_protocol_format(tree, hf_edp_elrp,
935                 tvb, offset, length, "ELRP");
936
937         elrp_tree = proto_item_add_subtree(elrp_item, ett_edp_elrp);
938
939         dissect_tlv_header(tvb, pinfo, offset, 4, elrp_tree);
940         offset += 4;
941         length -= 4;
942
943         proto_tree_add_item(elrp_tree, hf_edp_elrp_unknown, tvb, offset, length,
944                 ENC_NA);
945 }
946
947 static void
948 dissect_unknown_tlv(tvbuff_t *tvb, packet_info *pinfo, int offset, int length, proto_tree *tree)
949 {
950         proto_item      *unknown_item;
951         proto_tree      *unknown_tree;
952         guint8          tlv_type;
953
954         tlv_type = tvb_get_guint8(tvb, offset + 1);
955
956         unknown_item = proto_tree_add_protocol_format(tree, hf_edp_unknown,
957                 tvb, offset, length, "Unknown element [0x%02x]", tlv_type);
958
959         unknown_tree = proto_item_add_subtree(unknown_item, ett_edp_unknown);
960
961         dissect_tlv_header(tvb, pinfo, offset, 4, unknown_tree);
962         offset += 4;
963         length -= 4;
964
965         proto_tree_add_item(unknown_tree, hf_edp_unknown_data, tvb, offset, length,
966                 ENC_NA);
967 }
968
969 static void
970 dissect_edp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
971 {
972         proto_item *ti;
973         proto_tree *edp_tree = NULL;
974         proto_item *checksum_item;
975         proto_tree *checksum_tree;
976         guint32 offset = 0;
977         guint16 packet_checksum, computed_checksum;
978         gboolean checksum_good, checksum_bad;
979         gboolean last = FALSE;
980         guint8 tlv_type;
981         guint16 tlv_length;
982         guint16 data_length;
983         guint16 seqno;
984         vec_t cksum_vec[1];
985
986         col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
987         col_set_str(pinfo->cinfo, COL_INFO, PROTO_SHORT_NAME ":");
988
989         if (tree) {
990                 ti = proto_tree_add_item(tree, proto_edp, tvb, offset, -1,
991                     ENC_NA);
992                 edp_tree = proto_item_add_subtree(ti, ett_edp);
993
994                 proto_tree_add_item(edp_tree, hf_edp_version, tvb, offset, 1,
995                         ENC_BIG_ENDIAN);
996                 offset += 1;
997
998                 proto_tree_add_item(edp_tree, hf_edp_reserved, tvb, offset, 1,
999                         ENC_BIG_ENDIAN);
1000                 offset += 1;
1001
1002                 data_length = tvb_get_ntohs(tvb, offset);
1003                 proto_tree_add_uint(edp_tree, hf_edp_length, tvb, offset, 2,
1004                         data_length);
1005                 offset += 2;
1006
1007                 packet_checksum = tvb_get_ntohs(tvb, offset);
1008                 /*
1009                  * If we have the entire ESP packet available, check the checksum.
1010                  */
1011                 if (tvb_length(tvb) >= data_length) {
1012                         /* Checksum from version to null tlv */
1013                         cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, data_length);
1014                         cksum_vec[0].len = data_length;
1015                         computed_checksum = in_cksum(&cksum_vec[0], 1);
1016                         checksum_good = (computed_checksum == 0);
1017                         checksum_bad = !checksum_good;
1018                         if (checksum_good) {
1019                                 checksum_item = proto_tree_add_uint_format(edp_tree,
1020                                         hf_edp_checksum, tvb, offset, 2, packet_checksum,
1021                                         "Checksum: 0x%04x [correct]",
1022                                         packet_checksum);
1023                         } else {
1024                                 checksum_item = proto_tree_add_uint_format(edp_tree,
1025                                         hf_edp_checksum, tvb, offset, 2, packet_checksum,
1026                                         "Checksum: 0x%04x [incorrect, should be 0x%04x]",
1027                                         packet_checksum,
1028                                         in_cksum_shouldbe(packet_checksum, computed_checksum));
1029                         }
1030                 } else {
1031                         checksum_good = checksum_bad = FALSE;
1032                         checksum_item = proto_tree_add_uint(edp_tree, hf_edp_checksum,
1033                                 tvb, offset, 2, packet_checksum);
1034                 }
1035                 checksum_tree = proto_item_add_subtree(checksum_item, ett_edp_checksum);
1036                 checksum_item = proto_tree_add_boolean(checksum_tree, hf_edp_checksum_good,
1037                         tvb, offset, 2, checksum_good);
1038                 PROTO_ITEM_SET_GENERATED(checksum_item);
1039                 checksum_item = proto_tree_add_boolean(checksum_tree, hf_edp_checksum_bad,
1040                         tvb, offset, 2, checksum_bad);
1041                 PROTO_ITEM_SET_GENERATED(checksum_item);
1042                 offset += 2;
1043
1044                 seqno = tvb_get_ntohs(tvb, offset);
1045                 proto_tree_add_item(edp_tree, hf_edp_seqno, tvb, offset, 2,
1046                         ENC_BIG_ENDIAN);
1047                 offset += 2;
1048
1049                 /* Machine ID is 8 bytes, if it starts with 0000, the remaining
1050                    6 bytes are a MAC */
1051                 proto_tree_add_item(edp_tree, hf_edp_midtype, tvb, offset, 2,
1052                         ENC_BIG_ENDIAN);
1053                 offset += 2;
1054
1055                 proto_tree_add_item(edp_tree, hf_edp_midmac, tvb, offset, 6,
1056                         ENC_NA);
1057                 offset += 6;
1058
1059                 /* Decode the individual TLVs */
1060                 while (offset < data_length && !last) {
1061                         if (data_length - offset < 4) {
1062                                 proto_tree_add_text(edp_tree, tvb, offset, 4,
1063                                         "Too few bytes left for TLV: %u (< 4)",
1064                                         data_length - offset);
1065                                 break;
1066                         }
1067                         tlv_type = tvb_get_guint8(tvb, offset + 1);
1068                         tlv_length = tvb_get_ntohs(tvb, offset + 2);
1069
1070                         if ((tlv_length < 4) || (tlv_length > (data_length - offset))) {
1071                                 proto_tree_add_text(edp_tree, tvb, offset, 0,
1072                                         "TLV with invalid length: %u", tlv_length);
1073                                 break;
1074                         }
1075                         if (check_col(pinfo->cinfo, COL_INFO) &&
1076                                 tlv_type != EDP_TYPE_NULL)
1077                                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
1078                                         val_to_str(tlv_type, edp_type_vals, "[0x%02x]"));
1079
1080                         switch (tlv_type) {
1081                         case EDP_TYPE_NULL: /* Last TLV */
1082                                 dissect_null_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1083                                 last = 1;
1084                                 break;
1085                         case EDP_TYPE_DISPLAY: /* MIB II display string */
1086                                 dissect_display_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1087                                 break;
1088                         case EDP_TYPE_INFO: /* Basic system information */
1089                                 dissect_info_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1090                                 break;
1091                         case EDP_TYPE_VLAN: /* VLAN info */
1092                                 dissect_vlan_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1093                                 break;
1094                         case EDP_TYPE_ESRP: /* Extreme Standby Router Protocol */
1095                                 dissect_esrp_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1096                                 break;
1097                         case EDP_TYPE_EAPS: /* Ethernet Automatic Protection Swtiching */
1098                                 dissect_eaps_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1099                                 break;
1100                         case EDP_TYPE_ESL: /* EAPS shared link */
1101                                 dissect_esl_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1102                                 break;
1103                         case EDP_TYPE_ELSM: /* Extreme Link Status Monitoring */
1104                                 dissect_elsm_tlv(tvb, pinfo, offset, tlv_length, edp_tree, seqno);
1105                                 break;
1106                         case EDP_TYPE_ELRP: /* Extreme Loop Recognition Protocol */
1107                                 dissect_elrp_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1108                                 break;
1109                         default:
1110                                 dissect_unknown_tlv(tvb, pinfo, offset, tlv_length, edp_tree);
1111                                 break;
1112                         }
1113                         offset += tlv_length;
1114                 }
1115
1116         }
1117 }
1118
1119 void
1120 proto_register_edp(void)
1121 {
1122         static hf_register_info hf[] = {
1123
1124         /* EDP header */
1125                 { &hf_edp_version,
1126                 { "Version",    "edp.version", FT_UINT8, BASE_DEC, NULL,
1127                         0x0, NULL, HFILL }},
1128
1129                 { &hf_edp_reserved,
1130                 { "Reserved",   "edp.reserved", FT_UINT8, BASE_DEC, NULL,
1131                         0x0, NULL, HFILL }},
1132
1133                 { &hf_edp_length,
1134                 { "Data length",        "edp.length", FT_UINT16, BASE_DEC, NULL,
1135                         0x0, NULL, HFILL }},
1136
1137                 { &hf_edp_checksum,
1138                 { "EDP checksum",       "edp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1139                         NULL, HFILL }},
1140
1141                 { &hf_edp_checksum_good,
1142                 { "Good",       "edp.checksum_good", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1143                         "True: checksum matches packet content; False: doesn't match content or not checked", HFILL }},
1144
1145                 { &hf_edp_checksum_bad,
1146                 { "Bad",        "edp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1147                         "True: checksum doesn't match packet content; False: matches content or not checked", HFILL }},
1148
1149                 { &hf_edp_seqno,
1150                 { "Sequence number",    "edp.seqno", FT_UINT16, BASE_DEC, NULL,
1151                         0x0, NULL, HFILL }},
1152
1153                 { &hf_edp_midtype,
1154                 { "Machine ID type",    "edp.midtype", FT_UINT16, BASE_DEC, VALS(edp_midtype_vals),
1155                         0x0, NULL, HFILL }},
1156
1157                 { &hf_edp_midmac,
1158                 { "Machine MAC",        "edp.midmac", FT_ETHER, BASE_NONE, NULL,
1159                         0x0, NULL, HFILL }},
1160
1161         /* TLV header */
1162                 { &hf_edp_tlv_marker,
1163                 { "TLV Marker", "edp.tlv.marker", FT_UINT8, BASE_HEX, NULL,
1164                         0x0, NULL, HFILL }},
1165
1166                 { &hf_edp_tlv_type,
1167                 { "TLV type",   "edp.tlv.type", FT_UINT8, BASE_DEC, VALS(edp_type_vals),
1168                         0x0, NULL, HFILL }},
1169
1170                 { &hf_edp_tlv_length,
1171                 { "TLV length", "edp.tlv.length", FT_UINT16, BASE_DEC, NULL,
1172                         0x0, NULL, HFILL }},
1173
1174         /* Display element */
1175                 { &hf_edp_display,
1176                 { "Display",    "edp.display", FT_PROTOCOL, BASE_NONE, NULL,
1177                         0x0, "Display element", HFILL }},
1178
1179                 { &hf_edp_display_string,
1180                 { "Name",       "edp.display.string", FT_STRING, BASE_NONE, NULL,
1181                         0x0, "MIB II display string", HFILL }},
1182
1183         /* Info element */
1184                 { &hf_edp_info,
1185                 { "Info",       "edp.info", FT_PROTOCOL, BASE_NONE, NULL,
1186                         0x0, "Info element", HFILL }},
1187
1188                 { &hf_edp_info_slot,
1189                 { "Slot",       "edp.info.slot", FT_UINT16, BASE_DEC, NULL,
1190                         0x0, "Originating slot #", HFILL }},
1191
1192                 { &hf_edp_info_port,
1193                 { "Port",       "edp.info.port", FT_UINT16, BASE_DEC, NULL,
1194                         0x0, "Originating port #", HFILL }},
1195
1196                 { &hf_edp_info_vchassid,
1197                 { "Virt chassis",       "edp.info.vchassid", FT_UINT16, BASE_DEC, NULL,
1198                         0x0, "Virtual chassis ID", HFILL }},
1199
1200                 { &hf_edp_info_reserved,
1201                 { "Reserved",   "edp.info.reserved", FT_BYTES, BASE_NONE, NULL,
1202                         0x0, NULL, HFILL }},
1203
1204                 { &hf_edp_info_version,
1205                 { "Version",    "edp.info.version", FT_UINT32, BASE_HEX, NULL,
1206                         0x0, "Software version", HFILL }},
1207
1208                 { &hf_edp_info_version_major1,
1209                 { "Version (major1)",   "edp.info.version.major1", FT_UINT8, BASE_DEC, NULL,
1210                         0x0, "Software version (major1)", HFILL }},
1211
1212                 { &hf_edp_info_version_major2,
1213                 { "Version (major2)",   "edp.info.version.major2", FT_UINT8, BASE_DEC, NULL,
1214                         0x0, "Software version (major2)", HFILL }},
1215
1216                 { &hf_edp_info_version_sustaining,
1217                 { "Version (sustaining)",       "edp.info.version.sustaining", FT_UINT8, BASE_DEC, NULL,
1218                         0x0, "Software version (sustaining)", HFILL }},
1219
1220                 { &hf_edp_info_version_internal,
1221                 { "Version (internal)", "edp.info.version.internal", FT_UINT8, BASE_DEC, NULL,
1222                         0x0, "Software version (internal)", HFILL }},
1223
1224                 { &hf_edp_info_vchassconn,
1225                 { "Connections",        "edp.info.vchassconn", FT_BYTES, BASE_NONE, NULL,
1226                         0x0, "Virtual chassis connections", HFILL }},
1227
1228         /* VLAN element */
1229                 { &hf_edp_vlan,
1230                 { "Vlan",       "edp.vlan", FT_PROTOCOL, BASE_NONE, NULL,
1231                         0x0, "Vlan element", HFILL }},
1232
1233                 { &hf_edp_vlan_flags,
1234                 { "Flags",      "edp.vlan.flags", FT_UINT8, BASE_HEX, NULL,
1235                         0x0, NULL, HFILL }},
1236
1237                 { &hf_edp_vlan_flags_ip,
1238                 { "Flags-IP",   "edp.vlan.flags.ip", FT_BOOLEAN, 8, TFS(&tfs_set_notset),
1239                         0x80, "Vlan has IP address configured", HFILL }},
1240
1241                 { &hf_edp_vlan_flags_reserved,
1242                 { "Flags-reserved",     "edp.vlan.flags.reserved", FT_UINT8, BASE_HEX, NULL,
1243                         0x7e, NULL, HFILL }},
1244
1245                 { &hf_edp_vlan_flags_unknown,
1246                 { "Flags-Unknown",      "edp.vlan.flags.unknown", FT_BOOLEAN, 8, TFS(&tfs_set_notset),
1247                         0x01, NULL, HFILL }},
1248
1249                 { &hf_edp_vlan_reserved1,
1250                 { "Reserved1",  "edp.vlan.reserved1", FT_BYTES, BASE_NONE, NULL,
1251                         0x0, NULL, HFILL }},
1252
1253                 { &hf_edp_vlan_id,
1254                 { "Vlan ID",    "edp.vlan.id", FT_UINT16, BASE_DEC, NULL,
1255                         0x0, NULL, HFILL }},
1256
1257                 { &hf_edp_vlan_reserved2,
1258                 { "Reserved2",  "edp.vlan.reserved2", FT_BYTES, BASE_NONE, NULL,
1259                         0x0, NULL, HFILL }},
1260
1261                 { &hf_edp_vlan_ip,
1262                 { "IP addr",    "edp.vlan.ip", FT_IPv4, BASE_NONE, NULL,
1263                         0x0, "VLAN IP address", HFILL }},
1264
1265                 { &hf_edp_vlan_name,
1266                 { "Name",       "edp.vlan.name", FT_STRING, BASE_NONE, NULL,
1267                         0x0, "VLAN name", HFILL }},
1268
1269         /* ESRP element */
1270                 { &hf_edp_esrp,
1271                 { "ESRP",       "edp.esrp", FT_PROTOCOL, BASE_NONE, NULL,
1272                         0x0, "Extreme Standby Router Protocol element", HFILL }},
1273
1274                 { &hf_edp_esrp_proto,
1275                 { "Protocol",   "edp.esrp.proto", FT_UINT8, BASE_DEC, VALS(esrp_proto_vals),
1276                         0x0, NULL, HFILL }},
1277
1278                 { &hf_edp_esrp_group,
1279                 { "Group",      "edp.esrp.group", FT_UINT8, BASE_DEC, NULL,
1280                         0x0, NULL, HFILL }},
1281
1282                 { &hf_edp_esrp_prio,
1283                 { "Prio",       "edp.esrp.prio", FT_UINT16, BASE_DEC, NULL,
1284                         0x0, NULL, HFILL }},
1285
1286                 { &hf_edp_esrp_state,
1287                 { "State",      "edp.esrp.state", FT_UINT16, BASE_DEC, VALS(esrp_state_vals),
1288                         0x0, NULL, HFILL }},
1289
1290                 { &hf_edp_esrp_ports,
1291                 { "Ports",      "edp.esrp.ports", FT_UINT16, BASE_DEC, NULL,
1292                         0x0, "Number of active ports", HFILL }},
1293
1294                 { &hf_edp_esrp_virtip,
1295                 { "VirtIP",     "edp.esrp.virtip", FT_IPv4, BASE_NONE, NULL,
1296                         0x0, "Virtual IP address", HFILL }},
1297
1298                 { &hf_edp_esrp_sysmac,
1299                 { "Sys MAC",    "edp.esrp.sysmac", FT_ETHER, BASE_NONE, NULL,
1300                         0x0, "System MAC address", HFILL }},
1301
1302                 { &hf_edp_esrp_hello,
1303                 { "Hello",      "edp.esrp.hello", FT_UINT16, BASE_DEC, NULL,
1304                         0x0, "Hello timer", HFILL }},
1305
1306                 { &hf_edp_esrp_reserved,
1307                 { "Reserved",   "edp.esrp.reserved", FT_BYTES, BASE_NONE, NULL,
1308                         0x0, NULL, HFILL }},
1309
1310         /* EAPS element */
1311                 { &hf_edp_eaps,
1312                 { "EAPS",       "edp.eaps", FT_PROTOCOL, BASE_NONE, NULL,
1313                         0x0, "Ethernet Automatic Protection Switching element", HFILL }},
1314
1315                 { &hf_edp_eaps_ver,
1316                 { "Version",    "edp.eaps.ver", FT_UINT8, BASE_DEC, NULL,
1317                         0x0, NULL, HFILL }},
1318
1319                 { &hf_edp_eaps_type,
1320                 { "Type",       "edp.eaps.type", FT_UINT8, BASE_DEC, VALS(eaps_type_vals),
1321                         0x0, NULL, HFILL }},
1322
1323                 { &hf_edp_eaps_ctrlvlanid,
1324                 { "Vlan ID",    "edp.eaps.vlanid", FT_UINT16, BASE_DEC, NULL,
1325                         0x0, "Control Vlan ID", HFILL }},
1326
1327                 { &hf_edp_eaps_reserved0,
1328                 { "Reserved0",  "edp.eaps.reserved0", FT_BYTES, BASE_NONE, NULL,
1329                         0x0, NULL, HFILL }},
1330
1331                 { &hf_edp_eaps_sysmac,
1332                 { "Sys MAC",    "edp.eaps.sysmac", FT_ETHER, BASE_NONE, NULL,
1333                         0x0, "System MAC address", HFILL }},
1334
1335                 { &hf_edp_eaps_hello,
1336                 { "Hello",      "edp.eaps.hello", FT_UINT16, BASE_DEC, NULL,
1337                         0x0, "Hello timer", HFILL }},
1338
1339                 { &hf_edp_eaps_fail,
1340                 { "Fail",       "edp.eaps.fail", FT_UINT16, BASE_DEC, NULL,
1341                         0x0, "Fail timer", HFILL }},
1342
1343                 { &hf_edp_eaps_state,
1344                 { "State",      "edp.eaps.state", FT_UINT8, BASE_DEC, VALS(eaps_state_vals),
1345                         0x0, NULL, HFILL }},
1346
1347                 { &hf_edp_eaps_reserved1,
1348                 { "Reserved1",  "edp.eaps.reserved1", FT_BYTES, BASE_NONE, NULL,
1349                         0x0, NULL, HFILL }},
1350
1351                 { &hf_edp_eaps_helloseq,
1352                 { "Helloseq",   "edp.eaps.helloseq", FT_UINT16, BASE_DEC, NULL,
1353                         0x0, "Hello sequence", HFILL }},
1354
1355                 { &hf_edp_eaps_reserved2,
1356                 { "Reserved2",  "edp.eaps.reserved2", FT_BYTES, BASE_NONE, NULL,
1357                         0x0, NULL, HFILL }},
1358
1359         /* ESL element (EAPS shared link) */
1360                 { &hf_edp_esl,
1361                 { "ESL",        "edp.esl", FT_PROTOCOL, BASE_NONE, NULL,
1362                         0x0, "EAPS shared link", HFILL }},
1363
1364                 { &hf_edp_esl_ver,
1365                 { "Version",    "edp.esl.ver", FT_UINT8, BASE_DEC, NULL,
1366                         0x0, NULL, HFILL }},
1367
1368                 { &hf_edp_esl_type,
1369                 { "Type",       "edp.esl.type", FT_UINT8, BASE_DEC, VALS(esl_type_vals),
1370                         0x0, NULL, HFILL }},
1371
1372                 { &hf_edp_esl_ctrlvlanid,
1373                 { "Vlan ID",    "edp.esl.vlanid", FT_UINT16, BASE_DEC, NULL,
1374                         0x0, "Control Vlan ID", HFILL }},
1375
1376                 { &hf_edp_esl_reserved0,
1377                 { "Reserved0",  "edp.esl.reserved0", FT_BYTES, BASE_NONE, NULL,
1378                         0x0, NULL, HFILL }},
1379
1380                 { &hf_edp_esl_sysmac,
1381                 { "Sys MAC",    "edp.esl.sysmac", FT_ETHER, BASE_NONE, NULL,
1382                         0x0, "System MAC address", HFILL }},
1383
1384                 { &hf_edp_esl_reserved1,
1385                 { "Reserved1",  "edp.esl.reserved1", FT_BYTES, BASE_NONE, NULL,
1386                         0x0, NULL, HFILL }},
1387
1388                 { &hf_edp_esl_state,
1389                 { "State",      "edp.esl.state", FT_UINT8, BASE_DEC, VALS(esl_state_vals),
1390                         0x0, NULL, HFILL }},
1391
1392                 { &hf_edp_esl_linkrole,
1393                 { "Role",       "edp.esl.role", FT_UINT8, BASE_DEC, VALS(esl_role_vals),
1394                         0x0, NULL, HFILL }},
1395
1396                 { &hf_edp_esl_linkid1,
1397                 { "Link ID 1",  "edp.esl.linkid1", FT_UINT16, BASE_DEC, NULL,
1398                         0x0, "Shared link ID 1", HFILL }},
1399
1400                 { &hf_edp_esl_failed1,
1401                 { "Failed ID 1",        "edp.esl.failed1", FT_UINT16, BASE_DEC, NULL,
1402                         0x0, "Failed link ID 1", HFILL }},
1403
1404                 { &hf_edp_esl_failed2,
1405                 { "Failed ID 2",        "edp.esl.failed2", FT_UINT16, BASE_DEC, NULL,
1406                         0x0, "Failed link ID 2", HFILL }},
1407
1408                 { &hf_edp_esl_reserved4,
1409                 { "Reserved4",  "edp.esl.reserved4", FT_BYTES, BASE_NONE, NULL,
1410                         0x0, NULL, HFILL }},
1411
1412                 { &hf_edp_esl_linkid2,
1413                 { "Link ID 2",  "edp.esl.linkid2", FT_UINT16, BASE_DEC, NULL,
1414                         0x0, "Shared link ID 2", HFILL }},
1415
1416                 { &hf_edp_esl_reserved5,
1417                 { "Reserved5",  "edp.esl.reserved5", FT_BYTES, BASE_NONE, NULL,
1418                         0x0, NULL, HFILL }},
1419
1420                 { &hf_edp_esl_numlinks,
1421                 { "Num Shared Links",   "edp.esl.numlinks", FT_UINT16, BASE_DEC, NULL,
1422                         0x0, "Number of shared links in the network", HFILL }},
1423
1424                 { &hf_edp_esl_linklist,
1425                 { "Link List",  "edp.esl.linklist", FT_UINT16, BASE_DEC, NULL,
1426                         0x0, "List of Shared Link IDs", HFILL }},
1427
1428                 { &hf_edp_esl_rest,
1429                 { "Rest",       "edp.esl.rest", FT_BYTES, BASE_NONE, NULL,
1430                         0x0, NULL, HFILL }},
1431
1432         /* ELSM element */
1433                 { &hf_edp_elsm,
1434                 { "ELSM",       "edp.elsm", FT_PROTOCOL, BASE_NONE, NULL,
1435                         0x0, "Extreme Link Status Monitoring element", HFILL }},
1436
1437                 { &hf_edp_elsm_type,
1438                 { "Type",       "edp.elsm.type", FT_UINT8, BASE_DEC, VALS(elsm_type_vals),
1439                         0x0, NULL, HFILL }},
1440
1441                 { &hf_edp_elsm_subtype,
1442                 { "Subtype",    "edp.elsm.unknown", FT_UINT8, BASE_DEC, VALS(elsm_subtype_vals),
1443                         0x0, NULL, HFILL }},
1444
1445                 { &hf_edp_elsm_magic,
1446                 { "Magic",      "edp.elsm.unknown", FT_BYTES, BASE_NONE, NULL,
1447                         0x0, NULL, HFILL }},
1448
1449         /* ELRP element */
1450                 { &hf_edp_elrp,
1451                 { "ELRP",       "edp.elrp", FT_PROTOCOL, BASE_NONE, NULL,
1452                         0x0, "Extreme Loop Recognition Protocol element", HFILL }},
1453
1454                 { &hf_edp_elrp_unknown,
1455                 { "Unknown",    "edp.elrp.unknown", FT_BYTES, BASE_NONE, NULL,
1456                         0x0, NULL, HFILL }},
1457
1458         /* Unknown element */
1459                 { &hf_edp_unknown,
1460                 { "Unknown",    "edp.unknown", FT_PROTOCOL, BASE_NONE, NULL,
1461                         0x0, "Element unknown to Wireshark", HFILL }},
1462
1463                 { &hf_edp_unknown_data,
1464                 { "Unknown",    "edp.unknown.data", FT_BYTES, BASE_NONE, NULL,
1465                         0x0, NULL, HFILL }},
1466
1467         /* Null element */
1468                 { &hf_edp_null,
1469                 { "End",        "edp.null", FT_PROTOCOL, BASE_NONE, NULL,
1470                         0x0, "Last element", HFILL }},
1471         };
1472         static gint *ett[] = {
1473                 &ett_edp,
1474                 &ett_edp_checksum,
1475                 &ett_edp_tlv_header,
1476                 &ett_edp_vlan_flags,
1477                 &ett_edp_display,
1478                 &ett_edp_info,
1479                 &ett_edp_info_version,
1480                 &ett_edp_vlan,
1481                 &ett_edp_esrp,
1482                 &ett_edp_eaps,
1483                 &ett_edp_esl,
1484                 &ett_edp_elrp,
1485                 &ett_edp_elsm,
1486                 &ett_edp_unknown,
1487                 &ett_edp_null,
1488         };
1489
1490         proto_edp = proto_register_protocol(PROTO_LONG_NAME,
1491             PROTO_SHORT_NAME, "edp");
1492         proto_register_field_array(proto_edp, hf, array_length(hf));
1493         proto_register_subtree_array(ett, array_length(ett));
1494 }
1495
1496 void
1497 proto_reg_handoff_edp(void)
1498 {
1499         dissector_handle_t edp_handle;
1500
1501         edp_handle = create_dissector_handle(dissect_edp, proto_edp);
1502         dissector_add_uint("llc.extreme_pid", 0x00bb, edp_handle);
1503 }
1504
1505 void
1506 proto_register_extreme_oui(void)
1507 {
1508         static hf_register_info hf[] = {
1509           { &hf_llc_extreme_pid,
1510                 { "PID",        "llc.extreme_pid",  FT_UINT16, BASE_HEX,
1511                   VALS(extreme_pid_vals), 0x0, NULL, HFILL }
1512           }
1513         };
1514
1515         llc_add_oui(OUI_EXTREME, "llc.extreme_pid", "Extreme OUI PID", hf);
1516 }