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/etypes.h>
|
||||||
#include <epan/addr_resolv.h>
|
#include <epan/addr_resolv.h>
|
||||||
#include <epan/prefs.h>
|
#include <epan/prefs.h>
|
||||||
|
#include <epan/expert.h>
|
||||||
|
|
||||||
/* Offsets of fields within a BPDU */
|
/* Offsets of fields within a BPDU */
|
||||||
|
|
||||||
|
@ -60,6 +61,8 @@
|
||||||
#define BPDU_CIST_REMAINING_HOPS 101
|
#define BPDU_CIST_REMAINING_HOPS 101
|
||||||
#define BPDU_MSTI 102
|
#define BPDU_MSTI 102
|
||||||
|
|
||||||
|
#define BPDU_PVST_TLV 36
|
||||||
|
|
||||||
#define MSTI_FLAGS 0
|
#define MSTI_FLAGS 0
|
||||||
#define MSTI_REGIONAL_ROOT 1
|
#define MSTI_REGIONAL_ROOT 1
|
||||||
#define MSTI_INTERNAL_ROOT_PATH_COST 9
|
#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_flags_restricted_role = -1;
|
||||||
static int hf_bpdu_spt_agreement_digest = -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 = -1;
|
||||||
static gint ett_bpdu_flags = -1;
|
static gint ett_bpdu_flags = -1;
|
||||||
static gint ett_root_id = -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_spt = -1;
|
||||||
static gint ett_aux_mcid = -1;
|
static gint ett_aux_mcid = -1;
|
||||||
static gint ett_agreement = -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;
|
static gboolean bpdu_use_system_id_extensions = TRUE;
|
||||||
|
|
||||||
|
@ -178,6 +192,14 @@ static const value_string protocol_id_vals[] = {
|
||||||
{ 0, NULL }
|
{ 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_CONF 0x00 /* STP Configuration BPDU */
|
||||||
#define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */
|
#define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */
|
||||||
#define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */
|
#define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */
|
||||||
|
@ -223,7 +245,77 @@ static const char cont_sep[] = ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
guint16 protocol_identifier;
|
||||||
guint8 protocol_version_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);
|
BPDU_FORWARD_DELAY, 2, forward_delay);
|
||||||
|
|
||||||
if (bpdu_type == BPDU_TYPE_CONF) {
|
if (bpdu_type == BPDU_TYPE_CONF) {
|
||||||
|
if (is_bpdu_pvst)
|
||||||
|
dissect_bpdu_pvst_tlv(pinfo, bpdu_tree, tvb);
|
||||||
|
|
||||||
/* Nothing more in this BPDU */
|
/* Nothing more in this BPDU */
|
||||||
set_actual_length(tvb, CONF_BPDU_SIZE);
|
set_actual_length(tvb, CONF_BPDU_SIZE);
|
||||||
return;
|
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",
|
{ "Version 1 Length", "stp.version_1_length",
|
||||||
FT_UINT8, BASE_DEC, NULL, 0x0,
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
||||||
NULL, HFILL }},
|
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,
|
{ &hf_bpdu_version_3_length,
|
||||||
{ "Version 3 Length", "mstp.version_3_length",
|
{ "Version 3 Length", "mstp.version_3_length",
|
||||||
FT_UINT16, BASE_DEC, NULL, 0x0,
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
||||||
|
@ -1301,15 +1415,40 @@ proto_register_bpdu(void)
|
||||||
&ett_cist_bridge_id,
|
&ett_cist_bridge_id,
|
||||||
&ett_spt,
|
&ett_spt,
|
||||||
&ett_aux_mcid,
|
&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;
|
module_t *bpdu_module;
|
||||||
|
expert_module_t *expert_bpdu;
|
||||||
|
|
||||||
proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp");
|
proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp");
|
||||||
proto_register_field_array(proto_bpdu, hf, array_length(hf));
|
proto_register_field_array(proto_bpdu, hf, array_length(hf));
|
||||||
proto_register_subtree_array(ett, array_length(ett));
|
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);
|
bpdu_module = prefs_register_protocol(proto_bpdu, NULL);
|
||||||
prefs_register_bool_preference(bpdu_module, "use_system_id_extension",
|
prefs_register_bool_preference(bpdu_module, "use_system_id_extension",
|
||||||
|
@ -1337,7 +1476,9 @@ proto_reg_handoff_bpdu(void)
|
||||||
bpdu_handle = find_dissector("bpdu");
|
bpdu_handle = find_dissector("bpdu");
|
||||||
dissector_add_uint("llc.dsap", SAP_BPDU, bpdu_handle);
|
dissector_add_uint("llc.dsap", SAP_BPDU, bpdu_handle);
|
||||||
dissector_add_uint("chdlc.protocol", CHDLCTYPE_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("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