2 * Routines for BPDU (Spanning Tree Protocol) disassembly
6 * Copyright 1999 Christophe Tronche <ch.tronche@computer.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <epan/packet.h>
33 #include <epan/llcsaps.h>
34 #include <epan/ppptypes.h>
35 #include <epan/chdlctypes.h>
36 #include <epan/etypes.h>
37 #include <epan/addr_resolv.h>
38 #include <epan/prefs.h>
40 /* Offsets of fields within a BPDU */
42 #define BPDU_IDENTIFIER 0
43 #define BPDU_VERSION_IDENTIFIER 2
46 #define BPDU_ROOT_IDENTIFIER 5
47 #define BPDU_ROOT_PATH_COST 13
48 #define BPDU_BRIDGE_IDENTIFIER 17
49 #define BPDU_PORT_IDENTIFIER 25
50 #define BPDU_MESSAGE_AGE 27
51 #define BPDU_MAX_AGE 29
52 #define BPDU_HELLO_TIME 31
53 #define BPDU_FORWARD_DELAY 33
54 #define BPDU_VERSION_1_LENGTH 35
55 #define BPDU_VERSION_3_LENGTH 36
56 #define BPDU_MST_CONFIG_FORMAT_SELECTOR 38
57 #define BPDU_MST_CONFIG_NAME 39
58 #define BPDU_MST_CONFIG_REVISION_LEVEL 71
59 #define BPDU_MST_CONFIG_DIGEST 73
60 #define BPDU_CIST_INTERNAL_ROOT_PATH_COST 89
61 #define BPDU_CIST_BRIDGE_IDENTIFIER 93
62 #define BPDU_CIST_REMAINING_HOPS 101
66 #define MSTI_REGIONAL_ROOT 1
67 #define MSTI_INTERNAL_ROOT_PATH_COST 9
68 #define MSTI_BRIDGE_IDENTIFIER_PRIORITY 13
69 #define MSTI_PORT_IDENTIFIER_PRIORITY 14
70 #define MSTI_REMAINING_HOPS 15
73 #define CONF_BPDU_SIZE 35
74 #define TC_BPDU_SIZE 4
75 #define MST_BPDU_SIZE 38
76 #define VERSION_3_STATIC_LENGTH 64
77 #define MSTI_MESSAGE_SIZE 16
79 /* Values for the Alternative MSTI format */
81 #define ALT_BPDU_CIST_BRIDGE_IDENTIFIER 89
82 #define ALT_BPDU_CIST_INTERNAL_ROOT_PATH_COST 97
84 #define ALT_MSTI_MSTID 0
85 #define ALT_MSTI_FLAGS 2
86 #define ALT_MSTI_REGIONAL_ROOT 3
87 #define ALT_MSTI_INTERNAL_ROOT_PATH_COST 11
88 #define ALT_MSTI_BRIDGE_IDENTIFIER 15
89 #define ALT_MSTI_PORT_IDENTIFIER 23
90 #define ALT_MSTI_REMAINING_HOPS 25
92 #define ALT_MSTI_MESSAGE_SIZE 26
96 #define BPDU_FLAGS_TCACK 0x80
97 #define BPDU_FLAGS_AGREEMENT 0x40
98 #define BPDU_FLAGS_FORWARDING 0x20
99 #define BPDU_FLAGS_LEARNING 0x10
100 #define BPDU_FLAGS_PORT_ROLE_MASK 0x0C
101 #define BPDU_FLAGS_PORT_ROLE_SHIFT 2
102 #define BPDU_FLAGS_PROPOSAL 0x02
103 #define BPDU_FLAGS_TC 0x01
105 static int proto_bpdu = -1;
106 static int hf_bpdu_proto_id = -1;
107 static int hf_bpdu_version_id = -1;
108 static int hf_bpdu_type = -1;
109 static int hf_bpdu_flags = -1;
110 static int hf_bpdu_flags_tcack = -1;
111 static int hf_bpdu_flags_agreement = -1;
112 static int hf_bpdu_flags_forwarding = -1;
113 static int hf_bpdu_flags_learning = -1;
114 static int hf_bpdu_flags_port_role = -1;
115 static int hf_bpdu_flags_proposal = -1;
116 static int hf_bpdu_flags_tc = -1;
117 static int hf_bpdu_root_prio = -1;
118 static int hf_bpdu_root_sys_id_ext = -1;
119 static int hf_bpdu_root_mac = -1;
120 static int hf_bpdu_root_cost = -1;
121 static int hf_bpdu_bridge_prio = -1;
122 static int hf_bpdu_bridge_sys_id_ext = -1;
123 static int hf_bpdu_bridge_mac = -1;
124 static int hf_bpdu_port_id = -1;
125 static int hf_bpdu_msg_age = -1;
126 static int hf_bpdu_max_age = -1;
127 static int hf_bpdu_hello_time = -1;
128 static int hf_bpdu_forward_delay = -1;
129 static int hf_bpdu_version_1_length = -1;
130 static int hf_bpdu_version_3_length = -1;
131 static int hf_bpdu_mst_config_format_selector = -1;
132 static int hf_bpdu_mst_config_name = -1;
133 static int hf_bpdu_mst_config_revision_level = -1;
134 static int hf_bpdu_mst_config_digest = -1;
135 static int hf_bpdu_cist_internal_root_path_cost = -1;
136 static int hf_bpdu_cist_bridge_prio = -1;
137 static int hf_bpdu_cist_bridge_sys_id_ext = -1;
138 static int hf_bpdu_cist_bridge_mac = -1;
139 static int hf_bpdu_cist_remaining_hops = -1;
140 static int hf_bpdu_msti_flags = -1;
141 static int hf_bpdu_msti_regional_root_mac = -1;
142 static int hf_bpdu_msti_internal_root_path_cost = -1;
143 static int hf_bpdu_msti_bridge_identifier_priority = -1;
144 static int hf_bpdu_msti_port_identifier_priority = -1;
145 static int hf_bpdu_msti_port_id = -1;
146 static int hf_bpdu_msti_remaining_hops = -1;
148 static gint ett_bpdu = -1;
149 static gint ett_bpdu_flags = -1;
150 static gint ett_root_id = -1;
151 static gint ett_bridge_id = -1;
152 static gint ett_mstp = -1;
153 static gint ett_msti = -1;
154 static gint ett_cist_bridge_id = -1;
156 static gboolean bpdu_use_system_id_extensions = TRUE;
158 static dissector_handle_t gvrp_handle;
159 static dissector_handle_t gmrp_handle;
160 static dissector_handle_t data_handle;
162 static const value_string protocol_id_vals[] = {
163 { 0, "Spanning Tree Protocol" },
167 #define BPDU_TYPE_CONF 0x00 /* STP Configuration BPDU */
168 #define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */
169 #define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */
171 static const value_string bpdu_type_vals[] = {
172 { BPDU_TYPE_CONF, "Configuration" },
173 { BPDU_TYPE_RST, "Rapid/Multiple Spanning Tree" },
174 { BPDU_TYPE_TOPOLOGY_CHANGE, "Topology Change Notification" },
178 #define PROTO_VERSION_STP 0
179 #define PROTO_VERSION_RSTP 2
180 #define PROTO_VERSION_MSTP 3
182 #define MSTI_FORMAT_UNKNOWN 0
183 #define MSTI_FORMAT_IEEE_8021S 1
184 #define MSTI_FORMAT_ALTERNATIVE 2
186 static const value_string version_id_vals[] = {
187 { PROTO_VERSION_STP, "Spanning Tree" },
188 { PROTO_VERSION_RSTP, "Rapid Spanning Tree" },
189 { PROTO_VERSION_MSTP, "Multiple Spanning Tree" },
192 static const value_string role_vals[] = {
193 { 1, "Alternate or Backup" },
199 static const char initial_sep[] = " (";
200 static const char cont_sep[] = ", ";
202 #define APPEND_BOOLEAN_FLAG(flag, item, string) \
205 proto_item_append_text(item, string, sep); \
210 dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
212 guint16 protocol_identifier;
213 guint8 protocol_version_identifier;
216 guint16 root_identifier_bridge_priority;
217 guint16 root_identifier_system_id_extension = 0;
218 const guint8 *root_identifier_mac;
219 gchar *root_identifier_mac_str;
220 guint32 root_path_cost;
221 guint16 bridge_identifier_bridge_priority;
222 guint16 bridge_identifier_system_id_extension = 0;
223 const guint8 *bridge_identifier_mac;
224 gchar *bridge_identifier_mac_str;
225 guint16 port_identifier;
229 double forward_delay;
230 guint8 version_1_length;
231 guint16 version_3_length;
232 guint8 config_format_selector;
233 guint16 cist_bridge_identifier_bridge_priority;
234 guint16 cist_bridge_identifier_system_id_extension = 0;
235 const guint8 *cist_bridge_identifier_mac;
236 gchar *cist_bridge_identifier_mac_str;
238 guint32 msti_regional_root_mstid, msti_regional_root_priority;
239 const guint8 *msti_regional_root_mac;
240 gchar *msti_regional_root_mac_str;
241 guint16 msti_bridge_identifier_priority, msti_port_identifier_priority;
242 const guint8 *msti_bridge_identifier_mac;
243 gchar *msti_bridge_identifier_mac_str;
244 int total_msti_length, offset, msti, msti_format;
246 proto_tree *bpdu_tree;
247 proto_tree *mstp_tree, *msti_tree;
248 proto_item *bpdu_item;
249 proto_item *mstp_item, *msti_item;
250 proto_tree *flags_tree;
251 proto_item *flags_item;
252 proto_tree *root_id_tree;
253 proto_item *root_id_item;
254 proto_tree *bridge_id_tree;
255 proto_item *bridge_id_item;
256 proto_tree *cist_bridge_id_tree;
257 proto_item *cist_bridge_id_item;
258 proto_item *hidden_item;
261 /* GARP application frames require special interpretation of the
262 destination address field; otherwise, they will be mistaken as
264 Fortunately, they can be recognized by checking the first 6 octets
265 of the destination address, which are in the range from
266 01-80-C2-00-00-20 to 01-80-C2-00-00-2F.
268 Yes - we *do* need to check the destination address type;
269 on Linux cooked captures, there *is* no destination address,
271 if (pinfo->dl_dst.type == AT_ETHER) {
272 const guint8 *dstaddr;
274 dstaddr = pinfo->dl_dst.data;
275 if(dstaddr[0] == 0x01 && dstaddr[1] == 0x80 &&
276 dstaddr[2] == 0xC2 && dstaddr[3] == 0x00 &&
277 dstaddr[4] == 0x00 && ((dstaddr[5] & 0xF0) == 0x20)) {
279 switch (dstaddr[5]) {
283 call_dissector(gmrp_handle, tvb, pinfo, tree);
288 call_dissector(gvrp_handle, tvb, pinfo, tree);
292 pinfo->current_proto = "GARP";
294 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
295 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GARP");
296 /* Generic Attribute Registration Protocol */
299 if (check_col(pinfo->cinfo, COL_INFO)) {
300 col_add_fstr(pinfo->cinfo, COL_INFO,
301 "Unknown GARP application (0x%02X)",
309 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
310 col_set_str(pinfo->cinfo, COL_PROTOCOL, "STP"); /* Spanning Tree Protocol */
312 col_clear(pinfo->cinfo, COL_INFO);
314 bpdu_type = tvb_get_guint8(tvb, BPDU_TYPE);
316 protocol_version_identifier = tvb_get_guint8(tvb, BPDU_VERSION_IDENTIFIER);
322 flags = tvb_get_guint8(tvb, BPDU_FLAGS);
323 root_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_ROOT_IDENTIFIER);
324 if (bpdu_use_system_id_extensions ) {
325 root_identifier_system_id_extension = root_identifier_bridge_priority & 0x0fff;
326 root_identifier_bridge_priority &= 0xf000;
328 root_identifier_mac = tvb_get_ptr(tvb, BPDU_ROOT_IDENTIFIER + 2, 6);
329 root_identifier_mac_str = ether_to_str(root_identifier_mac);
330 root_path_cost = tvb_get_ntohl(tvb, BPDU_ROOT_PATH_COST);
331 port_identifier = tvb_get_ntohs(tvb, BPDU_PORT_IDENTIFIER);
335 /* Squelch GCC complaints. */
337 root_identifier_bridge_priority = 0;
338 root_identifier_mac = NULL;
339 root_identifier_mac_str = NULL;
345 if (check_col(pinfo->cinfo, COL_INFO)) {
349 if (bpdu_use_system_id_extensions ) {
350 col_add_fstr(pinfo->cinfo, COL_INFO,
351 "Conf. %sRoot = %d/%d/%s Cost = %d Port = 0x%04x",
352 flags & 0x1 ? "TC + " : "",
353 root_identifier_bridge_priority,
354 root_identifier_system_id_extension,
355 root_identifier_mac_str,
356 root_path_cost, port_identifier);
358 col_add_fstr(pinfo->cinfo, COL_INFO,
359 "Conf. %sRoot = %d/%s Cost = %d Port = 0x%04x",
360 flags & 0x1 ? "TC + " : "",
361 root_identifier_bridge_priority, root_identifier_mac_str,
362 root_path_cost, port_identifier);
366 case BPDU_TYPE_TOPOLOGY_CHANGE:
367 col_set_str(pinfo->cinfo, COL_INFO, "Topology Change Notification");
371 if (bpdu_use_system_id_extensions ) {
372 col_add_fstr(pinfo->cinfo, COL_INFO,
373 "%cST. %sRoot = %d/%d/%s Cost = %d Port = 0x%04x",
374 protocol_version_identifier == 3 ? 'M':'R',
375 flags & 0x1 ? "TC + " : "",
376 root_identifier_bridge_priority,
377 root_identifier_system_id_extension,
378 root_identifier_mac_str,
379 root_path_cost, port_identifier);
381 col_add_fstr(pinfo->cinfo, COL_INFO,
382 "%cST. %sRoot = %d/%s Cost = %d Port = 0x%04x",
383 protocol_version_identifier == 3 ? 'M':'R',
384 flags & 0x1 ? "TC + " : "",
385 root_identifier_bridge_priority, root_identifier_mac_str,
386 root_path_cost, port_identifier);
391 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BPDU type (%u)", bpdu_type);
397 bpdu_item = proto_tree_add_protocol_format(tree, proto_bpdu, tvb, 0, -1,
398 "Spanning Tree Protocol");
399 bpdu_tree = proto_item_add_subtree(bpdu_item, ett_bpdu);
401 protocol_identifier = tvb_get_ntohs(tvb, BPDU_IDENTIFIER);
402 proto_tree_add_uint(bpdu_tree, hf_bpdu_proto_id, tvb, BPDU_IDENTIFIER, 2,
403 protocol_identifier);
405 proto_tree_add_uint(bpdu_tree, hf_bpdu_version_id, tvb,
406 BPDU_VERSION_IDENTIFIER, 1,
407 protocol_version_identifier);
408 switch (protocol_version_identifier) {
418 proto_tree_add_text(bpdu_tree, tvb, BPDU_VERSION_IDENTIFIER, 1,
419 " (Warning: this version of Wireshark only knows about versions 0, 2 & 3)");
422 proto_tree_add_uint(bpdu_tree, hf_bpdu_type, tvb, BPDU_TYPE, 1, bpdu_type);
424 if (bpdu_type == BPDU_TYPE_TOPOLOGY_CHANGE) {
425 set_actual_length(tvb, TC_BPDU_SIZE);
429 if (bpdu_type != BPDU_TYPE_CONF && bpdu_type != BPDU_TYPE_RST) {
430 /* Unknown BPDU type - just display the rest of the PDU as data */
431 proto_tree_add_text(bpdu_tree, tvb, BPDU_TYPE + 1, -1,
432 "Unknown BPDU type data");
436 bridge_identifier_bridge_priority = tvb_get_ntohs(tvb, BPDU_BRIDGE_IDENTIFIER);
437 if (bpdu_use_system_id_extensions ) {
438 bridge_identifier_system_id_extension = bridge_identifier_bridge_priority & 0x0fff;
439 bridge_identifier_bridge_priority &= 0xf000;
441 bridge_identifier_mac = tvb_get_ptr(tvb, BPDU_BRIDGE_IDENTIFIER + 2, 6);
442 bridge_identifier_mac_str = ether_to_str(bridge_identifier_mac);
444 flags_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_flags, tvb,
445 BPDU_FLAGS, 1, flags);
446 flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
448 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item,
449 "%sTopology Change Acknowledgment");
450 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
451 BPDU_FLAGS, 1, flags);
452 if (bpdu_type == BPDU_TYPE_RST) {
453 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item,
455 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
456 BPDU_FLAGS, 1, flags);
457 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item,
459 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
460 BPDU_FLAGS, 1, flags);
461 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item,
463 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
464 BPDU_FLAGS, 1, flags);
468 port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
469 proto_item_append_text(flags_item, "%sPort Role: %s", sep,
470 val_to_str(port_role, role_vals,
474 proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
475 BPDU_FLAGS, 1, flags);
476 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item,
478 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
479 BPDU_FLAGS, 1, flags);
481 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item,
482 "%sTopology Change");
483 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
484 BPDU_FLAGS, 1, flags);
485 if (sep != initial_sep) {
486 /* We put something in; put in the terminating ")" */
487 proto_item_append_text(flags_item, ")");
490 /* add Identifier with format based on preference value
491 * bpdu_use_system_id_extensions
493 if (bpdu_use_system_id_extensions) {
494 root_id_item = proto_tree_add_text(bpdu_tree, tvb,
495 BPDU_ROOT_IDENTIFIER, 8,
496 "Root Identifier: %d / %d / %s",
497 root_identifier_bridge_priority,
498 root_identifier_system_id_extension,
499 root_identifier_mac_str);
500 root_id_tree = proto_item_add_subtree(root_id_item, ett_root_id);
501 proto_tree_add_uint(root_id_tree, hf_bpdu_root_prio, tvb,
502 BPDU_ROOT_IDENTIFIER , 1,
503 root_identifier_bridge_priority);
504 proto_tree_add_uint(root_id_tree, hf_bpdu_root_sys_id_ext, tvb,
505 BPDU_ROOT_IDENTIFIER , 2,
506 root_identifier_system_id_extension);
507 proto_tree_add_ether_format_value(root_id_tree, hf_bpdu_root_mac,
508 tvb, BPDU_ROOT_IDENTIFIER + 2, 6,
510 "%s", root_identifier_mac_str);
512 root_id_item = proto_tree_add_text(bpdu_tree, tvb,
513 BPDU_ROOT_IDENTIFIER, 8,
514 "Root Identifier: %d / %s",
515 root_identifier_bridge_priority,
516 root_identifier_mac_str);
517 root_id_tree = proto_item_add_subtree(root_id_item, ett_root_id);
518 proto_tree_add_uint(root_id_tree, hf_bpdu_root_prio, tvb,
519 BPDU_ROOT_IDENTIFIER , 2,
520 root_identifier_bridge_priority);
521 proto_tree_add_ether_format_value(root_id_tree, hf_bpdu_root_mac,
522 tvb, BPDU_ROOT_IDENTIFIER + 2, 6,
524 "%s", root_identifier_mac_str);
526 /* end of Identifier formatting */
528 proto_tree_add_uint(bpdu_tree, hf_bpdu_root_cost, tvb,
529 BPDU_ROOT_PATH_COST, 4, root_path_cost);
531 /* add Identifier with format based on preference value
532 * bpdu_use_system_id_extensions
534 if (bpdu_use_system_id_extensions) {
535 bridge_id_item = proto_tree_add_text(bpdu_tree, tvb,
536 BPDU_BRIDGE_IDENTIFIER, 8,
537 "Bridge Identifier: %d / %d / %s",
538 bridge_identifier_bridge_priority,
539 bridge_identifier_system_id_extension,
540 bridge_identifier_mac_str);
541 bridge_id_tree = proto_item_add_subtree(bridge_id_item, ett_bridge_id);
542 proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_prio, tvb,
543 BPDU_BRIDGE_IDENTIFIER , 1,
544 bridge_identifier_bridge_priority);
545 proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_sys_id_ext, tvb,
546 BPDU_BRIDGE_IDENTIFIER , 2,
547 bridge_identifier_system_id_extension);
548 proto_tree_add_ether_format_value(bridge_id_tree, hf_bpdu_bridge_mac,
549 tvb, BPDU_BRIDGE_IDENTIFIER + 2, 6,
550 bridge_identifier_mac,
551 "%s", bridge_identifier_mac_str);
553 bridge_id_item = proto_tree_add_text(bpdu_tree, tvb,
554 BPDU_BRIDGE_IDENTIFIER, 8,
555 "Bridge Identifier: %d / %s",
556 bridge_identifier_bridge_priority,
557 bridge_identifier_mac_str);
558 bridge_id_tree = proto_item_add_subtree(bridge_id_item, ett_bridge_id);
559 proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_prio, tvb,
560 BPDU_BRIDGE_IDENTIFIER , 2,
561 bridge_identifier_bridge_priority);
562 proto_tree_add_ether_format_value(bridge_id_tree, hf_bpdu_bridge_mac,
563 tvb, BPDU_BRIDGE_IDENTIFIER + 2, 6,
564 bridge_identifier_mac,
565 "%s", bridge_identifier_mac_str);
567 /* end of Identifier formatting */
569 proto_tree_add_uint(bpdu_tree, hf_bpdu_port_id, tvb,
570 BPDU_PORT_IDENTIFIER, 2, port_identifier);
571 message_age = tvb_get_ntohs(tvb, BPDU_MESSAGE_AGE) / 256.0;
572 proto_tree_add_double(bpdu_tree, hf_bpdu_msg_age, tvb, BPDU_MESSAGE_AGE, 2,
574 max_age = tvb_get_ntohs(tvb, BPDU_MAX_AGE) / 256.0;
575 proto_tree_add_double(bpdu_tree, hf_bpdu_max_age, tvb, BPDU_MAX_AGE, 2,
577 hello_time = tvb_get_ntohs(tvb, BPDU_HELLO_TIME) / 256.0;
578 proto_tree_add_double(bpdu_tree, hf_bpdu_hello_time, tvb,
579 BPDU_HELLO_TIME, 2, hello_time);
580 forward_delay = tvb_get_ntohs(tvb, BPDU_FORWARD_DELAY) / 256.0;
581 proto_tree_add_double(bpdu_tree, hf_bpdu_forward_delay, tvb,
582 BPDU_FORWARD_DELAY, 2, forward_delay);
584 if (bpdu_type == BPDU_TYPE_CONF) {
585 /* Nothing more in this BPDU */
586 set_actual_length(tvb, CONF_BPDU_SIZE);
590 /* RST or MST BPDU */
591 version_1_length = tvb_get_guint8(tvb, BPDU_VERSION_1_LENGTH);
592 proto_tree_add_uint(bpdu_tree, hf_bpdu_version_1_length, tvb,
593 BPDU_VERSION_1_LENGTH, 1, version_1_length);
594 /* Is this an MST BPDU? */
595 if (protocol_version_identifier >= 3 && version_1_length == 0 &&
596 tvb_reported_length(tvb) >= 102) {
598 * OK, it passes the "Protocol Identifier is 0000 0000
599 * 0000 0000", "Protocol Version Identifier is 3 or
600 * greater", "BPDU Type is 0000 0010", "contains 102 or
601 * more octets", and "a Version 1 Length of 0" tests.
603 version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH);
604 proto_tree_add_uint(bpdu_tree, hf_bpdu_version_3_length, tvb,
605 BPDU_VERSION_3_LENGTH, 2, version_3_length);
608 * Check the Version 3 Length, and see whether it's a
609 * multiple of the MSTI Configuration Message length. Also
610 * check the config_format_selector because some MST BPDU's
611 * have BPDU_VERSION_3_LENGTH set to 0 and use the
612 * field BPDU_MST_CONFIG_FORMAT_SELECTOR as a length-field
615 config_format_selector = tvb_get_guint8(tvb, BPDU_MST_CONFIG_FORMAT_SELECTOR);
616 if (version_3_length != 0) {
617 msti_format = MSTI_FORMAT_IEEE_8021S;
618 if (version_3_length >= VERSION_3_STATIC_LENGTH) {
619 total_msti_length = version_3_length - VERSION_3_STATIC_LENGTH;
622 * XXX - there appears to be an ambiguity in the 802.3Q-2003
623 * standard and at least some of the 802.3s drafts.
625 * The "Version 3 Length" field is defined to be "the number of
626 * octets taken by the parameters that follow in the BPDU", but
627 * it's spoken of as "representing an integral number, from 0 to
628 * 64 inclusive, of MSTI Configuration Messages".
630 * According to mail from a member of the stds-802-1@ieee.org list,
631 * the latter of those is just saying that the length must not have
632 * a value that implies that there's a partial MSTI message in the
633 * packet; it's still in units of octets, not messages.
635 * However, it appears that Cisco's C3550 software (C3550-I5Q3L2-M,
636 * Version 12.1(12c)EA1) might be sending out lengths in units of
639 * This length can't be the number of octets taken by the parameters
640 * that follow in the BPDU, because it's less than the fixed-length
641 * portion of those parameters, so we assume the length is a count of
644 total_msti_length = version_3_length * MSTI_MESSAGE_SIZE;
647 if (tvb_reported_length(tvb) == (guint)config_format_selector + MST_BPDU_SIZE + 1 ) {
648 msti_format = MSTI_FORMAT_ALTERNATIVE;
649 total_msti_length = config_format_selector - VERSION_3_STATIC_LENGTH;
652 * XXX - Unknown MSTI format, since version_3_length is 0
653 * lets assume there are no msti instances in the packet.
655 msti_format = MSTI_FORMAT_UNKNOWN;
656 total_msti_length = 0;
660 set_actual_length(tvb, BPDU_MSTI + total_msti_length);
662 mstp_item = proto_tree_add_text(bpdu_tree, tvb, BPDU_VERSION_3_LENGTH,
663 -1, "MST Extension");
664 mstp_tree = proto_item_add_subtree(mstp_item, ett_mstp);
666 proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_format_selector, tvb,
667 BPDU_MST_CONFIG_FORMAT_SELECTOR, 1, FALSE);
668 proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_name, tvb,
669 BPDU_MST_CONFIG_NAME, 32, FALSE);
671 proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_revision_level, tvb,
672 BPDU_MST_CONFIG_REVISION_LEVEL, 2, FALSE);
673 proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_digest, tvb,
674 BPDU_MST_CONFIG_DIGEST, 16, FALSE);
676 switch(msti_format) {
678 case MSTI_FORMAT_IEEE_8021S:
679 proto_tree_add_item(mstp_tree, hf_bpdu_cist_internal_root_path_cost, tvb,
680 BPDU_CIST_INTERNAL_ROOT_PATH_COST, 4, FALSE);
682 cist_bridge_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_CIST_BRIDGE_IDENTIFIER);
683 cist_bridge_identifier_mac = tvb_get_ptr(tvb, BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6);
684 cist_bridge_identifier_mac_str = ether_to_str(cist_bridge_identifier_mac);
686 /* add Identifier with format based on preference value
687 * bpdu_use_system_id_extensions
689 if (bpdu_use_system_id_extensions ) {
690 cist_bridge_identifier_system_id_extension = cist_bridge_identifier_bridge_priority & 0x0fff;
691 cist_bridge_identifier_bridge_priority &= 0xf000;
693 cist_bridge_id_item = proto_tree_add_text(mstp_tree, tvb,
694 BPDU_CIST_BRIDGE_IDENTIFIER, 8,
695 "CIST Bridge Identifier: %d / %d / %s",
696 cist_bridge_identifier_bridge_priority,
697 cist_bridge_identifier_system_id_extension,
698 cist_bridge_identifier_mac_str);
699 cist_bridge_id_tree = proto_item_add_subtree(cist_bridge_id_item, ett_cist_bridge_id);
700 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb,
701 BPDU_CIST_BRIDGE_IDENTIFIER , 1,
702 cist_bridge_identifier_bridge_priority);
703 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_sys_id_ext, tvb,
704 BPDU_CIST_BRIDGE_IDENTIFIER , 2,
705 cist_bridge_identifier_system_id_extension);
706 proto_tree_add_ether_format_value(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac,
707 tvb, BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6,
708 cist_bridge_identifier_mac,
709 "%s", cist_bridge_identifier_mac_str);
711 cist_bridge_id_item = proto_tree_add_text(mstp_tree, tvb,
712 BPDU_CIST_BRIDGE_IDENTIFIER, 8,
713 "CIST Bridge Identifier: %d / %s",
714 cist_bridge_identifier_bridge_priority,
715 cist_bridge_identifier_mac_str);
716 cist_bridge_id_tree = proto_item_add_subtree(cist_bridge_id_item, ett_cist_bridge_id);
717 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb,
718 BPDU_CIST_BRIDGE_IDENTIFIER , 2,
719 cist_bridge_identifier_bridge_priority);
720 proto_tree_add_ether_format_value(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac,
721 tvb, BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6,
722 cist_bridge_identifier_mac,
723 "%s", cist_bridge_identifier_mac_str);
725 /* end of Identifier formatting */
729 case MSTI_FORMAT_ALTERNATIVE:
730 cist_bridge_identifier_bridge_priority = tvb_get_ntohs(tvb,ALT_BPDU_CIST_BRIDGE_IDENTIFIER);
731 cist_bridge_identifier_mac = tvb_get_ptr(tvb, ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6);
732 cist_bridge_identifier_mac_str = ether_to_str(cist_bridge_identifier_mac);
734 /* add Identifier with format based on preference value
735 * bpdu_use_system_id_extensions
737 if (bpdu_use_system_id_extensions ) {
738 cist_bridge_identifier_system_id_extension = cist_bridge_identifier_bridge_priority & 0x0fff;
739 cist_bridge_identifier_bridge_priority &= 0xf000;
741 cist_bridge_id_item = proto_tree_add_text(mstp_tree, tvb,
742 ALT_BPDU_CIST_BRIDGE_IDENTIFIER, 8,
743 "CIST Bridge Identifier: %d / %d / %s",
744 cist_bridge_identifier_bridge_priority,
745 cist_bridge_identifier_system_id_extension,
746 cist_bridge_identifier_mac_str);
747 cist_bridge_id_tree = proto_item_add_subtree(cist_bridge_id_item, ett_cist_bridge_id);
748 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb,
749 ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 1,
750 cist_bridge_identifier_bridge_priority);
751 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_sys_id_ext, tvb,
752 ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 2,
753 cist_bridge_identifier_system_id_extension);
754 proto_tree_add_ether_format_value(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac,
755 tvb, ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6,
756 cist_bridge_identifier_mac,
757 "%s", cist_bridge_identifier_mac_str);
759 cist_bridge_id_item = proto_tree_add_text(mstp_tree, tvb,
760 ALT_BPDU_CIST_BRIDGE_IDENTIFIER, 8,
761 "CIST Bridge Identifier: %d / %s",
762 cist_bridge_identifier_bridge_priority,
763 cist_bridge_identifier_mac_str);
764 cist_bridge_id_tree = proto_item_add_subtree(cist_bridge_id_item, ett_cist_bridge_id);
765 proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb,
766 ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 2,
767 cist_bridge_identifier_bridge_priority);
768 proto_tree_add_ether_format_value(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac,
769 tvb, ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6,
770 cist_bridge_identifier_mac,
771 "%s", cist_bridge_identifier_mac_str);
773 /* end of Identifier formatting */
775 proto_tree_add_item(mstp_tree, hf_bpdu_cist_internal_root_path_cost, tvb,
776 ALT_BPDU_CIST_INTERNAL_ROOT_PATH_COST, 4, FALSE);
781 proto_tree_add_item(mstp_tree, hf_bpdu_cist_remaining_hops, tvb,
782 BPDU_CIST_REMAINING_HOPS, 1, FALSE);
786 while (total_msti_length > 0) {
787 switch(msti_format) {
789 case MSTI_FORMAT_IEEE_8021S:
790 msti_regional_root_mstid = tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT);
791 msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8;
792 msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) +
793 tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT+1);
794 msti_regional_root_mac = tvb_get_ptr(tvb, offset+ MSTI_REGIONAL_ROOT + 2, 6);
795 msti_regional_root_mac_str = ether_to_str(msti_regional_root_mac);
797 msti_item = proto_tree_add_text(mstp_tree, tvb, offset, 16,
798 "MSTID %d, Regional Root Identifier %d / %s",
799 msti_regional_root_mstid,
800 msti_regional_root_priority,
801 msti_regional_root_mac_str);
802 msti_tree = proto_item_add_subtree(msti_item, ett_msti);
805 flags = tvb_get_guint8(tvb, offset+MSTI_FLAGS);
806 flags_item = proto_tree_add_uint(msti_tree, hf_bpdu_msti_flags, tvb,
807 offset+MSTI_FLAGS, 1, flags);
808 flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
811 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item, "%sMaster");
812 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
813 offset+MSTI_FLAGS, 1, flags);
814 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item, "%sAgreement");
815 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
816 offset+MSTI_FLAGS, 1, flags);
817 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item, "%sForwarding");
818 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
819 offset+MSTI_FLAGS, 1, flags);
820 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item, "%sLearning");
821 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
822 offset+MSTI_FLAGS, 1, flags);
825 port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
826 proto_item_append_text(flags_item, "%sPort Role: %s", sep,
827 val_to_str(port_role, role_vals,
830 proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
831 offset+MSTI_FLAGS, 1, flags);
833 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item, "%sProposal");
834 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
835 offset+MSTI_FLAGS, 1, flags);
836 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item, "%sTopology Change");
837 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
838 offset+MSTI_FLAGS, 1, flags);
839 if (sep != initial_sep) { /* We put something in; put in the terminating ")" */
840 proto_item_append_text(flags_item, ")");
843 /* pri, MSTID, Regional root */
844 hidden_item = proto_tree_add_ether(msti_tree, hf_bpdu_msti_regional_root_mac, tvb,
845 offset + MSTI_REGIONAL_ROOT + 2, 6,
846 msti_regional_root_mac);
847 PROTO_ITEM_SET_HIDDEN(hidden_item);
848 proto_tree_add_text(msti_tree, tvb, offset + MSTI_REGIONAL_ROOT, 8,
849 "MSTID %d, priority %d Root Identifier %s",
850 msti_regional_root_mstid,
851 msti_regional_root_priority,
852 msti_regional_root_mac_str);
855 proto_tree_add_item(msti_tree, hf_bpdu_msti_internal_root_path_cost, tvb,
856 offset+MSTI_INTERNAL_ROOT_PATH_COST, 4, FALSE);
858 msti_bridge_identifier_priority = tvb_get_guint8(tvb, offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY) >> 4;
859 msti_port_identifier_priority = tvb_get_guint8(tvb, offset+MSTI_PORT_IDENTIFIER_PRIORITY) >> 4;
861 proto_tree_add_uint(msti_tree, hf_bpdu_msti_bridge_identifier_priority, tvb,
862 offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY, 1,
863 msti_bridge_identifier_priority);
864 proto_tree_add_uint(msti_tree, hf_bpdu_msti_port_identifier_priority, tvb,
865 offset+MSTI_PORT_IDENTIFIER_PRIORITY, 1,
866 msti_port_identifier_priority);
868 proto_tree_add_item(msti_tree, hf_bpdu_msti_remaining_hops, tvb,
869 offset + MSTI_REMAINING_HOPS, 1, FALSE);
871 total_msti_length -= MSTI_MESSAGE_SIZE;
872 offset += MSTI_MESSAGE_SIZE;
875 case MSTI_FORMAT_ALTERNATIVE:
876 msti_regional_root_mstid = tvb_get_guint8(tvb, offset+ ALT_MSTI_REGIONAL_ROOT);
877 msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8;
878 msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) +
879 tvb_get_guint8(tvb, offset+ ALT_MSTI_REGIONAL_ROOT+1);
880 msti_regional_root_mac = tvb_get_ptr(tvb, offset+ ALT_MSTI_REGIONAL_ROOT + 2, 6);
881 msti_regional_root_mac_str = ether_to_str(msti_regional_root_mac);
883 msti_item = proto_tree_add_text(mstp_tree, tvb, offset, 16,
884 "MSTID %d, Regional Root Identifier %d / %s",
885 msti_regional_root_mstid,
886 msti_regional_root_priority,
887 msti_regional_root_mac_str);
888 msti_tree = proto_item_add_subtree(msti_item, ett_msti);
890 msti_mstid = tvb_get_ntohs(tvb, offset+ ALT_MSTI_MSTID);
891 proto_tree_add_text(msti_tree, tvb, offset+ALT_MSTI_MSTID, 2,
892 "MSTID: %d", msti_mstid);
895 flags = tvb_get_guint8(tvb, offset+ALT_MSTI_FLAGS);
896 flags_item = proto_tree_add_uint(msti_tree, hf_bpdu_msti_flags, tvb,
897 offset+ALT_MSTI_FLAGS, 1, flags);
898 flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
901 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item, "%sMaster");
902 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
903 offset+ALT_MSTI_FLAGS, 1, flags);
904 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item, "%sAgreement");
905 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
906 offset+ALT_MSTI_FLAGS, 1, flags);
907 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item, "%sForwarding");
908 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
909 offset+ALT_MSTI_FLAGS, 1, flags);
910 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item, "%sLearning");
911 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
912 offset+ALT_MSTI_FLAGS, 1, flags);
915 port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
916 proto_item_append_text(flags_item, "%sPort Role: %s", sep,
917 val_to_str(port_role, role_vals,
920 proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
921 offset+ALT_MSTI_FLAGS, 1, flags);
923 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item, "%sProposal");
924 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
925 offset+ALT_MSTI_FLAGS, 1, flags);
926 APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item, "%sTopology Change");
927 proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
928 offset+ALT_MSTI_FLAGS, 1, flags);
929 if (sep != initial_sep) { /* We put something in; put in the terminating ")" */
930 proto_item_append_text(flags_item, ")");
933 /* pri, MSTID, Regional root */
934 hidden_item = proto_tree_add_ether(msti_tree, hf_bpdu_msti_regional_root_mac, tvb,
935 offset + ALT_MSTI_REGIONAL_ROOT + 2, 6,
936 msti_regional_root_mac);
937 PROTO_ITEM_SET_HIDDEN(hidden_item);
938 proto_tree_add_text(msti_tree, tvb, offset + ALT_MSTI_REGIONAL_ROOT, 8,
939 "MSTI Regional Root Identifier: %d / %d / %s",
940 msti_regional_root_mstid,
941 msti_regional_root_priority,
942 msti_regional_root_mac_str);
945 proto_tree_add_item(msti_tree, hf_bpdu_msti_internal_root_path_cost, tvb,
946 offset+ALT_MSTI_INTERNAL_ROOT_PATH_COST, 4, FALSE);
948 msti_bridge_identifier_priority = tvb_get_ntohs(tvb, offset+ALT_MSTI_BRIDGE_IDENTIFIER);
949 msti_bridge_identifier_mac = tvb_get_ptr(tvb, offset+ALT_MSTI_BRIDGE_IDENTIFIER + 2, 6);
950 msti_bridge_identifier_mac_str = ether_to_str(msti_bridge_identifier_mac);
951 proto_tree_add_text(msti_tree, tvb, offset+ALT_MSTI_BRIDGE_IDENTIFIER, 8,
952 "MSTI Bridge Identifier: %d / %d / %s",
953 msti_bridge_identifier_priority & 0x0fff,
954 msti_bridge_identifier_priority & 0xf000,
955 msti_bridge_identifier_mac_str);
957 msti_port_identifier_priority = tvb_get_ntohs(tvb, offset+ALT_MSTI_PORT_IDENTIFIER);
958 proto_tree_add_uint(msti_tree, hf_bpdu_msti_port_id, tvb,
959 offset+ALT_MSTI_PORT_IDENTIFIER, 2, msti_port_identifier_priority);
961 proto_tree_add_item(msti_tree, hf_bpdu_msti_remaining_hops, tvb,
962 offset + ALT_MSTI_REMAINING_HOPS, 1, FALSE);
964 total_msti_length -= ALT_MSTI_MESSAGE_SIZE;
965 offset += ALT_MSTI_MESSAGE_SIZE;
976 proto_register_bpdu(void)
979 static hf_register_info hf[] = {
981 { "Protocol Identifier", "stp.protocol",
982 FT_UINT16, BASE_HEX, VALS(protocol_id_vals), 0x0,
984 { &hf_bpdu_version_id,
985 { "Protocol Version Identifier", "stp.version",
986 FT_UINT8, BASE_DEC, VALS(version_id_vals), 0x0,
989 { "BPDU Type", "stp.type",
990 FT_UINT8, BASE_HEX, VALS(bpdu_type_vals), 0x0,
993 { "BPDU flags", "stp.flags",
994 FT_UINT8, BASE_HEX, NULL, 0x0,
996 { &hf_bpdu_flags_tcack,
997 { "Topology Change Acknowledgment", "stp.flags.tcack",
998 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_TCACK,
1000 { &hf_bpdu_flags_agreement,
1001 { "Agreement", "stp.flags.agreement",
1002 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_AGREEMENT,
1004 { &hf_bpdu_flags_forwarding,
1005 { "Forwarding", "stp.flags.forwarding",
1006 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_FORWARDING,
1008 { &hf_bpdu_flags_learning,
1009 { "Learning", "stp.flags.learning",
1010 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_LEARNING,
1012 { &hf_bpdu_flags_port_role,
1013 { "Port Role", "stp.flags.port_role",
1014 FT_UINT8, BASE_DEC, VALS(role_vals), BPDU_FLAGS_PORT_ROLE_MASK,
1016 { &hf_bpdu_flags_proposal,
1017 { "Proposal", "stp.flags.proposal",
1018 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_PROPOSAL,
1020 { &hf_bpdu_flags_tc,
1021 { "Topology Change", "stp.flags.tc",
1022 FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_TC,
1024 { &hf_bpdu_root_prio,
1025 { "Root Bridge Priority", "stp.root.prio",
1026 FT_UINT16, BASE_DEC, NULL, 0x0,
1028 { &hf_bpdu_root_sys_id_ext,
1029 { "Root Bridge System ID Extension", "stp.root.ext",
1030 FT_UINT16, BASE_DEC, NULL, 0x0,
1032 { &hf_bpdu_root_mac,
1033 { "Root Bridge System ID", "stp.root.hw",
1034 FT_ETHER, BASE_NONE, NULL, 0x0,
1036 { &hf_bpdu_root_cost,
1037 { "Root Path Cost", "stp.root.cost",
1038 FT_UINT32, BASE_DEC, NULL, 0x0,
1040 { &hf_bpdu_bridge_prio,
1041 { "Bridge Priority", "stp.bridge.prio",
1042 FT_UINT16, BASE_DEC, NULL, 0x0,
1044 { &hf_bpdu_bridge_sys_id_ext,
1045 { "Bridge System ID Extension", "stp.bridge.ext",
1046 FT_UINT16, BASE_DEC, NULL, 0x0,
1048 { &hf_bpdu_bridge_mac,
1049 { "Bridge System ID", "stp.bridge.hw",
1050 FT_ETHER, BASE_NONE, NULL, 0x0,
1053 { "Port identifier", "stp.port",
1054 FT_UINT16, BASE_HEX, NULL, 0x0,
1057 { "Message Age", "stp.msg_age",
1058 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1061 { "Max Age", "stp.max_age",
1062 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1064 { &hf_bpdu_hello_time,
1065 { "Hello Time", "stp.hello",
1066 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1068 { &hf_bpdu_forward_delay,
1069 { "Forward Delay", "stp.forward",
1070 FT_DOUBLE, BASE_NONE, NULL, 0x0,
1072 { &hf_bpdu_version_1_length,
1073 { "Version 1 Length", "stp.version_1_length",
1074 FT_UINT8, BASE_DEC, NULL, 0x0,
1076 { &hf_bpdu_version_3_length,
1077 { "Version 3 Length", "mstp.version_3_length",
1078 FT_UINT16, BASE_DEC, NULL, 0x0,
1080 { &hf_bpdu_mst_config_format_selector,
1081 { "MST Config ID format selector", "mstp.config_format_selector",
1082 FT_UINT8, BASE_DEC, NULL, 0x0,
1084 { &hf_bpdu_mst_config_name,
1085 { "MST Config name", "mstp.config_name",
1086 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1088 { &hf_bpdu_mst_config_revision_level,
1089 { "MST Config revision", "mstp.config_revision_level",
1090 FT_UINT16, BASE_DEC, NULL, 0x0,
1092 { &hf_bpdu_mst_config_digest,
1093 { "MST Config digest", "mstp.config_digest",
1094 FT_BYTES, BASE_NONE, NULL, 0x0,
1096 { &hf_bpdu_cist_internal_root_path_cost,
1097 { "CIST Internal Root Path Cost", "mstp.cist_internal_root_path_cost",
1098 FT_UINT32, BASE_DEC, NULL, 0x0,
1100 { &hf_bpdu_cist_bridge_prio,
1101 { "CIST Bridge Priority", "mstp.cist_bridge.prio",
1102 FT_UINT16, BASE_DEC, NULL, 0x0,
1104 { &hf_bpdu_cist_bridge_sys_id_ext,
1105 { "CIST Bridge Identifier System ID Extension", "mstp.cist_bridge.ext",
1106 FT_UINT16, BASE_DEC, NULL, 0x0,
1108 { &hf_bpdu_cist_bridge_mac,
1109 { "CIST Bridge Identifier System ID", "mstp.cist_bridge.hw",
1110 FT_ETHER, BASE_NONE, NULL, 0x0,
1112 { &hf_bpdu_cist_remaining_hops,
1113 { "CIST Remaining hops", "mstp.cist_remaining_hops",
1114 FT_UINT8, BASE_DEC, NULL, 0x0,
1116 { &hf_bpdu_msti_flags,
1117 { "MSTI flags", "mstp.msti.flags",
1118 FT_UINT8, BASE_HEX, NULL, 0x0,
1120 { &hf_bpdu_msti_regional_root_mac,
1121 { "Regional Root", "mstp.msti.root.hw",
1122 FT_ETHER, BASE_NONE, NULL, 0x0,
1124 { &hf_bpdu_msti_internal_root_path_cost,
1125 { "Internal root path cost", "mstp.msti.root_cost",
1126 FT_UINT32, BASE_DEC, NULL, 0x0,
1128 { &hf_bpdu_msti_bridge_identifier_priority,
1129 { "Bridge Identifier Priority", "mstp.msti.bridge_priority",
1130 FT_UINT8, BASE_DEC, NULL, 0x0,
1132 { &hf_bpdu_msti_port_identifier_priority,
1133 { "Port identifier priority", "mstp.msti.port_priority",
1134 FT_UINT8, BASE_DEC, NULL, 0x0,
1136 { &hf_bpdu_msti_port_id,
1137 { "Port identifier", "mstp.msti.port",
1138 FT_UINT16, BASE_HEX, NULL, 0x0,
1140 { &hf_bpdu_msti_remaining_hops,
1141 { "Remaining hops", "mstp.msti.remaining_hops",
1142 FT_UINT8, BASE_DEC, NULL, 0x0,
1146 static gint *ett[] = {
1155 module_t *bpdu_module;
1157 proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp");
1158 proto_register_field_array(proto_bpdu, hf, array_length(hf));
1159 proto_register_subtree_array(ett, array_length(ett));
1161 register_dissector("bpdu", dissect_bpdu, proto_bpdu);
1163 bpdu_module = prefs_register_protocol(proto_bpdu, NULL);
1164 prefs_register_bool_preference(bpdu_module, "use_system_id_extension",
1165 "Use 802.1t System ID Extensions",
1166 "Whether the BPDU dissector should use 802.1t System ID Extensions when dissecting the Bridge Identifier",
1167 &bpdu_use_system_id_extensions);
1171 proto_reg_handoff_bpdu(void)
1173 dissector_handle_t bpdu_handle;
1176 * Get handle for the GVRP dissector.
1178 gvrp_handle = find_dissector("gvrp");
1181 * Get handle for the GMRP dissector.
1183 gmrp_handle = find_dissector("gmrp");
1184 data_handle = find_dissector("data");
1186 bpdu_handle = find_dissector("bpdu");
1187 dissector_add("llc.dsap", SAP_BPDU, bpdu_handle);
1188 dissector_add("chdlctype", CHDLCTYPE_BPDU, bpdu_handle);
1189 dissector_add("llc.cisco_pid", 0x010b, bpdu_handle);
1190 dissector_add("ethertype", ETHERTYPE_STP, bpdu_handle);