From Peter Paluch via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9160
Extend the BPDU dissector in packet-bpdu.c so that it recognizes and displays the PVID TLV in Cisco's PVST+/RPVST+ BPDUs. svn path=/trunk/; revision=52294
This commit is contained in:
parent
2468b33cce
commit
67da8b61fd
|
@ -34,6 +34,7 @@
|
|||
#include <epan/etypes.h>
|
||||
#include <epan/addr_resolv.h>
|
||||
#include <epan/prefs.h>
|
||||
#include <epan/expert.h>
|
||||
|
||||
/* Offsets of fields within a BPDU */
|
||||
|
||||
|
@ -60,6 +61,8 @@
|
|||
#define BPDU_CIST_REMAINING_HOPS 101
|
||||
#define BPDU_MSTI 102
|
||||
|
||||
#define BPDU_PVST_TLV 36
|
||||
|
||||
#define MSTI_FLAGS 0
|
||||
#define MSTI_REGIONAL_ROOT 1
|
||||
#define MSTI_INTERNAL_ROOT_PATH_COST 9
|
||||
|
@ -156,6 +159,11 @@ static int hf_bpdu_flags_agree_valid = -1;
|
|||
static int hf_bpdu_flags_restricted_role = -1;
|
||||
static int hf_bpdu_spt_agreement_digest = -1;
|
||||
|
||||
static int hf_bpdu_pvst_tlvtype = -1;
|
||||
static int hf_bpdu_pvst_tlvlength = -1;
|
||||
static int hf_bpdu_pvst_tlvvalue = -1;
|
||||
static int hf_bpdu_pvst_tlv_origvlan = -1;
|
||||
|
||||
static gint ett_bpdu = -1;
|
||||
static gint ett_bpdu_flags = -1;
|
||||
static gint ett_root_id = -1;
|
||||
|
@ -166,6 +174,12 @@ static gint ett_cist_bridge_id = -1;
|
|||
static gint ett_spt = -1;
|
||||
static gint ett_aux_mcid = -1;
|
||||
static gint ett_agreement = -1;
|
||||
static gint ett_bpdu_pvst_tlv = -1;
|
||||
|
||||
static expert_field ei_pvst_tlv_length_invalid = EI_INIT;
|
||||
static expert_field ei_pvst_tlv_origvlan_missing = EI_INIT;
|
||||
static expert_field ei_pvst_tlv_truncated = EI_INIT;
|
||||
static expert_field ei_pvst_tlv_unknown = EI_INIT;
|
||||
|
||||
static gboolean bpdu_use_system_id_extensions = TRUE;
|
||||
|
||||
|
@ -178,6 +192,14 @@ static const value_string protocol_id_vals[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
#define BPDU_PVST_TLV_ORIGVLAN 0 /* Originating VLAN TLV in Cisco (R)PVST+ BPDUs */
|
||||
|
||||
static const value_string bpdu_pvst_tlv_vals[] = {
|
||||
{ BPDU_PVST_TLV_ORIGVLAN, "Originating VLAN" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
#define BPDU_TYPE_CONF 0x00 /* STP Configuration BPDU */
|
||||
#define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */
|
||||
#define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */
|
||||
|
@ -223,7 +245,77 @@ static const char cont_sep[] = ", ";
|
|||
}
|
||||
|
||||
static void
|
||||
dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_bpdu_pvst);
|
||||
|
||||
static void
|
||||
dissect_bpdu_cisco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
dissect_bpdu(tvb, pinfo, tree, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_bpdu_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
dissect_bpdu(tvb, pinfo, tree, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_bpdu_pvst_tlv(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb) {
|
||||
gboolean pvst_tlv_origvlan_present = FALSE;
|
||||
guint16 tlv_type, tlv_length;
|
||||
int offset = BPDU_PVST_TLV;
|
||||
proto_item * ti = NULL;
|
||||
proto_item * tlv_length_item = NULL;
|
||||
proto_tree * tlv_tree = NULL;
|
||||
|
||||
if (tvb_reported_length_remaining(tvb, offset) < 4) /* TLV Type and Length fields occupy 4 bytes in total */
|
||||
expert_add_info(pinfo, tree, &ei_pvst_tlv_truncated);
|
||||
|
||||
while (tvb_reported_length_remaining(tvb, offset) >= 4) { /* TLV Type and Length fields occupy 4 bytes in total */
|
||||
tlv_type = tvb_get_ntohs(tvb, offset);
|
||||
tlv_length = tvb_get_ntohs(tvb, offset + 2);
|
||||
|
||||
ti = proto_tree_add_text(tree, tvb, offset, 4 + tlv_length, "%s",
|
||||
val_to_str(tlv_type, bpdu_pvst_tlv_vals, "Unknown TLV type: 0x%04x"));
|
||||
|
||||
tlv_tree = proto_item_add_subtree(ti, ett_bpdu_pvst_tlv);
|
||||
proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvtype, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
tlv_length_item = proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvlength,
|
||||
tvb, offset + 2, 2, ENC_BIG_ENDIAN);
|
||||
|
||||
if (tvb_reported_length_remaining(tvb, offset + 4) < tlv_length) {
|
||||
expert_add_info(pinfo, tlv_length_item, &ei_pvst_tlv_truncated);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += 4;
|
||||
|
||||
switch (tlv_type) {
|
||||
case BPDU_PVST_TLV_ORIGVLAN:
|
||||
if (tlv_length == 2) { /* Originating VLAN ID must be 2 bytes long */
|
||||
proto_item_append_text(ti, " (PVID): %u", tvb_get_ntohs(tvb, offset));
|
||||
proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlv_origvlan, tvb, offset, tlv_length, ENC_BIG_ENDIAN);
|
||||
pvst_tlv_origvlan_present = TRUE;
|
||||
}
|
||||
else
|
||||
expert_add_info(pinfo, tlv_length_item, &ei_pvst_tlv_length_invalid);
|
||||
break;
|
||||
|
||||
default:
|
||||
proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvvalue, tvb, offset, tlv_length, ENC_NA);
|
||||
expert_add_info(pinfo, tlv_tree, &ei_pvst_tlv_unknown);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += tlv_length;
|
||||
}
|
||||
|
||||
if (pvst_tlv_origvlan_present == FALSE) /* If a (R)PVST+ BPDU lacks the Originating VLAN TLV, it is malformed */
|
||||
expert_add_info(pinfo, tree, &ei_pvst_tlv_origvlan_missing);
|
||||
}
|
||||
|
||||
static void
|
||||
dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_bpdu_pvst)
|
||||
{
|
||||
guint16 protocol_identifier;
|
||||
guint8 protocol_version_identifier;
|
||||
|
@ -589,6 +681,9 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
BPDU_FORWARD_DELAY, 2, forward_delay);
|
||||
|
||||
if (bpdu_type == BPDU_TYPE_CONF) {
|
||||
if (is_bpdu_pvst)
|
||||
dissect_bpdu_pvst_tlv(pinfo, bpdu_tree, tvb);
|
||||
|
||||
/* Nothing more in this BPDU */
|
||||
set_actual_length(tvb, CONF_BPDU_SIZE);
|
||||
return;
|
||||
|
@ -1077,6 +1172,9 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
}
|
||||
} else { /* It is RSTP BPDU and may still be Rapid PVST+ */
|
||||
if (is_bpdu_pvst)
|
||||
dissect_bpdu_pvst_tlv(pinfo, bpdu_tree, tvb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1182,6 +1280,22 @@ proto_register_bpdu(void)
|
|||
{ "Version 1 Length", "stp.version_1_length",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_bpdu_pvst_tlvtype,
|
||||
{ "Type", "stp.pvst.tlvtype",
|
||||
FT_UINT16, BASE_HEX, VALS(bpdu_pvst_tlv_vals), 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_bpdu_pvst_tlvlength,
|
||||
{ "Length", "stp.pvst.tlvlen",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_bpdu_pvst_tlv_origvlan,
|
||||
{ "Originating VLAN", "stp.pvst.origvlan",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_bpdu_pvst_tlvvalue,
|
||||
{ "Value", "stp.pvst.tlvval",
|
||||
FT_BYTES, BASE_NONE, NULL, 0x0,
|
||||
NULL, HFILL }},
|
||||
{ &hf_bpdu_version_3_length,
|
||||
{ "Version 3 Length", "mstp.version_3_length",
|
||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||
|
@ -1301,15 +1415,40 @@ proto_register_bpdu(void)
|
|||
&ett_cist_bridge_id,
|
||||
&ett_spt,
|
||||
&ett_aux_mcid,
|
||||
&ett_agreement
|
||||
&ett_agreement,
|
||||
&ett_bpdu_pvst_tlv
|
||||
};
|
||||
|
||||
static ei_register_info ei[] = {
|
||||
{ &ei_pvst_tlv_length_invalid,
|
||||
{ "stp.pvst.tlvlen.invalid", PI_MALFORMED, PI_ERROR,
|
||||
"Indicated length is not valid for this record type", EXPFILL }},
|
||||
|
||||
{ &ei_pvst_tlv_origvlan_missing,
|
||||
{ "stp.pvst.origvlan.missing", PI_MALFORMED, PI_ERROR,
|
||||
"Originating (PVID) VLAN TLV is missing or corrupt", EXPFILL }},
|
||||
|
||||
{ &ei_pvst_tlv_truncated,
|
||||
{ "stp.pvst.tlv.truncated", PI_MALFORMED, PI_ERROR,
|
||||
"TLV record is truncated prematurely", EXPFILL }},
|
||||
|
||||
{ &ei_pvst_tlv_unknown,
|
||||
{ "stp.pvst.tlv.unknown", PI_UNDECODED, PI_COMMENT,
|
||||
"TLV type is unknown", EXPFILL }}
|
||||
};
|
||||
|
||||
module_t *bpdu_module;
|
||||
expert_module_t *expert_bpdu;
|
||||
|
||||
proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp");
|
||||
proto_register_field_array(proto_bpdu, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
register_dissector("bpdu", dissect_bpdu, proto_bpdu);
|
||||
register_dissector("bpdu", dissect_bpdu_generic, proto_bpdu);
|
||||
register_dissector("bpdu_cisco", dissect_bpdu_cisco, proto_bpdu);
|
||||
|
||||
expert_bpdu = expert_register_protocol(proto_bpdu);
|
||||
expert_register_field_array(expert_bpdu, ei, array_length(ei));
|
||||
|
||||
bpdu_module = prefs_register_protocol(proto_bpdu, NULL);
|
||||
prefs_register_bool_preference(bpdu_module, "use_system_id_extension",
|
||||
|
@ -1337,7 +1476,9 @@ proto_reg_handoff_bpdu(void)
|
|||
bpdu_handle = find_dissector("bpdu");
|
||||
dissector_add_uint("llc.dsap", SAP_BPDU, bpdu_handle);
|
||||
dissector_add_uint("chdlc.protocol", CHDLCTYPE_BPDU, bpdu_handle);
|
||||
dissector_add_uint("llc.cisco_pid", 0x010b, bpdu_handle);
|
||||
dissector_add_uint("llc.cisco_pid", 0x010c, bpdu_handle);
|
||||
dissector_add_uint("ethertype", ETHERTYPE_STP, bpdu_handle);
|
||||
dissector_add_uint("llc.cisco_pid", 0x010c, bpdu_handle); /* Cisco's VLAN-bridge STP is just plain STP */
|
||||
|
||||
bpdu_handle = find_dissector("bpdu_cisco");
|
||||
dissector_add_uint("llc.cisco_pid", 0x010b, bpdu_handle); /* Handle Cisco's (R)PVST+ TLV extensions */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue