/* packet-bpdu.c
* Routines for BPDU (Spanning Tree Protocol) disassembly
*
- * $Id: packet-bpdu.c,v 1.44 2003/01/11 10:01:51 guy Exp $
+ * $Id: packet-bpdu.c,v 1.50 2004/01/08 20:05:20 guy Exp $
*
* Copyright 1999 Christophe Tronche <ch.tronche@computer.org>
*
#include <epan/packet.h>
#include "llcsaps.h"
#include "ppptypes.h"
+#include "chdlctypes.h"
#include <epan/resolv.h>
/* Offsets of fields within a BPDU */
#define CONF_BPDU_SIZE 35
#define TC_BPDU_SIZE 4
#define RST_BPDU_SIZE 36
-#define VERSION_3_STATIC_LENGTH 64
+#define VERSION_3_STATIC_LENGTH 66
#define MSTI_MESSAGE_SIZE 16
/* Flag bits */
case BPDU_TYPE_RST:
if (protocol_version_identifier == 3) {
version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH);
- set_actual_length(tvb, RST_BPDU_SIZE + 2 + version_3_length);
+ /*
+ * XXX - there appears to be an ambiguity in the 802.1s spec.
+ * In 14.6.q and Figure 14-1, the "Version 3 Length" field
+ * "is the number of octets taken by the parameters that
+ * follow in the BPDU", but item 14.4.e.3 speaks of "a
+ * Version 3 length representing an integral number, from 0
+ * to 64 inclusive, of MSTI Configuration Messages".
+ *
+ * According to mail from a member of the stds-802-1@ieee.org
+ * list, item 14.4.e.3 is just saying that the length must
+ * not have a value that implies that there's a partial
+ * MSTI message in the packet, and that it's in units of
+ * bytes, not messages.
+ *
+ * However, it appears that Cisco's C3550 software
+ * (C3550-I5Q3L2-M, Version 12.1(12c)EA1) might be sending out
+ * lengths in units of messages.
+ *
+ * So if the length is too short, we assume it's because it's
+ * in units of messages, not bytes.
+ */
+ if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+ set_actual_length(tvb, RST_BPDU_SIZE +
+ VERSION_3_STATIC_LENGTH +
+ version_3_length * MSTI_MESSAGE_SIZE);
+ } else
+ set_actual_length(tvb, RST_BPDU_SIZE + 2 + version_3_length);
} else
set_actual_length(tvb, RST_BPDU_SIZE);
break;
mstp_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_version_3_length, tvb,
BPDU_VERSION_3_LENGTH, 2, version_3_length);
+ /*
+ * XXX - see comment above about the interpretation of the
+ * "Version 3 Length" field not being clear.
+ */
+ if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+ proto_item_append_text(mstp_item,
+ " (Malformed: number of MSTI messages!!! Must be %u)",
+ (VERSION_3_STATIC_LENGTH - 2 + version_3_length * MSTI_MESSAGE_SIZE));
+ } else {
+ proto_item_append_text(mstp_item,
+ " (Number of MSTI messages: %u)",
+ (version_3_length - (VERSION_3_STATIC_LENGTH - 2)) / MSTI_MESSAGE_SIZE);
+ }
mstp_tree = proto_item_add_subtree(mstp_item, ett_mstp);
-
mst_config_format_selector = tvb_get_guint8(tvb, BPDU_MST_CONFIG_FORMAT_SELECTOR);
proto_tree_add_uint(mstp_tree, hf_bpdu_mst_config_format_selector, tvb,
BPDU_MST_CONFIG_FORMAT_SELECTOR, 1, mst_config_format_selector);
BPDU_CIST_REMAINING_HOPS, 1, cist_remaining_hops);
/* MSTI messages */
- length = version_3_length - VERSION_3_STATIC_LENGTH;
offset = BPDU_MSTI;
+ length = tvb_reported_length_remaining(tvb, offset);
msti = 1;
while (length >= MSTI_MESSAGE_SIZE) {
msti_regional_root_mstid = tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT);
msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8;
msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) +
- tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT+1);;
+ tvb_get_guint8(tvb, offset+ MSTI_REGIONAL_ROOT+1);
msti_regional_root_mac = tvb_get_ptr(tvb, offset+ MSTI_REGIONAL_ROOT + 2, 6);
msti_regional_root_mac_str = ether_to_str(msti_regional_root_mac);
msti_tree = proto_item_add_subtree(msti_item, ett_msti);
/* flags */
+ flags = tvb_get_guint8(tvb, offset+MSTI_FLAGS);
flags_item = proto_tree_add_uint(msti_tree, hf_bpdu_msti_flags, tvb,
offset+MSTI_FLAGS, 1, flags);
+ flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
sep = initial_sep;
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item, "%sMaster");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
+ offset+MSTI_FLAGS, 1, flags);
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item, "%sAgreement");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
+ offset+MSTI_FLAGS, 1, flags);
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item, "%sForwarding");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
+ offset+MSTI_FLAGS, 1, flags);
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item, "%sLearning");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
+ offset+MSTI_FLAGS, 1, flags);
if (flags_item) {
guint8 port_role;
port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
proto_item_append_text(flags_item, "%sPort Role: %s", sep,
val_to_str(port_role, role_vals, "Unknown (%u)"));
}
+ proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
+ offset+MSTI_FLAGS, 1, flags);
sep = cont_sep;
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item, "%sProposal");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
+ offset+MSTI_FLAGS, 1, flags);
APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item, "%sTopology Change");
+ proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
+ offset+MSTI_FLAGS, 1, flags);
if (sep != initial_sep) { /* We put something in; put in the terminating ")" */
proto_item_append_text(flags_item, ")");
}
bpdu_handle = find_dissector("bpdu");
dissector_add("llc.dsap", SAP_BPDU, bpdu_handle);
dissector_add("ppp.protocol", PPP_BPDU, bpdu_handle);
- dissector_add("chdlctype", 0x4242, bpdu_handle);
+ dissector_add("chdlctype", CHDLCTYPE_BPDU, bpdu_handle);
}