/src/wireshark/epan/dissectors/packet-bpdu.c
Line | Count | Source |
1 | | /* packet-bpdu.c |
2 | | * Routines for BPDU (Spanning Tree Protocol) disassembly |
3 | | * |
4 | | * Copyright 1999 Christophe Tronche <ch.tronche@computer.org> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/etypes.h> |
17 | | #include <epan/addr_resolv.h> |
18 | | #include <epan/prefs.h> |
19 | | #include <epan/expert.h> |
20 | | #include <epan/tfs.h> |
21 | | #include "packet-llc.h" |
22 | | #include "packet-chdlc.h" |
23 | | #include "packet-cisco-pid.h" |
24 | | |
25 | | /* Offsets of fields within a BPDU */ |
26 | | |
27 | 58 | #define BPDU_IDENTIFIER 0 |
28 | 60 | #define BPDU_VERSION_IDENTIFIER 2 |
29 | 60 | #define BPDU_TYPE 3 |
30 | 50 | #define BPDU_FLAGS 4 |
31 | 122 | #define BPDU_ROOT_IDENTIFIER 5 |
32 | 50 | #define BPDU_ROOT_PATH_COST 13 |
33 | 120 | #define BPDU_BRIDGE_IDENTIFIER 17 |
34 | 50 | #define BPDU_PORT_IDENTIFIER 25 |
35 | 48 | #define BPDU_MESSAGE_AGE 27 |
36 | 48 | #define BPDU_MAX_AGE 29 |
37 | 48 | #define BPDU_HELLO_TIME 31 |
38 | 48 | #define BPDU_FORWARD_DELAY 33 |
39 | 36 | #define BPDU_VERSION_1_LENGTH 35 |
40 | 36 | #define BPDU_VERSION_3_LENGTH 36 |
41 | 24 | #define BPDU_MST_CONFIG_FORMAT_SELECTOR 38 |
42 | 12 | #define BPDU_MST_CONFIG_NAME 39 |
43 | 12 | #define BPDU_MST_CONFIG_REVISION_LEVEL 71 |
44 | 12 | #define BPDU_MST_CONFIG_DIGEST 73 |
45 | 9 | #define BPDU_CIST_INTERNAL_ROOT_PATH_COST 89 |
46 | 45 | #define BPDU_CIST_BRIDGE_IDENTIFIER 93 |
47 | 12 | #define BPDU_CIST_REMAINING_HOPS 101 |
48 | 16 | #define BPDU_MSTI 102 |
49 | | |
50 | 0 | #define BPDU_PVST_TLV 36 |
51 | | |
52 | 100 | #define MSTI_FLAGS 0 |
53 | 500 | #define MSTI_REGIONAL_ROOT 1 |
54 | 100 | #define MSTI_INTERNAL_ROOT_PATH_COST 9 |
55 | 200 | #define MSTI_BRIDGE_IDENTIFIER_PRIORITY 13 |
56 | 200 | #define MSTI_PORT_IDENTIFIER_PRIORITY 14 |
57 | 100 | #define MSTI_REMAINING_HOPS 15 |
58 | | |
59 | | |
60 | 6 | #define CONF_BPDU_SIZE 35 |
61 | 0 | #define TC_BPDU_SIZE 4 |
62 | 3 | #define MST_BPDU_SIZE 38 |
63 | 12 | #define VERSION_3_STATIC_LENGTH 64 |
64 | 206 | #define MSTI_MESSAGE_SIZE 16 |
65 | | |
66 | | /* Values for the Alternative MSTI format */ |
67 | | |
68 | 0 | #define ALT_BPDU_CIST_BRIDGE_IDENTIFIER 89 |
69 | 0 | #define ALT_BPDU_CIST_INTERNAL_ROOT_PATH_COST 97 |
70 | | |
71 | 0 | #define ALT_MSTI_MSTID 0 |
72 | 0 | #define ALT_MSTI_FLAGS 2 |
73 | 0 | #define ALT_MSTI_REGIONAL_ROOT 3 |
74 | 0 | #define ALT_MSTI_INTERNAL_ROOT_PATH_COST 11 |
75 | 0 | #define ALT_MSTI_BRIDGE_IDENTIFIER 15 |
76 | 0 | #define ALT_MSTI_PORT_IDENTIFIER 23 |
77 | 0 | #define ALT_MSTI_REMAINING_HOPS 25 |
78 | | |
79 | 0 | #define ALT_MSTI_MESSAGE_SIZE 26 |
80 | | |
81 | | /* Flag bits */ |
82 | | |
83 | 15 | #define BPDU_FLAGS_TCACK 0x80 |
84 | 15 | #define BPDU_FLAGS_AGREEMENT 0x40 |
85 | 15 | #define BPDU_FLAGS_FORWARDING 0x20 |
86 | 15 | #define BPDU_FLAGS_LEARNING 0x10 |
87 | 15 | #define BPDU_FLAGS_PORT_ROLE_MASK 0x0C |
88 | | #define BPDU_FLAGS_PORT_ROLE_SHIFT 2 |
89 | 15 | #define BPDU_FLAGS_PROPOSAL 0x02 |
90 | 15 | #define BPDU_FLAGS_TC 0x01 |
91 | | |
92 | | void proto_register_bpdu(void); |
93 | | void proto_reg_handoff_bpdu(void); |
94 | | |
95 | | static int proto_bpdu; |
96 | | static int hf_bpdu_proto_id; |
97 | | static int hf_bpdu_version_id; |
98 | | static int hf_bpdu_type; |
99 | | static int hf_bpdu_flags; |
100 | | static int hf_bpdu_flags_tcack; |
101 | | static int hf_bpdu_flags_agreement; |
102 | | static int hf_bpdu_flags_forwarding; |
103 | | static int hf_bpdu_flags_learning; |
104 | | static int hf_bpdu_flags_port_role; |
105 | | static int hf_bpdu_flags_proposal; |
106 | | static int hf_bpdu_flags_tc; |
107 | | static int hf_bpdu_root_prio; |
108 | | static int hf_bpdu_root_sys_id_ext; |
109 | | static int hf_bpdu_root_mac; |
110 | | static int hf_bpdu_root_cost; |
111 | | static int hf_bpdu_bridge_prio; |
112 | | static int hf_bpdu_bridge_sys_id_ext; |
113 | | static int hf_bpdu_bridge_mac; |
114 | | static int hf_bpdu_port_id; |
115 | | static int hf_bpdu_msg_age; |
116 | | static int hf_bpdu_max_age; |
117 | | static int hf_bpdu_hello_time; |
118 | | static int hf_bpdu_forward_delay; |
119 | | static int hf_bpdu_version_1_length; |
120 | | static int hf_bpdu_version_3_length; |
121 | | static int hf_bpdu_mst_config_format_selector; |
122 | | static int hf_bpdu_mst_config_name; |
123 | | static int hf_bpdu_mst_config_revision_level; |
124 | | static int hf_bpdu_mst_config_digest; |
125 | | static int hf_bpdu_cist_internal_root_path_cost; |
126 | | static int hf_bpdu_cist_bridge_prio; |
127 | | static int hf_bpdu_cist_bridge_sys_id_ext; |
128 | | static int hf_bpdu_cist_bridge_mac; |
129 | | static int hf_bpdu_cist_remaining_hops; |
130 | | static int hf_bpdu_msti_flags; |
131 | | static int hf_bpdu_msti_id; |
132 | | static int hf_bpdu_msti_id_FFF; |
133 | | static int hf_bpdu_mst_priority; |
134 | | static int hf_bpdu_msti_regional_root_id; |
135 | | static int hf_bpdu_msti_regional_root_mac; |
136 | | static int hf_bpdu_msti_internal_root_path_cost; |
137 | | static int hf_bpdu_msti_bridge_identifier_priority; |
138 | | static int hf_bpdu_msti_port_identifier_priority; |
139 | | static int hf_bpdu_msti_port_id; |
140 | | static int hf_bpdu_msti_bridge_id; |
141 | | static int hf_bpdu_msti_bridge_id_priority; |
142 | | static int hf_bpdu_msti_bridge_id_mac; |
143 | | static int hf_bpdu_msti_remaining_hops; |
144 | | static int hf_bpdu_version_4_length; |
145 | | static int hf_bpdu_spt_config_format_selector; |
146 | | static int hf_bpdu_spt_config_name; |
147 | | static int hf_bpdu_spt_config_revision_level; |
148 | | static int hf_bpdu_spt_config_digest; |
149 | | static int hf_bpdu_flags_agree_num; |
150 | | static int hf_bpdu_flags_dagree_num; |
151 | | static int hf_bpdu_flags_agree_valid; |
152 | | static int hf_bpdu_flags_restricted_role; |
153 | | static int hf_bpdu_spt_agreement_digest; |
154 | | static int hf_bpdu_agreement_digest_format_id; |
155 | | static int hf_bpdu_agreement_digest_format_capabilities; |
156 | | static int hf_bpdu_agreement_digest_convention_id; |
157 | | static int hf_bpdu_agreement_digest_convention_capabilities; |
158 | | static int hf_bpdu_agreement_digest_edge_count; |
159 | | |
160 | | static int hf_bpdu_pvst_tlvtype; |
161 | | static int hf_bpdu_pvst_tlvlength; |
162 | | static int hf_bpdu_pvst_tlvvalue; |
163 | | static int hf_bpdu_pvst_tlv_origvlan; |
164 | | |
165 | | static int ett_bpdu; |
166 | | static int ett_bpdu_flags; |
167 | | static int ett_root_id; |
168 | | static int ett_bridge_id; |
169 | | static int ett_mstp; |
170 | | static int ett_msti; |
171 | | static int ett_cist_bridge_id; |
172 | | static int ett_spt; |
173 | | static int ett_aux_mcid; |
174 | | static int ett_agreement; |
175 | | static int ett_bpdu_pvst_tlv; |
176 | | |
177 | | static expert_field ei_pvst_tlv_length_invalid; |
178 | | static expert_field ei_pvst_tlv_origvlan_missing; |
179 | | static expert_field ei_pvst_tlv_truncated; |
180 | | static expert_field ei_pvst_tlv_unknown; |
181 | | static expert_field ei_bpdu_type; |
182 | | static expert_field ei_bpdu_version_support; |
183 | | |
184 | | |
185 | | static bool bpdu_use_system_id_extensions = true; |
186 | | |
187 | | static dissector_handle_t gvrp_handle; |
188 | | static dissector_handle_t gmrp_handle; |
189 | | |
190 | | static dissector_handle_t bpdu_handle; |
191 | | static dissector_handle_t bpdu_cisco_handle; |
192 | | |
193 | | static const value_string protocol_id_vals[] = { |
194 | | { 0, "Spanning Tree Protocol" }, |
195 | | { 0, NULL } |
196 | | }; |
197 | | |
198 | 0 | #define BPDU_PVST_TLV_ORIGVLAN 0 /* Originating VLAN TLV in Cisco (R)PVST+ BPDUs */ |
199 | | |
200 | | static const value_string bpdu_pvst_tlv_vals[] = { |
201 | | { BPDU_PVST_TLV_ORIGVLAN, "Originating VLAN" }, |
202 | | { 0, NULL } |
203 | | }; |
204 | | |
205 | | |
206 | 100 | #define BPDU_TYPE_CONF 0x00 /* STP Configuration BPDU */ |
207 | 87 | #define BPDU_TYPE_RST 0x02 /* RST BPDU (or MST) */ |
208 | 29 | #define BPDU_TYPE_TOPOLOGY_CHANGE 0x80 /* STP TCN (Topology change notify) BPDU */ |
209 | | |
210 | | static const value_string bpdu_type_vals[] = { |
211 | | { BPDU_TYPE_CONF, "Configuration" }, |
212 | | { BPDU_TYPE_RST, "Rapid/Multiple Spanning Tree" }, |
213 | | { BPDU_TYPE_TOPOLOGY_CHANGE, "Topology Change Notification" }, |
214 | | { 0, NULL } |
215 | | }; |
216 | | |
217 | | #define PROTO_VERSION_STP 0 |
218 | | #define PROTO_VERSION_RSTP 2 |
219 | | #define PROTO_VERSION_MSTP 3 |
220 | | #define PROTO_VERSION_SPB 4 |
221 | | |
222 | 3 | #define MSTI_FORMAT_UNKNOWN 0 |
223 | 118 | #define MSTI_FORMAT_IEEE_8021S 1 |
224 | 0 | #define MSTI_FORMAT_ALTERNATIVE 2 |
225 | | |
226 | | static const value_string version_id_vals[] = { |
227 | | { PROTO_VERSION_STP, "Spanning Tree" }, |
228 | | { PROTO_VERSION_RSTP, "Rapid Spanning Tree" }, |
229 | | { PROTO_VERSION_MSTP, "Multiple Spanning Tree" }, |
230 | | { PROTO_VERSION_SPB, "Shortest Path Tree" }, |
231 | | { 0, NULL} |
232 | | }; |
233 | | static const value_string role_vals[] = { |
234 | | { 1, "Alternate or Backup" }, |
235 | | { 2, "Root" }, |
236 | | { 3, "Designated" }, |
237 | | { 0, NULL } |
238 | | }; |
239 | | |
240 | | |
241 | | static void |
242 | 0 | dissect_bpdu_pvst_tlv(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb) { |
243 | 0 | bool pvst_tlv_origvlan_present = false; |
244 | 0 | uint16_t tlv_type, tlv_length; |
245 | 0 | int offset = BPDU_PVST_TLV; |
246 | 0 | proto_item * ti = NULL; |
247 | 0 | proto_item * tlv_length_item = NULL; |
248 | 0 | proto_tree * tlv_tree = NULL; |
249 | |
|
250 | 0 | if (tvb_reported_length_remaining(tvb, offset) < 4) /* TLV Type and Length fields occupy 4 bytes in total */ |
251 | 0 | expert_add_info(pinfo, tree, &ei_pvst_tlv_truncated); |
252 | |
|
253 | 0 | while (tvb_reported_length_remaining(tvb, offset) >= 4) { /* TLV Type and Length fields occupy 4 bytes in total */ |
254 | 0 | tlv_type = tvb_get_ntohs(tvb, offset); |
255 | 0 | tlv_length = tvb_get_ntohs(tvb, offset + 2); |
256 | |
|
257 | 0 | tlv_tree = proto_tree_add_subtree(tree, tvb, offset, 4 + tlv_length, |
258 | 0 | ett_bpdu_pvst_tlv, &ti, |
259 | 0 | val_to_str(pinfo->pool, tlv_type, bpdu_pvst_tlv_vals, "Unknown TLV type: 0x%04x")); |
260 | |
|
261 | 0 | proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvtype, tvb, offset, 2, ENC_BIG_ENDIAN); |
262 | 0 | tlv_length_item = proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvlength, |
263 | 0 | tvb, offset + 2, 2, ENC_BIG_ENDIAN); |
264 | |
|
265 | 0 | if (tvb_reported_length_remaining(tvb, offset + 4) < tlv_length) { |
266 | 0 | expert_add_info(pinfo, tlv_length_item, &ei_pvst_tlv_truncated); |
267 | 0 | break; |
268 | 0 | } |
269 | | |
270 | 0 | offset += 4; |
271 | |
|
272 | 0 | switch (tlv_type) { |
273 | 0 | case BPDU_PVST_TLV_ORIGVLAN: |
274 | 0 | if (tlv_length == 2) { /* Originating VLAN ID must be 2 bytes long */ |
275 | 0 | proto_item_append_text(ti, " (PVID): %u", tvb_get_ntohs(tvb, offset)); |
276 | 0 | proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlv_origvlan, tvb, offset, tlv_length, ENC_BIG_ENDIAN); |
277 | 0 | pvst_tlv_origvlan_present = true; |
278 | 0 | } |
279 | 0 | else |
280 | 0 | expert_add_info(pinfo, tlv_length_item, &ei_pvst_tlv_length_invalid); |
281 | 0 | break; |
282 | | |
283 | 0 | default: |
284 | 0 | proto_tree_add_item(tlv_tree, hf_bpdu_pvst_tlvvalue, tvb, offset, tlv_length, ENC_NA); |
285 | 0 | expert_add_info(pinfo, tlv_tree, &ei_pvst_tlv_unknown); |
286 | 0 | break; |
287 | 0 | } |
288 | | |
289 | 0 | offset += tlv_length; |
290 | 0 | } |
291 | | |
292 | 0 | if (pvst_tlv_origvlan_present == false) /* If a (R)PVST+ BPDU lacks the Originating VLAN TLV, it is malformed */ |
293 | 0 | expert_add_info(pinfo, tree, &ei_pvst_tlv_origvlan_missing); |
294 | 0 | } |
295 | | |
296 | | static void |
297 | | dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool is_bpdu_pvst) |
298 | 31 | { |
299 | 31 | uint16_t protocol_identifier; |
300 | 31 | uint8_t protocol_version_identifier; |
301 | 31 | uint8_t bpdu_type; |
302 | 31 | uint8_t flags; |
303 | 31 | uint16_t root_identifier_bridge_priority; |
304 | 31 | uint16_t root_identifier_system_id_extension = 0; |
305 | 31 | const char *root_identifier_mac_str; |
306 | 31 | uint32_t root_path_cost; |
307 | 31 | uint16_t bridge_identifier_bridge_priority; |
308 | 31 | uint16_t bridge_identifier_system_id_extension = 0; |
309 | 31 | const char *bridge_identifier_mac_str; |
310 | 31 | uint16_t port_identifier; |
311 | 31 | double message_age; |
312 | 31 | double max_age; |
313 | 31 | double hello_time; |
314 | 31 | double forward_delay; |
315 | 31 | uint8_t version_1_length; |
316 | 31 | uint16_t version_3_length; |
317 | 31 | uint16_t version_4_length = 0; |
318 | 31 | uint16_t bpdu_version_4_length = 0; |
319 | 31 | uint8_t config_format_selector; |
320 | 31 | uint16_t cist_bridge_identifier_bridge_priority; |
321 | 31 | uint16_t cist_bridge_identifier_system_id_extension = 0; |
322 | 31 | const char *cist_bridge_identifier_mac_str; |
323 | 31 | uint32_t msti_regional_root_mstid, msti_regional_root_priority; |
324 | 31 | const char *msti_regional_root_mac_str; |
325 | 31 | uint16_t msti_bridge_identifier_priority, msti_port_identifier_priority; |
326 | 31 | int total_msti_length, offset, msti_format; |
327 | 31 | int msti_length_remaining; |
328 | | |
329 | 31 | int spt_offset = 0; |
330 | | |
331 | 31 | int MCID_LEN = 51; |
332 | 31 | uint8_t spt_agree_data = 0; |
333 | | |
334 | 31 | proto_tree *bpdu_tree; |
335 | 31 | proto_tree *mstp_tree, *msti_tree, *spt_tree = NULL, *aux_mcid_tree = NULL, *agreement_tree = NULL; |
336 | 31 | proto_item *bpdu_item; |
337 | 31 | proto_item *agreement_item, *proto_id_item, *type_item; |
338 | 31 | proto_tree *root_id_tree; |
339 | 31 | proto_tree *bridge_id_tree; |
340 | 31 | proto_tree *cist_bridge_id_tree; |
341 | | |
342 | 31 | static int * const bpdu_flags[] = { |
343 | 31 | &hf_bpdu_flags_tcack, |
344 | 31 | &hf_bpdu_flags_tc, |
345 | 31 | NULL |
346 | 31 | }; |
347 | | |
348 | 31 | static int * const rst_flags[] = { |
349 | 31 | &hf_bpdu_flags_tcack, |
350 | 31 | &hf_bpdu_flags_agreement, |
351 | 31 | &hf_bpdu_flags_forwarding, |
352 | 31 | &hf_bpdu_flags_learning, |
353 | 31 | &hf_bpdu_flags_port_role, |
354 | 31 | &hf_bpdu_flags_proposal, |
355 | 31 | &hf_bpdu_flags_tc, |
356 | 31 | NULL |
357 | 31 | }; |
358 | | |
359 | | /* GARP application frames require special interpretation of the |
360 | | destination address field; otherwise, they will be mistaken as |
361 | | BPDU frames. |
362 | | Fortunately, they can be recognized by checking the first 6 octets |
363 | | of the destination address, which are in the range from |
364 | | 01-80-C2-00-00-20 to 01-80-C2-00-00-2F. |
365 | | |
366 | | Yes - we *do* need to check the destination address type; |
367 | | on Linux cooked captures, there *is* no destination address, |
368 | | so it's AT_NONE. */ |
369 | 31 | if (pinfo->dl_dst.type == AT_ETHER) { |
370 | 25 | const uint8_t *dstaddr; |
371 | | |
372 | 25 | dstaddr = (const uint8_t *)pinfo->dl_dst.data; |
373 | 25 | if(dstaddr[0] == 0x01 && dstaddr[1] == 0x80 && |
374 | 0 | dstaddr[2] == 0xC2 && dstaddr[3] == 0x00 && |
375 | 0 | dstaddr[4] == 0x00 && ((dstaddr[5] == 0x0D) || ((dstaddr[5] & 0xF0) == 0x20))) { |
376 | |
|
377 | 0 | switch (dstaddr[5]) { |
378 | | |
379 | 0 | case 0x20: |
380 | | /* for GMRP */ |
381 | 0 | call_dissector(gmrp_handle, tvb, pinfo, tree); |
382 | 0 | return; |
383 | | |
384 | 0 | case 0x21: |
385 | 0 | case 0x0D: |
386 | | /* for GVRP */ |
387 | 0 | call_dissector(gvrp_handle, tvb, pinfo, tree); |
388 | 0 | return; |
389 | 0 | } |
390 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "GARP"); |
391 | | /* Generic Attribute Registration Protocol */ |
392 | |
|
393 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
394 | 0 | "Unknown GARP application (0x%02X)", |
395 | 0 | dstaddr[5]); |
396 | |
|
397 | 0 | return; |
398 | 0 | } |
399 | 25 | } |
400 | | |
401 | 31 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "STP"); /* Spanning Tree Protocol */ |
402 | 31 | col_clear(pinfo->cinfo, COL_INFO); |
403 | | |
404 | 31 | bpdu_type = tvb_get_uint8(tvb, BPDU_TYPE); |
405 | | |
406 | 31 | protocol_version_identifier = tvb_get_uint8(tvb, BPDU_VERSION_IDENTIFIER); |
407 | | |
408 | 31 | switch (bpdu_type) { |
409 | | |
410 | 10 | case BPDU_TYPE_CONF: |
411 | 26 | case BPDU_TYPE_RST: |
412 | 26 | flags = tvb_get_uint8(tvb, BPDU_FLAGS); |
413 | 26 | root_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_ROOT_IDENTIFIER); |
414 | 26 | if (bpdu_use_system_id_extensions ) { |
415 | 25 | root_identifier_system_id_extension = root_identifier_bridge_priority & 0x0fff; |
416 | 25 | root_identifier_bridge_priority &= 0xf000; |
417 | 25 | } |
418 | 26 | root_identifier_mac_str = tvb_ether_to_str(pinfo->pool, tvb, BPDU_ROOT_IDENTIFIER + 2); |
419 | 26 | root_path_cost = tvb_get_ntohl(tvb, BPDU_ROOT_PATH_COST); |
420 | 26 | port_identifier = tvb_get_ntohs(tvb, BPDU_PORT_IDENTIFIER); |
421 | 26 | break; |
422 | | |
423 | 5 | default: |
424 | | /* Squelch GCC complaints. */ |
425 | 5 | flags = 0; |
426 | 5 | root_identifier_bridge_priority = 0; |
427 | 5 | root_identifier_mac_str = NULL; |
428 | 5 | root_path_cost = 0; |
429 | 5 | port_identifier = 0; |
430 | 5 | break; |
431 | 31 | } |
432 | | |
433 | 29 | switch (bpdu_type) { |
434 | | |
435 | 8 | case BPDU_TYPE_CONF: |
436 | 8 | if (bpdu_use_system_id_extensions ) { |
437 | 8 | col_add_fstr(pinfo->cinfo, COL_INFO, |
438 | 8 | "Conf. %sRoot = %d/%d/%s Cost = %d Port = 0x%04x", |
439 | 8 | flags & 0x1 ? "TC + " : "", |
440 | 8 | root_identifier_bridge_priority, |
441 | 8 | root_identifier_system_id_extension, |
442 | 8 | root_identifier_mac_str, |
443 | 8 | root_path_cost, port_identifier); |
444 | 8 | } else { |
445 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
446 | 0 | "Conf. %sRoot = %d/%s Cost = %d Port = 0x%04x", |
447 | 0 | flags & 0x1 ? "TC + " : "", |
448 | 0 | root_identifier_bridge_priority, root_identifier_mac_str, |
449 | 0 | root_path_cost, port_identifier); |
450 | 0 | } |
451 | 8 | break; |
452 | | |
453 | 0 | case BPDU_TYPE_TOPOLOGY_CHANGE: |
454 | 0 | col_set_str(pinfo->cinfo, COL_INFO, "Topology Change Notification"); |
455 | 0 | break; |
456 | | |
457 | 16 | case BPDU_TYPE_RST: |
458 | 16 | if (bpdu_use_system_id_extensions ) { |
459 | 16 | col_add_fstr(pinfo->cinfo, COL_INFO, |
460 | 16 | "%sT. %sRoot = %d/%d/%s Cost = %d Port = 0x%04x", |
461 | 16 | protocol_version_identifier == 3 ? "MS": |
462 | 16 | (protocol_version_identifier == 4 ? "SP":"RS"), |
463 | 16 | flags & 0x1 ? "TC + " : "", |
464 | 16 | root_identifier_bridge_priority, |
465 | 16 | root_identifier_system_id_extension, |
466 | 16 | root_identifier_mac_str, |
467 | 16 | root_path_cost, port_identifier); |
468 | 16 | } else { |
469 | 0 | col_add_fstr(pinfo->cinfo, COL_INFO, |
470 | 0 | "%sT. %sRoot = %d/%s Cost = %d Port = 0x%04x", |
471 | 0 | protocol_version_identifier == 3 ? "MS": |
472 | 0 | (protocol_version_identifier == 4 ? "SP":"RS"), |
473 | 0 | flags & 0x1 ? "TC + " : "", |
474 | 0 | root_identifier_bridge_priority, root_identifier_mac_str, |
475 | 0 | root_path_cost, port_identifier); |
476 | 0 | } |
477 | 16 | break; |
478 | | |
479 | 5 | default: |
480 | 5 | col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown BPDU type (%u)", bpdu_type); |
481 | 5 | break; |
482 | 29 | } |
483 | | |
484 | 29 | bpdu_item = proto_tree_add_protocol_format(tree, proto_bpdu, tvb, 0, -1, |
485 | 29 | "Spanning Tree Protocol"); |
486 | 29 | bpdu_tree = proto_item_add_subtree(bpdu_item, ett_bpdu); |
487 | | |
488 | 29 | protocol_identifier = tvb_get_ntohs(tvb, BPDU_IDENTIFIER); |
489 | 29 | proto_tree_add_uint(bpdu_tree, hf_bpdu_proto_id, tvb, BPDU_IDENTIFIER, 2, |
490 | 29 | protocol_identifier); |
491 | | |
492 | 29 | proto_id_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_version_id, tvb, |
493 | 29 | BPDU_VERSION_IDENTIFIER, 1, |
494 | 29 | protocol_version_identifier); |
495 | 29 | switch (protocol_version_identifier) { |
496 | | |
497 | 8 | case 0: |
498 | 8 | break; |
499 | | |
500 | 1 | case 2: |
501 | 2 | case 3: |
502 | 2 | case 4: |
503 | 2 | break; |
504 | | |
505 | 19 | default: |
506 | 19 | expert_add_info(pinfo, proto_id_item, &ei_bpdu_version_support); |
507 | 19 | break; |
508 | 29 | } |
509 | 29 | type_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_type, tvb, BPDU_TYPE, 1, bpdu_type); |
510 | | |
511 | 29 | if (bpdu_type == BPDU_TYPE_TOPOLOGY_CHANGE) { |
512 | 0 | set_actual_length(tvb, TC_BPDU_SIZE); |
513 | 0 | return; |
514 | 0 | } |
515 | | |
516 | 29 | if (bpdu_type != BPDU_TYPE_CONF && bpdu_type != BPDU_TYPE_RST) { |
517 | | /* Unknown BPDU type - just display the rest of the PDU as data */ |
518 | 5 | expert_add_info(pinfo, type_item, &ei_bpdu_type); |
519 | 5 | return; |
520 | 5 | } |
521 | | |
522 | 24 | bridge_identifier_bridge_priority = tvb_get_ntohs(tvb, BPDU_BRIDGE_IDENTIFIER); |
523 | 24 | if (bpdu_use_system_id_extensions ) { |
524 | 24 | bridge_identifier_system_id_extension = bridge_identifier_bridge_priority & 0x0fff; |
525 | 24 | bridge_identifier_bridge_priority &= 0xf000; |
526 | 24 | } |
527 | 24 | bridge_identifier_mac_str = tvb_ether_to_str(pinfo->pool, tvb, BPDU_BRIDGE_IDENTIFIER + 2); |
528 | | |
529 | 24 | if (bpdu_type == BPDU_TYPE_RST) { |
530 | 16 | proto_tree_add_bitmask_value_with_flags(bpdu_tree, tvb, BPDU_FLAGS, hf_bpdu_flags, ett_bpdu_flags, rst_flags, flags, BMT_NO_FALSE|BMT_NO_TFS); |
531 | 16 | } else { |
532 | 8 | proto_tree_add_bitmask_value_with_flags(bpdu_tree, tvb, BPDU_FLAGS, hf_bpdu_flags, ett_bpdu_flags, bpdu_flags, flags, BMT_NO_FALSE|BMT_NO_TFS); |
533 | 8 | } |
534 | | |
535 | | /* add Identifier with format based on preference value |
536 | | * bpdu_use_system_id_extensions |
537 | | * */ |
538 | 24 | if (bpdu_use_system_id_extensions) { |
539 | 24 | root_id_tree = proto_tree_add_subtree_format(bpdu_tree, tvb, |
540 | 24 | BPDU_ROOT_IDENTIFIER, 8, |
541 | 24 | ett_root_id, NULL, |
542 | 24 | "Root Identifier: %d / %d / %s", |
543 | 24 | root_identifier_bridge_priority, |
544 | 24 | root_identifier_system_id_extension, |
545 | 24 | root_identifier_mac_str); |
546 | 24 | proto_tree_add_uint(root_id_tree, hf_bpdu_root_prio, tvb, |
547 | 24 | BPDU_ROOT_IDENTIFIER , 1, |
548 | 24 | root_identifier_bridge_priority); |
549 | 24 | proto_tree_add_uint(root_id_tree, hf_bpdu_root_sys_id_ext, tvb, |
550 | 24 | BPDU_ROOT_IDENTIFIER , 2, |
551 | 24 | root_identifier_system_id_extension); |
552 | 24 | proto_tree_add_item(root_id_tree, hf_bpdu_root_mac, tvb, |
553 | 24 | BPDU_ROOT_IDENTIFIER + 2, 6, ENC_NA); |
554 | | |
555 | 24 | } else { |
556 | 0 | root_id_tree = proto_tree_add_subtree_format(bpdu_tree, tvb, |
557 | 0 | BPDU_ROOT_IDENTIFIER, 8, |
558 | 0 | ett_root_id, NULL, |
559 | 0 | "Root Identifier: %d / %s", |
560 | 0 | root_identifier_bridge_priority, |
561 | 0 | root_identifier_mac_str); |
562 | 0 | proto_tree_add_uint(root_id_tree, hf_bpdu_root_prio, tvb, |
563 | 0 | BPDU_ROOT_IDENTIFIER , 2, |
564 | 0 | root_identifier_bridge_priority); |
565 | 0 | proto_tree_add_item(root_id_tree, hf_bpdu_root_mac, tvb, |
566 | 0 | BPDU_ROOT_IDENTIFIER + 2, 6, ENC_NA); |
567 | 0 | } |
568 | | /* end of Identifier formatting */ |
569 | | |
570 | 24 | proto_tree_add_uint(bpdu_tree, hf_bpdu_root_cost, tvb, |
571 | 24 | BPDU_ROOT_PATH_COST, 4, root_path_cost); |
572 | | |
573 | | /* add Identifier with format based on preference value |
574 | | * bpdu_use_system_id_extensions |
575 | | * */ |
576 | 24 | if (bpdu_use_system_id_extensions) { |
577 | 24 | bridge_id_tree = proto_tree_add_subtree_format(bpdu_tree, tvb, |
578 | 24 | BPDU_BRIDGE_IDENTIFIER, 8, |
579 | 24 | ett_bridge_id, NULL, |
580 | 24 | "Bridge Identifier: %d / %d / %s", |
581 | 24 | bridge_identifier_bridge_priority, |
582 | 24 | bridge_identifier_system_id_extension, |
583 | 24 | bridge_identifier_mac_str); |
584 | 24 | proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_prio, tvb, |
585 | 24 | BPDU_BRIDGE_IDENTIFIER , 1, |
586 | 24 | bridge_identifier_bridge_priority); |
587 | 24 | proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_sys_id_ext, tvb, |
588 | 24 | BPDU_BRIDGE_IDENTIFIER , 2, |
589 | 24 | bridge_identifier_system_id_extension); |
590 | 24 | proto_tree_add_item(bridge_id_tree, hf_bpdu_bridge_mac, tvb, |
591 | 24 | BPDU_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
592 | 24 | } else { |
593 | 0 | bridge_id_tree = proto_tree_add_subtree_format(bpdu_tree, tvb, |
594 | 0 | BPDU_BRIDGE_IDENTIFIER, 8, |
595 | 0 | ett_bridge_id, NULL, |
596 | 0 | "Bridge Identifier: %d / %s", |
597 | 0 | bridge_identifier_bridge_priority, |
598 | 0 | bridge_identifier_mac_str); |
599 | 0 | proto_tree_add_uint(bridge_id_tree, hf_bpdu_bridge_prio, tvb, |
600 | 0 | BPDU_BRIDGE_IDENTIFIER , 2, |
601 | 0 | bridge_identifier_bridge_priority); |
602 | 0 | proto_tree_add_item(bridge_id_tree, hf_bpdu_bridge_mac, tvb, |
603 | 0 | BPDU_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
604 | 0 | } |
605 | | /* end of Identifier formatting */ |
606 | | |
607 | 24 | proto_tree_add_uint(bpdu_tree, hf_bpdu_port_id, tvb, |
608 | 24 | BPDU_PORT_IDENTIFIER, 2, port_identifier); |
609 | 24 | message_age = tvb_get_ntohs(tvb, BPDU_MESSAGE_AGE) / 256.0; |
610 | 24 | proto_tree_add_double(bpdu_tree, hf_bpdu_msg_age, tvb, BPDU_MESSAGE_AGE, 2, |
611 | 24 | message_age); |
612 | 24 | max_age = tvb_get_ntohs(tvb, BPDU_MAX_AGE) / 256.0; |
613 | 24 | proto_tree_add_double(bpdu_tree, hf_bpdu_max_age, tvb, BPDU_MAX_AGE, 2, |
614 | 24 | max_age); |
615 | 24 | hello_time = tvb_get_ntohs(tvb, BPDU_HELLO_TIME) / 256.0; |
616 | 24 | proto_tree_add_double(bpdu_tree, hf_bpdu_hello_time, tvb, |
617 | 24 | BPDU_HELLO_TIME, 2, hello_time); |
618 | 24 | forward_delay = tvb_get_ntohs(tvb, BPDU_FORWARD_DELAY) / 256.0; |
619 | 24 | proto_tree_add_double(bpdu_tree, hf_bpdu_forward_delay, tvb, |
620 | 24 | BPDU_FORWARD_DELAY, 2, forward_delay); |
621 | | |
622 | 24 | if (bpdu_type == BPDU_TYPE_CONF) { |
623 | 6 | if (is_bpdu_pvst) |
624 | 0 | dissect_bpdu_pvst_tlv(pinfo, bpdu_tree, tvb); |
625 | | |
626 | | /* Nothing more in this BPDU */ |
627 | 6 | set_actual_length(tvb, CONF_BPDU_SIZE); |
628 | 6 | return; |
629 | 6 | } |
630 | | |
631 | | /* RST or MST BPDU */ |
632 | 18 | version_1_length = tvb_get_uint8(tvb, BPDU_VERSION_1_LENGTH); |
633 | 18 | proto_tree_add_uint(bpdu_tree, hf_bpdu_version_1_length, tvb, |
634 | 18 | BPDU_VERSION_1_LENGTH, 1, version_1_length); |
635 | | /* Is this an MST BPDU? */ |
636 | 18 | if (protocol_version_identifier >= 3 && version_1_length == 0 && |
637 | 13 | tvb_reported_length(tvb) >= 102) { |
638 | | /* |
639 | | * OK, it passes the "Protocol Identifier is 0000 0000 |
640 | | * 0000 0000", "Protocol Version Identifier is 3 or |
641 | | * greater", "BPDU Type is 0000 0010", "contains 102 or |
642 | | * more octets", and "a Version 1 Length of 0" tests. |
643 | | */ |
644 | 12 | version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH); |
645 | 12 | proto_tree_add_uint(bpdu_tree, hf_bpdu_version_3_length, tvb, |
646 | 12 | BPDU_VERSION_3_LENGTH, 2, version_3_length); |
647 | | |
648 | | /* |
649 | | * Check the Version 3 Length, and see whether it's a |
650 | | * multiple of the MSTI Configuration Message length. Also |
651 | | * check the config_format_selector because some MST BPDU's |
652 | | * have BPDU_VERSION_3_LENGTH set to 0 and use the |
653 | | * field BPDU_MST_CONFIG_FORMAT_SELECTOR as a length-field |
654 | | * for the MSTI data. |
655 | | */ |
656 | 12 | config_format_selector = tvb_get_uint8(tvb, BPDU_MST_CONFIG_FORMAT_SELECTOR); |
657 | 12 | if (version_3_length != 0) { |
658 | 9 | msti_format = MSTI_FORMAT_IEEE_8021S; |
659 | 9 | if (version_3_length >= VERSION_3_STATIC_LENGTH) { |
660 | 3 | total_msti_length = version_3_length - VERSION_3_STATIC_LENGTH; |
661 | 6 | } else { |
662 | | /* |
663 | | * XXX - there appears to be an ambiguity in the 802.3Q-2003 |
664 | | * standard and at least some of the 802.3s drafts. |
665 | | * |
666 | | * The "Version 3 Length" field is defined to be "the number of |
667 | | * octets taken by the parameters that follow in the BPDU", but |
668 | | * it's spoken of as "representing an integral number, from 0 to |
669 | | * 64 inclusive, of MSTI Configuration Messages". |
670 | | * |
671 | | * According to mail from a member of the stds-802-1@ieee.org list, |
672 | | * the latter of those is just saying that the length must not have |
673 | | * a value that implies that there's a partial MSTI message in the |
674 | | * packet; it's still in units of octets, not messages. |
675 | | * |
676 | | * However, it appears that Cisco's C3550 software (C3550-I5Q3L2-M, |
677 | | * Version 12.1(12c)EA1) might be sending out lengths in units of |
678 | | * messages. |
679 | | * |
680 | | * This length can't be the number of octets taken by the parameters |
681 | | * that follow in the BPDU, because it's less than the fixed-length |
682 | | * portion of those parameters, so we assume the length is a count of |
683 | | * messages. |
684 | | */ |
685 | 6 | total_msti_length = version_3_length * MSTI_MESSAGE_SIZE; |
686 | 6 | } |
687 | 9 | } else { |
688 | 3 | if (tvb_reported_length(tvb) == (unsigned)config_format_selector + MST_BPDU_SIZE + 1 ) { |
689 | 0 | msti_format = MSTI_FORMAT_ALTERNATIVE; |
690 | 0 | total_msti_length = config_format_selector - VERSION_3_STATIC_LENGTH; |
691 | 3 | } else { |
692 | | /* |
693 | | * XXX - Unknown MSTI format, since version_3_length is 0 |
694 | | * lets assume there are no msti instances in the packet. |
695 | | */ |
696 | 3 | msti_format = MSTI_FORMAT_UNKNOWN; |
697 | 3 | total_msti_length = 0; |
698 | 3 | } |
699 | 3 | } |
700 | 12 | if (protocol_version_identifier == 3) { |
701 | 0 | set_actual_length(tvb, BPDU_MSTI + total_msti_length); |
702 | 0 | } |
703 | | |
704 | 12 | mstp_tree = proto_tree_add_subtree(bpdu_tree, tvb, BPDU_VERSION_3_LENGTH, |
705 | 12 | -1, ett_mstp, NULL, "MST Extension"); |
706 | | |
707 | 12 | proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_format_selector, tvb, |
708 | 12 | BPDU_MST_CONFIG_FORMAT_SELECTOR, 1, ENC_BIG_ENDIAN); |
709 | 12 | proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_name, tvb, |
710 | 12 | BPDU_MST_CONFIG_NAME, 32, ENC_ASCII|ENC_NA); |
711 | | |
712 | 12 | proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_revision_level, tvb, |
713 | 12 | BPDU_MST_CONFIG_REVISION_LEVEL, 2, ENC_BIG_ENDIAN); |
714 | 12 | proto_tree_add_item(mstp_tree, hf_bpdu_mst_config_digest, tvb, |
715 | 12 | BPDU_MST_CONFIG_DIGEST, 16, ENC_NA); |
716 | | |
717 | 12 | switch(msti_format) { |
718 | | |
719 | 9 | case MSTI_FORMAT_IEEE_8021S: |
720 | 9 | proto_tree_add_item(mstp_tree, hf_bpdu_cist_internal_root_path_cost, tvb, |
721 | 9 | BPDU_CIST_INTERNAL_ROOT_PATH_COST, 4, ENC_BIG_ENDIAN); |
722 | | |
723 | 9 | cist_bridge_identifier_bridge_priority = tvb_get_ntohs(tvb,BPDU_CIST_BRIDGE_IDENTIFIER); |
724 | 9 | cist_bridge_identifier_mac_str = tvb_ether_to_str(pinfo->pool, tvb, BPDU_CIST_BRIDGE_IDENTIFIER + 2); |
725 | | |
726 | | /* add Identifier with format based on preference value |
727 | | * bpdu_use_system_id_extensions |
728 | | * */ |
729 | 9 | if (bpdu_use_system_id_extensions ) { |
730 | 9 | cist_bridge_identifier_system_id_extension = cist_bridge_identifier_bridge_priority & 0x0fff; |
731 | 9 | cist_bridge_identifier_bridge_priority &= 0xf000; |
732 | | |
733 | 9 | cist_bridge_id_tree = proto_tree_add_subtree_format(mstp_tree, tvb, |
734 | 9 | BPDU_CIST_BRIDGE_IDENTIFIER, 8, |
735 | 9 | ett_cist_bridge_id, NULL, |
736 | 9 | "CIST Bridge Identifier: %d / %d / %s", |
737 | 9 | cist_bridge_identifier_bridge_priority, |
738 | 9 | cist_bridge_identifier_system_id_extension, |
739 | 9 | cist_bridge_identifier_mac_str); |
740 | 9 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb, |
741 | 9 | BPDU_CIST_BRIDGE_IDENTIFIER , 1, |
742 | 9 | cist_bridge_identifier_bridge_priority); |
743 | 9 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_sys_id_ext, tvb, |
744 | 9 | BPDU_CIST_BRIDGE_IDENTIFIER , 2, |
745 | 9 | cist_bridge_identifier_system_id_extension); |
746 | 9 | proto_tree_add_item(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac, tvb, |
747 | 9 | BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
748 | | |
749 | 9 | } else { |
750 | 0 | cist_bridge_id_tree = proto_tree_add_subtree_format(mstp_tree, tvb, |
751 | 0 | BPDU_CIST_BRIDGE_IDENTIFIER, 8, |
752 | 0 | ett_cist_bridge_id, NULL, |
753 | 0 | "CIST Bridge Identifier: %d / %s", |
754 | 0 | cist_bridge_identifier_bridge_priority, |
755 | 0 | cist_bridge_identifier_mac_str); |
756 | 0 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb, |
757 | 0 | BPDU_CIST_BRIDGE_IDENTIFIER , 2, |
758 | 0 | cist_bridge_identifier_bridge_priority); |
759 | 0 | proto_tree_add_item(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac, tvb, |
760 | 0 | BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
761 | 0 | } |
762 | | /* end of Identifier formatting */ |
763 | | |
764 | 9 | break; |
765 | | |
766 | 0 | case MSTI_FORMAT_ALTERNATIVE: |
767 | 0 | cist_bridge_identifier_bridge_priority = tvb_get_ntohs(tvb,ALT_BPDU_CIST_BRIDGE_IDENTIFIER); |
768 | 0 | cist_bridge_identifier_mac_str = tvb_ether_to_str(pinfo->pool, tvb, ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2); |
769 | | |
770 | | /* add Identifier with format based on preference value |
771 | | * bpdu_use_system_id_extensions |
772 | | * */ |
773 | 0 | if (bpdu_use_system_id_extensions ) { |
774 | 0 | cist_bridge_identifier_system_id_extension = cist_bridge_identifier_bridge_priority & 0x0fff; |
775 | 0 | cist_bridge_identifier_bridge_priority &= 0xf000; |
776 | |
|
777 | 0 | cist_bridge_id_tree = proto_tree_add_subtree_format(mstp_tree, tvb, |
778 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER, 8, |
779 | 0 | ett_cist_bridge_id, NULL, |
780 | 0 | "CIST Bridge Identifier: %d / %d / %s", |
781 | 0 | cist_bridge_identifier_bridge_priority, |
782 | 0 | cist_bridge_identifier_system_id_extension, |
783 | 0 | cist_bridge_identifier_mac_str); |
784 | 0 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb, |
785 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 1, |
786 | 0 | cist_bridge_identifier_bridge_priority); |
787 | 0 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_sys_id_ext, tvb, |
788 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 2, |
789 | 0 | cist_bridge_identifier_system_id_extension); |
790 | 0 | proto_tree_add_item(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac, tvb, |
791 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
792 | 0 | } else { |
793 | 0 | cist_bridge_id_tree = proto_tree_add_subtree_format(mstp_tree, tvb, |
794 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER, 8, |
795 | 0 | ett_cist_bridge_id, NULL, |
796 | 0 | "CIST Bridge Identifier: %d / %s", |
797 | 0 | cist_bridge_identifier_bridge_priority, |
798 | 0 | cist_bridge_identifier_mac_str); |
799 | 0 | proto_tree_add_uint(cist_bridge_id_tree, hf_bpdu_cist_bridge_prio, tvb, |
800 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER , 2, |
801 | 0 | cist_bridge_identifier_bridge_priority); |
802 | 0 | proto_tree_add_item(cist_bridge_id_tree, hf_bpdu_cist_bridge_mac, tvb, |
803 | 0 | ALT_BPDU_CIST_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
804 | 0 | } |
805 | | /* end of Identifier formatting */ |
806 | |
|
807 | 0 | proto_tree_add_item(mstp_tree, hf_bpdu_cist_internal_root_path_cost, tvb, |
808 | 0 | ALT_BPDU_CIST_INTERNAL_ROOT_PATH_COST, 4, ENC_BIG_ENDIAN); |
809 | |
|
810 | 0 | break; |
811 | 12 | } |
812 | | |
813 | 12 | proto_tree_add_item(mstp_tree, hf_bpdu_cist_remaining_hops, tvb, |
814 | 12 | BPDU_CIST_REMAINING_HOPS, 1, ENC_BIG_ENDIAN); |
815 | | /* MSTI messages */ |
816 | 12 | offset = BPDU_MSTI; |
817 | 12 | msti_length_remaining = total_msti_length; |
818 | 104 | while (msti_length_remaining > 0) { |
819 | 100 | switch(msti_format) { |
820 | | |
821 | 100 | case MSTI_FORMAT_IEEE_8021S: |
822 | 100 | msti_regional_root_mstid = tvb_get_uint8(tvb, offset+ MSTI_REGIONAL_ROOT); |
823 | 100 | msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8; |
824 | 100 | msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) + |
825 | 100 | tvb_get_uint8(tvb, offset+ MSTI_REGIONAL_ROOT+1); |
826 | 100 | msti_regional_root_mac_str = tvb_ether_to_str(pinfo->pool, tvb, offset + MSTI_REGIONAL_ROOT + 2); |
827 | | |
828 | 100 | msti_tree = proto_tree_add_subtree_format(mstp_tree, tvb, offset, 16, ett_msti, NULL, |
829 | 100 | "MSTID %d, Regional Root Identifier %d / %s", |
830 | 100 | msti_regional_root_mstid, |
831 | 100 | msti_regional_root_priority, |
832 | 100 | msti_regional_root_mac_str); |
833 | | |
834 | | /* flags */ |
835 | 100 | proto_tree_add_bitmask_with_flags(msti_tree, tvb, offset+MSTI_FLAGS, hf_bpdu_msti_flags, ett_bpdu_flags, rst_flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS); |
836 | | |
837 | | /* pri, MSTID, Regional root */ |
838 | 100 | proto_tree_add_item(msti_tree, hf_bpdu_mst_priority, tvb, offset + MSTI_REGIONAL_ROOT, 1, ENC_BIG_ENDIAN); |
839 | 100 | proto_tree_add_item(msti_tree, hf_bpdu_msti_id_FFF, tvb, offset + MSTI_REGIONAL_ROOT, 2, ENC_BIG_ENDIAN); |
840 | 100 | proto_tree_add_item(msti_tree, hf_bpdu_msti_regional_root_mac, tvb, |
841 | 100 | offset + MSTI_REGIONAL_ROOT + 2, 6, ENC_NA); |
842 | | |
843 | 100 | proto_tree_add_item(msti_tree, hf_bpdu_msti_internal_root_path_cost, tvb, |
844 | 100 | offset+MSTI_INTERNAL_ROOT_PATH_COST, 4, ENC_BIG_ENDIAN); |
845 | | |
846 | 100 | msti_bridge_identifier_priority = tvb_get_uint8(tvb, offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY) >> 4; |
847 | 100 | msti_port_identifier_priority = tvb_get_uint8(tvb, offset+MSTI_PORT_IDENTIFIER_PRIORITY) >> 4; |
848 | | |
849 | 100 | proto_tree_add_uint(msti_tree, hf_bpdu_msti_bridge_identifier_priority, tvb, |
850 | 100 | offset+MSTI_BRIDGE_IDENTIFIER_PRIORITY, 1, |
851 | 100 | msti_bridge_identifier_priority); |
852 | 100 | proto_tree_add_uint(msti_tree, hf_bpdu_msti_port_identifier_priority, tvb, |
853 | 100 | offset+MSTI_PORT_IDENTIFIER_PRIORITY, 1, |
854 | 100 | msti_port_identifier_priority); |
855 | | |
856 | 100 | proto_tree_add_item(msti_tree, hf_bpdu_msti_remaining_hops, tvb, |
857 | 100 | offset + MSTI_REMAINING_HOPS, 1, ENC_BIG_ENDIAN); |
858 | | |
859 | 100 | msti_length_remaining -= MSTI_MESSAGE_SIZE; |
860 | 100 | offset += MSTI_MESSAGE_SIZE; |
861 | 100 | break; |
862 | | |
863 | 0 | case MSTI_FORMAT_ALTERNATIVE: |
864 | 0 | msti_regional_root_mstid = tvb_get_uint8(tvb, offset+ ALT_MSTI_REGIONAL_ROOT); |
865 | 0 | msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8; |
866 | 0 | msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) + |
867 | 0 | tvb_get_uint8(tvb, offset+ ALT_MSTI_REGIONAL_ROOT+1); |
868 | 0 | msti_regional_root_mac_str = tvb_ether_to_str(pinfo->pool, tvb, offset+ ALT_MSTI_REGIONAL_ROOT + 2); |
869 | |
|
870 | 0 | msti_tree = proto_tree_add_subtree_format(mstp_tree, tvb, offset, 16, ett_msti, NULL, |
871 | 0 | "MSTID %d, Regional Root Identifier %d / %s", |
872 | 0 | msti_regional_root_mstid, |
873 | 0 | msti_regional_root_priority, |
874 | 0 | msti_regional_root_mac_str); |
875 | |
|
876 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_id, tvb, offset+ALT_MSTI_MSTID, 2, ENC_BIG_ENDIAN); |
877 | | |
878 | | /* flags */ |
879 | 0 | proto_tree_add_bitmask_with_flags(msti_tree, tvb, offset+ALT_MSTI_FLAGS, hf_bpdu_msti_flags, ett_bpdu_flags, rst_flags, ENC_NA, BMT_NO_FALSE|BMT_NO_TFS); |
880 | | |
881 | | /* pri, MSTID, Regional root */ |
882 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_mst_priority, tvb, offset + ALT_MSTI_REGIONAL_ROOT, 1, ENC_BIG_ENDIAN); |
883 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_regional_root_id, tvb, offset + ALT_MSTI_REGIONAL_ROOT, 2, ENC_BIG_ENDIAN); |
884 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_regional_root_mac, tvb, |
885 | 0 | offset + ALT_MSTI_REGIONAL_ROOT + 2, 6, ENC_NA); |
886 | |
|
887 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_internal_root_path_cost, tvb, |
888 | 0 | offset+ALT_MSTI_INTERNAL_ROOT_PATH_COST, 4, ENC_BIG_ENDIAN); |
889 | |
|
890 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_bridge_id, tvb, offset + ALT_MSTI_BRIDGE_IDENTIFIER, 2, ENC_BIG_ENDIAN); |
891 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_bridge_id_priority, tvb, offset + ALT_MSTI_BRIDGE_IDENTIFIER, 2, ENC_BIG_ENDIAN); |
892 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_bridge_id_mac, tvb, |
893 | 0 | offset + ALT_MSTI_BRIDGE_IDENTIFIER + 2, 6, ENC_NA); |
894 | |
|
895 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_port_id, tvb, offset+ALT_MSTI_PORT_IDENTIFIER, 2, ENC_BIG_ENDIAN); |
896 | |
|
897 | 0 | proto_tree_add_item(msti_tree, hf_bpdu_msti_remaining_hops, tvb, |
898 | 0 | offset + ALT_MSTI_REMAINING_HOPS, 1, ENC_BIG_ENDIAN); |
899 | |
|
900 | 0 | msti_length_remaining -= ALT_MSTI_MESSAGE_SIZE; |
901 | 0 | offset += ALT_MSTI_MESSAGE_SIZE; |
902 | 0 | break; |
903 | 100 | } |
904 | 100 | } |
905 | | |
906 | 4 | if (protocol_version_identifier >= 4 && version_1_length == 0 |
907 | 4 | && tvb_reported_length(tvb) >= 106) { |
908 | | /* |
909 | | * OK, it passes the "Protocol Identifier is 0000 0000 |
910 | | * 0000 0000", "Protocol Version Identifier is 4 or |
911 | | * greater", "BPDU Type is 0000 0010", "contains 106 or |
912 | | * more octets", and "a Version 1 Length of 0" tests. |
913 | | */ |
914 | 4 | bpdu_version_4_length = BPDU_MSTI + total_msti_length; |
915 | 4 | version_4_length = tvb_get_ntohs(tvb, bpdu_version_4_length); |
916 | | |
917 | 4 | proto_tree_add_uint(bpdu_tree, hf_bpdu_version_4_length, tvb, |
918 | 4 | bpdu_version_4_length, 2, version_4_length); |
919 | | |
920 | | /* version 4 length is 55 or more. |
921 | | */ |
922 | 4 | if (version_4_length >= 53) { |
923 | 4 | static int * const agreements[] = { |
924 | 4 | &hf_bpdu_flags_agree_num, |
925 | 4 | &hf_bpdu_flags_dagree_num, |
926 | 4 | &hf_bpdu_flags_agree_valid, |
927 | 4 | &hf_bpdu_flags_restricted_role, |
928 | 4 | NULL |
929 | 4 | }; |
930 | | |
931 | 4 | spt_tree = proto_tree_add_subtree(bpdu_tree, tvb, bpdu_version_4_length, -1, |
932 | 4 | ett_spt, NULL, "SPT Extension"); |
933 | | |
934 | 4 | spt_offset = (bpdu_version_4_length + 2); |
935 | | |
936 | | /* Aux MCID: */ |
937 | | |
938 | 4 | aux_mcid_tree = proto_tree_add_subtree(spt_tree, tvb, spt_offset, |
939 | 4 | MCID_LEN, ett_aux_mcid, NULL, "MCID Data"); |
940 | | |
941 | 4 | proto_tree_add_item(aux_mcid_tree, |
942 | 4 | hf_bpdu_spt_config_format_selector, tvb, spt_offset, 1, |
943 | 4 | ENC_BIG_ENDIAN); |
944 | 4 | proto_tree_add_item(aux_mcid_tree, hf_bpdu_spt_config_name, tvb, |
945 | 4 | spt_offset + 1, 32, ENC_ASCII | ENC_NA); |
946 | | |
947 | 4 | proto_tree_add_item(aux_mcid_tree, |
948 | 4 | hf_bpdu_spt_config_revision_level, tvb, spt_offset + 33, |
949 | 4 | 2, ENC_BIG_ENDIAN); |
950 | 4 | proto_tree_add_item(aux_mcid_tree, hf_bpdu_spt_config_digest, |
951 | 4 | tvb, spt_offset + 35, 16, ENC_NA); |
952 | 4 | spt_offset += MCID_LEN; |
953 | | |
954 | | /* Agreement Data */ |
955 | 4 | agreement_tree = proto_tree_add_subtree(spt_tree, tvb, spt_offset, |
956 | 4 | -1, ett_agreement, &agreement_item, "Agreement Data"); |
957 | | |
958 | 4 | spt_agree_data = tvb_get_uint8(tvb, spt_offset); |
959 | | |
960 | 4 | proto_item_append_text(agreement_item, " (AN: %d", (spt_agree_data & 0x03)); |
961 | | |
962 | 4 | proto_tree_add_bitmask_list_value(agreement_tree, tvb, spt_offset, 1, agreements, spt_agree_data); |
963 | | |
964 | 4 | proto_item_append_text(agreement_item, ", DAN: %d)", ((spt_agree_data & 0x0C) >> 2)); |
965 | 4 | spt_offset += 2; |
966 | | |
967 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_agreement_digest_format_id, tvb, spt_offset, 1, ENC_NA); |
968 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_agreement_digest_format_capabilities, tvb, spt_offset, 1, ENC_NA); |
969 | 4 | spt_offset += 1; |
970 | | |
971 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_agreement_digest_convention_id, tvb, spt_offset, 1, ENC_NA); |
972 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_agreement_digest_convention_capabilities, tvb, spt_offset, 1, ENC_NA); |
973 | 4 | spt_offset += 1; |
974 | | |
975 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_agreement_digest_edge_count, tvb, spt_offset, 2, ENC_BIG_ENDIAN); |
976 | 4 | spt_offset += 10; |
977 | | |
978 | 4 | proto_tree_add_item(agreement_tree, hf_bpdu_spt_agreement_digest, |
979 | 4 | tvb, spt_offset, 20, ENC_NA); |
980 | | /*spt_offset += 20;*/ |
981 | | |
982 | 4 | if (protocol_version_identifier == 4) { |
983 | 0 | set_actual_length(tvb, (bpdu_version_4_length + version_4_length + 2)); |
984 | 0 | } |
985 | 4 | } |
986 | 4 | } |
987 | 6 | } else { /* It is RSTP BPDU and may still be Rapid PVST+ */ |
988 | 6 | if (is_bpdu_pvst) |
989 | 0 | dissect_bpdu_pvst_tlv(pinfo, bpdu_tree, tvb); |
990 | 6 | } |
991 | 18 | } |
992 | | |
993 | | static int |
994 | | dissect_bpdu_cisco(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
995 | 0 | { |
996 | 0 | dissect_bpdu(tvb, pinfo, tree, true); |
997 | 0 | return tvb_captured_length(tvb); |
998 | 0 | } |
999 | | |
1000 | | static int |
1001 | | dissect_bpdu_generic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1002 | 31 | { |
1003 | 31 | dissect_bpdu(tvb, pinfo, tree, false); |
1004 | 31 | return tvb_captured_length(tvb); |
1005 | 31 | } |
1006 | | |
1007 | | void |
1008 | | proto_register_bpdu(void) |
1009 | 15 | { |
1010 | | |
1011 | 15 | static hf_register_info hf[] = { |
1012 | 15 | { &hf_bpdu_proto_id, |
1013 | 15 | { "Protocol Identifier", "stp.protocol", |
1014 | 15 | FT_UINT16, BASE_HEX, VALS(protocol_id_vals), 0x0, |
1015 | 15 | NULL, HFILL }}, |
1016 | 15 | { &hf_bpdu_version_id, |
1017 | 15 | { "Protocol Version Identifier", "stp.version", |
1018 | 15 | FT_UINT8, BASE_DEC, VALS(version_id_vals), 0x0, |
1019 | 15 | NULL, HFILL }}, |
1020 | 15 | { &hf_bpdu_type, |
1021 | 15 | { "BPDU Type", "stp.type", |
1022 | 15 | FT_UINT8, BASE_HEX, VALS(bpdu_type_vals), 0x0, |
1023 | 15 | NULL, HFILL }}, |
1024 | 15 | { &hf_bpdu_flags, |
1025 | 15 | { "BPDU flags", "stp.flags", |
1026 | 15 | FT_UINT8, BASE_HEX, NULL, 0x0, |
1027 | 15 | NULL, HFILL }}, |
1028 | 15 | { &hf_bpdu_flags_tcack, |
1029 | 15 | { "Topology Change Acknowledgment", "stp.flags.tcack", |
1030 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_TCACK, |
1031 | 15 | NULL, HFILL }}, |
1032 | 15 | { &hf_bpdu_flags_agreement, |
1033 | 15 | { "Agreement", "stp.flags.agreement", |
1034 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_AGREEMENT, |
1035 | 15 | NULL, HFILL }}, |
1036 | 15 | { &hf_bpdu_flags_forwarding, |
1037 | 15 | { "Forwarding", "stp.flags.forwarding", |
1038 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_FORWARDING, |
1039 | 15 | NULL, HFILL }}, |
1040 | 15 | { &hf_bpdu_flags_learning, |
1041 | 15 | { "Learning", "stp.flags.learning", |
1042 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_LEARNING, |
1043 | 15 | NULL, HFILL }}, |
1044 | 15 | { &hf_bpdu_flags_port_role, |
1045 | 15 | { "Port Role", "stp.flags.port_role", |
1046 | 15 | FT_UINT8, BASE_DEC, VALS(role_vals), BPDU_FLAGS_PORT_ROLE_MASK, |
1047 | 15 | NULL, HFILL }}, |
1048 | 15 | { &hf_bpdu_flags_proposal, |
1049 | 15 | { "Proposal", "stp.flags.proposal", |
1050 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_PROPOSAL, |
1051 | 15 | NULL, HFILL }}, |
1052 | 15 | { &hf_bpdu_flags_tc, |
1053 | 15 | { "Topology Change", "stp.flags.tc", |
1054 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), BPDU_FLAGS_TC, |
1055 | 15 | NULL, HFILL }}, |
1056 | 15 | { &hf_bpdu_root_prio, |
1057 | 15 | { "Root Bridge Priority", "stp.root.prio", |
1058 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1059 | 15 | NULL, HFILL }}, |
1060 | 15 | { &hf_bpdu_root_sys_id_ext, |
1061 | 15 | { "Root Bridge System ID Extension", "stp.root.ext", |
1062 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1063 | 15 | NULL, HFILL }}, |
1064 | 15 | { &hf_bpdu_root_mac, |
1065 | 15 | { "Root Bridge System ID", "stp.root.hw", |
1066 | 15 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1067 | 15 | NULL, HFILL }}, |
1068 | 15 | { &hf_bpdu_root_cost, |
1069 | 15 | { "Root Path Cost", "stp.root.cost", |
1070 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1071 | 15 | NULL, HFILL }}, |
1072 | 15 | { &hf_bpdu_bridge_prio, |
1073 | 15 | { "Bridge Priority", "stp.bridge.prio", |
1074 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1075 | 15 | NULL, HFILL }}, |
1076 | 15 | { &hf_bpdu_bridge_sys_id_ext, |
1077 | 15 | { "Bridge System ID Extension", "stp.bridge.ext", |
1078 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1079 | 15 | NULL, HFILL }}, |
1080 | 15 | { &hf_bpdu_bridge_mac, |
1081 | 15 | { "Bridge System ID", "stp.bridge.hw", |
1082 | 15 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1083 | 15 | NULL, HFILL }}, |
1084 | 15 | { &hf_bpdu_port_id, |
1085 | 15 | { "Port identifier", "stp.port", |
1086 | 15 | FT_UINT16, BASE_HEX, NULL, 0x0, |
1087 | 15 | NULL, HFILL }}, |
1088 | 15 | { &hf_bpdu_msg_age, |
1089 | 15 | { "Message Age", "stp.msg_age", |
1090 | 15 | FT_DOUBLE, BASE_NONE, NULL, 0x0, |
1091 | 15 | NULL, HFILL }}, |
1092 | 15 | { &hf_bpdu_max_age, |
1093 | 15 | { "Max Age", "stp.max_age", |
1094 | 15 | FT_DOUBLE, BASE_NONE, NULL, 0x0, |
1095 | 15 | NULL, HFILL }}, |
1096 | 15 | { &hf_bpdu_hello_time, |
1097 | 15 | { "Hello Time", "stp.hello", |
1098 | 15 | FT_DOUBLE, BASE_NONE, NULL, 0x0, |
1099 | 15 | NULL, HFILL }}, |
1100 | 15 | { &hf_bpdu_forward_delay, |
1101 | 15 | { "Forward Delay", "stp.forward", |
1102 | 15 | FT_DOUBLE, BASE_NONE, NULL, 0x0, |
1103 | 15 | NULL, HFILL }}, |
1104 | 15 | { &hf_bpdu_version_1_length, |
1105 | 15 | { "Version 1 Length", "stp.version_1_length", |
1106 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1107 | 15 | NULL, HFILL }}, |
1108 | 15 | { &hf_bpdu_pvst_tlvtype, |
1109 | 15 | { "Type", "stp.pvst.tlvtype", |
1110 | 15 | FT_UINT16, BASE_HEX, VALS(bpdu_pvst_tlv_vals), 0x0, |
1111 | 15 | NULL, HFILL }}, |
1112 | 15 | { &hf_bpdu_pvst_tlvlength, |
1113 | 15 | { "Length", "stp.pvst.tlvlen", |
1114 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1115 | 15 | NULL, HFILL }}, |
1116 | 15 | { &hf_bpdu_pvst_tlv_origvlan, |
1117 | 15 | { "Originating VLAN", "stp.pvst.origvlan", |
1118 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1119 | 15 | NULL, HFILL }}, |
1120 | 15 | { &hf_bpdu_pvst_tlvvalue, |
1121 | 15 | { "Value", "stp.pvst.tlvval", |
1122 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1123 | 15 | NULL, HFILL }}, |
1124 | 15 | { &hf_bpdu_version_3_length, |
1125 | 15 | { "Version 3 Length", "mstp.version_3_length", |
1126 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1127 | 15 | NULL, HFILL }}, |
1128 | 15 | { &hf_bpdu_mst_config_format_selector, |
1129 | 15 | { "MST Config ID format selector", "mstp.config_format_selector", |
1130 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1131 | 15 | NULL, HFILL }}, |
1132 | 15 | { &hf_bpdu_mst_config_name, |
1133 | 15 | { "MST Config name", "mstp.config_name", |
1134 | 15 | FT_STRINGZPAD, BASE_NONE, NULL, 0x0, |
1135 | 15 | NULL, HFILL }}, |
1136 | 15 | { &hf_bpdu_mst_config_revision_level, |
1137 | 15 | { "MST Config revision", "mstp.config_revision_level", |
1138 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1139 | 15 | NULL, HFILL }}, |
1140 | 15 | { &hf_bpdu_mst_config_digest, |
1141 | 15 | { "MST Config digest", "mstp.config_digest", |
1142 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1143 | 15 | NULL, HFILL }}, |
1144 | 15 | { &hf_bpdu_cist_internal_root_path_cost, |
1145 | 15 | { "CIST Internal Root Path Cost", "mstp.cist_internal_root_path_cost", |
1146 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1147 | 15 | NULL, HFILL }}, |
1148 | 15 | { &hf_bpdu_cist_bridge_prio, |
1149 | 15 | { "CIST Bridge Priority", "mstp.cist_bridge.prio", |
1150 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1151 | 15 | NULL, HFILL }}, |
1152 | 15 | { &hf_bpdu_cist_bridge_sys_id_ext, |
1153 | 15 | { "CIST Bridge Identifier System ID Extension", "mstp.cist_bridge.ext", |
1154 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1155 | 15 | NULL, HFILL }}, |
1156 | 15 | { &hf_bpdu_cist_bridge_mac, |
1157 | 15 | { "CIST Bridge Identifier System ID", "mstp.cist_bridge.hw", |
1158 | 15 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1159 | 15 | NULL, HFILL }}, |
1160 | 15 | { &hf_bpdu_cist_remaining_hops, |
1161 | 15 | { "CIST Remaining hops", "mstp.cist_remaining_hops", |
1162 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1163 | 15 | NULL, HFILL }}, |
1164 | 15 | { &hf_bpdu_msti_flags, |
1165 | 15 | { "MSTI flags", "mstp.msti.flags", |
1166 | 15 | FT_UINT8, BASE_HEX, NULL, 0x0, |
1167 | 15 | NULL, HFILL }}, |
1168 | 15 | { &hf_bpdu_mst_priority, |
1169 | 15 | { "Priority", "mstp.msti.priority", |
1170 | 15 | FT_UINT8, BASE_HEX, NULL, 0xF0, |
1171 | 15 | NULL, HFILL }}, |
1172 | 15 | { &hf_bpdu_msti_id_FFF, |
1173 | 15 | { "MSTID", "mstp.msti.msti_id", |
1174 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0FFF, |
1175 | 15 | NULL, HFILL }}, |
1176 | 15 | { &hf_bpdu_msti_id, |
1177 | 15 | { "MSTID", "mstp.msti.msti_id", |
1178 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1179 | 15 | NULL, HFILL }}, |
1180 | 15 | { &hf_bpdu_msti_regional_root_id, |
1181 | 15 | { "MSTI Regional Root Identifier", "mstp.msti.regional_root_id", |
1182 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1183 | 15 | NULL, HFILL }}, |
1184 | 15 | { &hf_bpdu_msti_regional_root_mac, |
1185 | 15 | { "Regional Root", "mstp.msti.root.hw", |
1186 | 15 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1187 | 15 | NULL, HFILL }}, |
1188 | 15 | { &hf_bpdu_msti_internal_root_path_cost, |
1189 | 15 | { "Internal root path cost", "mstp.msti.root_cost", |
1190 | 15 | FT_UINT32, BASE_DEC, NULL, 0x0, |
1191 | 15 | NULL, HFILL }}, |
1192 | 15 | { &hf_bpdu_msti_bridge_id, |
1193 | 15 | { "MSTI Bridge Identifier", "mstp.msti.bridge_id", |
1194 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0FFF, |
1195 | 15 | NULL, HFILL }}, |
1196 | 15 | { &hf_bpdu_msti_bridge_id_priority, |
1197 | 15 | { "MSTI Bridge Priority", "mstp.msti.bridge_id_priority", |
1198 | 15 | FT_UINT16, BASE_DEC, NULL, 0xF000, |
1199 | 15 | NULL, HFILL }}, |
1200 | 15 | { &hf_bpdu_msti_bridge_id_mac, |
1201 | 15 | { "MSTI Bridge MAC", "mstp.msti.bridge_id_mac", |
1202 | 15 | FT_ETHER, BASE_NONE, NULL, 0x0, |
1203 | 15 | NULL, HFILL }}, |
1204 | 15 | { &hf_bpdu_msti_bridge_identifier_priority, |
1205 | 15 | { "Bridge Identifier Priority", "mstp.msti.bridge_priority", |
1206 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1207 | 15 | NULL, HFILL }}, |
1208 | 15 | { &hf_bpdu_msti_port_identifier_priority, |
1209 | 15 | { "Port identifier priority", "mstp.msti.port_priority", |
1210 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1211 | 15 | NULL, HFILL }}, |
1212 | 15 | { &hf_bpdu_msti_port_id, |
1213 | 15 | { "Port identifier", "mstp.msti.port", |
1214 | 15 | FT_UINT16, BASE_HEX, NULL, 0x0, |
1215 | 15 | NULL, HFILL }}, |
1216 | 15 | { &hf_bpdu_msti_remaining_hops, |
1217 | 15 | { "Remaining hops", "mstp.msti.remaining_hops", |
1218 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1219 | 15 | NULL, HFILL }}, |
1220 | 15 | { &hf_bpdu_version_4_length, |
1221 | 15 | { "Version 4 Length", "mstp.version_4_length", |
1222 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1223 | 15 | NULL, HFILL }}, |
1224 | 15 | { &hf_bpdu_spt_config_format_selector, |
1225 | 15 | { "SPT Config ID format selector", "mstp.config_format_selector", |
1226 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0, |
1227 | 15 | NULL, HFILL }}, |
1228 | 15 | { &hf_bpdu_spt_config_name, |
1229 | 15 | {"SPT Config name", "mstp.config_name", |
1230 | 15 | FT_STRINGZPAD, BASE_NONE, NULL, 0x0, |
1231 | 15 | NULL, HFILL } }, |
1232 | 15 | { &hf_bpdu_spt_config_revision_level, |
1233 | 15 | { "SPT Config revision", "mstp.config_revision_level", |
1234 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1235 | 15 | NULL, HFILL } }, |
1236 | 15 | { &hf_bpdu_spt_config_digest, |
1237 | 15 | { "SPT Config digest", "mstp.config_digest", |
1238 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1239 | 15 | NULL, HFILL } }, |
1240 | 15 | { &hf_bpdu_flags_agree_num, |
1241 | 15 | { "Agreement Number", "mstp.agree_flags.agreement_num", |
1242 | 15 | FT_UINT8, BASE_DEC, NULL, 0x03, |
1243 | 15 | NULL, HFILL } }, |
1244 | 15 | { &hf_bpdu_flags_dagree_num, |
1245 | 15 | { "Disagreement Number", "mstp.agree_flags.dagreement_num", |
1246 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0C, |
1247 | 15 | NULL, HFILL } }, |
1248 | 15 | { &hf_bpdu_flags_agree_valid, |
1249 | 15 | { "Agreement Valid Flag", "mstp.agree_flags.agreement_valid", |
1250 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10, |
1251 | 15 | NULL, HFILL } }, |
1252 | 15 | { &hf_bpdu_flags_restricted_role, |
1253 | 15 | { "Restricted Role", "mstp.agree_flags.rest_role", |
1254 | 15 | FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20, |
1255 | 15 | NULL, HFILL } }, |
1256 | 15 | { &hf_bpdu_spt_agreement_digest, |
1257 | 15 | { "Agreement Digest", "mstp.agreement_digest", |
1258 | 15 | FT_BYTES, BASE_NONE, NULL, 0x0, |
1259 | 15 | NULL, HFILL } }, |
1260 | 15 | { &hf_bpdu_agreement_digest_format_id, |
1261 | 15 | { "Agreement Digest Format Id", "bpdu.agreement_digest_format_id", |
1262 | 15 | FT_UINT8, BASE_DEC, NULL, 0xF0, |
1263 | 15 | NULL, HFILL }}, |
1264 | 15 | { &hf_bpdu_agreement_digest_format_capabilities, |
1265 | 15 | { "Agreement Digest Format Capabilities", "bpdu.agreement_digest_format_capabilities", |
1266 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0F, |
1267 | 15 | NULL, HFILL }}, |
1268 | 15 | { &hf_bpdu_agreement_digest_convention_id, |
1269 | 15 | { "Agreement Digest Convention Id", "bpdu.agreement_digest_convention_id", |
1270 | 15 | FT_UINT8, BASE_DEC, NULL, 0xF0, |
1271 | 15 | NULL, HFILL }}, |
1272 | 15 | { &hf_bpdu_agreement_digest_convention_capabilities, |
1273 | 15 | { "Agreement Digest Convention Capabilities", "bpdu.agreement_digest_convention_capabilities", |
1274 | 15 | FT_UINT8, BASE_DEC, NULL, 0x0F, |
1275 | 15 | NULL, HFILL }}, |
1276 | 15 | { &hf_bpdu_agreement_digest_edge_count, |
1277 | 15 | { "Agreement Digest Edge Count", "bpdu.agreement_digest_edge_count", |
1278 | 15 | FT_UINT16, BASE_DEC, NULL, 0x0, |
1279 | 15 | NULL, HFILL }}, |
1280 | 15 | }; |
1281 | 15 | static int *ett[] = { |
1282 | 15 | &ett_bpdu, |
1283 | 15 | &ett_bpdu_flags, |
1284 | 15 | &ett_root_id, |
1285 | 15 | &ett_bridge_id, |
1286 | 15 | &ett_mstp, |
1287 | 15 | &ett_msti, |
1288 | 15 | &ett_cist_bridge_id, |
1289 | 15 | &ett_spt, |
1290 | 15 | &ett_aux_mcid, |
1291 | 15 | &ett_agreement, |
1292 | 15 | &ett_bpdu_pvst_tlv |
1293 | 15 | }; |
1294 | | |
1295 | 15 | static ei_register_info ei[] = { |
1296 | 15 | { &ei_pvst_tlv_length_invalid, |
1297 | 15 | { "stp.pvst.tlvlen.invalid", PI_MALFORMED, PI_ERROR, |
1298 | 15 | "Indicated length is not valid for this record type", EXPFILL }}, |
1299 | | |
1300 | 15 | { &ei_pvst_tlv_origvlan_missing, |
1301 | 15 | { "stp.pvst.origvlan.missing", PI_MALFORMED, PI_ERROR, |
1302 | 15 | "Originating (PVID) VLAN TLV is missing or corrupt", EXPFILL }}, |
1303 | | |
1304 | 15 | { &ei_pvst_tlv_truncated, |
1305 | 15 | { "stp.pvst.tlv.truncated", PI_MALFORMED, PI_ERROR, |
1306 | 15 | "TLV record is truncated prematurely", EXPFILL }}, |
1307 | | |
1308 | 15 | { &ei_pvst_tlv_unknown, |
1309 | 15 | { "stp.pvst.tlv.unknown", PI_UNDECODED, PI_COMMENT, |
1310 | 15 | "TLV type is unknown", EXPFILL }}, |
1311 | | |
1312 | 15 | { &ei_bpdu_version_support, |
1313 | 15 | { "bpdu.version_support", PI_PROTOCOL, PI_WARN, |
1314 | 15 | "This version of Wireshark only knows about versions 0, 2, 3 & 4", EXPFILL }}, |
1315 | | |
1316 | 15 | { &ei_bpdu_type, |
1317 | 15 | { "stp.type.unknown", PI_PROTOCOL, PI_WARN, |
1318 | 15 | "Unknown BPDU type data", EXPFILL }}, |
1319 | 15 | }; |
1320 | | |
1321 | 15 | module_t *bpdu_module; |
1322 | 15 | expert_module_t *expert_bpdu; |
1323 | | |
1324 | 15 | proto_bpdu = proto_register_protocol("Spanning Tree Protocol", "STP", "stp"); |
1325 | 15 | proto_register_field_array(proto_bpdu, hf, array_length(hf)); |
1326 | 15 | proto_register_subtree_array(ett, array_length(ett)); |
1327 | | |
1328 | 15 | bpdu_handle = register_dissector("bpdu", dissect_bpdu_generic, proto_bpdu); |
1329 | 15 | bpdu_cisco_handle = register_dissector("bpdu_cisco", dissect_bpdu_cisco, proto_bpdu); |
1330 | | |
1331 | 15 | expert_bpdu = expert_register_protocol(proto_bpdu); |
1332 | 15 | expert_register_field_array(expert_bpdu, ei, array_length(ei)); |
1333 | | |
1334 | 15 | bpdu_module = prefs_register_protocol(proto_bpdu, NULL); |
1335 | 15 | prefs_register_bool_preference(bpdu_module, "use_system_id_extension", |
1336 | 15 | "Use 802.1t System ID Extensions", |
1337 | 15 | "Whether the BPDU dissector should use 802.1t System ID Extensions when dissecting the Bridge Identifier", |
1338 | 15 | &bpdu_use_system_id_extensions); |
1339 | 15 | } |
1340 | | |
1341 | | void |
1342 | | proto_reg_handoff_bpdu(void) |
1343 | 15 | { |
1344 | | /* |
1345 | | * Get handle for the GVRP dissector. |
1346 | | */ |
1347 | 15 | gvrp_handle = find_dissector("gvrp"); |
1348 | | |
1349 | | /* |
1350 | | * Get handle for the GMRP dissector. |
1351 | | */ |
1352 | 15 | gmrp_handle = find_dissector_add_dependency("gmrp", proto_bpdu); |
1353 | | |
1354 | 15 | dissector_add_uint("llc.dsap", SAP_BPDU, bpdu_handle); |
1355 | 15 | dissector_add_uint("chdlc.protocol", CHDLCTYPE_BPDU, bpdu_handle); |
1356 | 15 | dissector_add_uint("ethertype", ETHERTYPE_STP, bpdu_handle); |
1357 | 15 | dissector_add_uint("llc.cisco_pid", CISCO_PID_RLQ_REQ, bpdu_handle); /* Cisco's RLQ is just plain STP */ |
1358 | 15 | dissector_add_uint("llc.cisco_pid", CISCO_PID_RLQ_RESP, bpdu_handle); /* Cisco's RLQ is just plain STP */ |
1359 | 15 | dissector_add_uint("llc.cisco_pid", CISCO_PID_VLAN_BRIDGE, bpdu_handle); /* Cisco's VLAN-bridge STP is just plain STP */ |
1360 | 15 | dissector_add_uint("llc.cisco_pid", CISCO_PID_PVSTPP, bpdu_cisco_handle); /* Handle Cisco's (R)PVST+ TLV extensions */ |
1361 | 15 | } |
1362 | | |
1363 | | /* |
1364 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1365 | | * |
1366 | | * Local Variables: |
1367 | | * c-basic-offset: 2 |
1368 | | * tab-width: 8 |
1369 | | * indent-tabs-mode: nil |
1370 | | * End: |
1371 | | * |
1372 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
1373 | | * :indentSize=2:tabSize=8:noTabs=true: |
1374 | | */ |