2 * Routines for DEC BPDU (DEC Spanning Tree Protocol) disassembly
6 * Copyright 2001 Paul Ionescu <paul@acorp.ro>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/addr_resolv.h>
32 #include <epan/etypes.h>
33 #include <epan/ppptypes.h>
35 /* Offsets of fields within a BPDU */
37 #define BPDU_DEC_CODE 0
39 #define BPDU_VERSION 2
41 #define BPDU_ROOT_PRI 4
42 #define BPDU_ROOT_MAC 6
43 #define BPDU_ROOT_PATH_COST 12
44 #define BPDU_BRIDGE_PRI 14
45 #define BPDU_BRIDGE_MAC 16
46 #define BPDU_PORT_IDENTIFIER 22
47 #define BPDU_MESSAGE_AGE 23
48 #define BPDU_HELLO_TIME 24
49 #define BPDU_MAX_AGE 25
50 #define BPDU_FORWARD_DELAY 26
52 #define DEC_BPDU_SIZE 27
56 #define BPDU_FLAGS_SHORT_TIMERS 0x80
57 #define BPDU_FLAGS_TCACK 0x02
58 #define BPDU_FLAGS_TC 0x01
60 void proto_register_dec_bpdu(void);
61 void proto_reg_handoff_dec_bpdu(void);
63 static int proto_dec_bpdu
= -1;
64 static int hf_dec_bpdu_proto_id
= -1;
65 static int hf_dec_bpdu_type
= -1;
66 static int hf_dec_bpdu_version_id
= -1;
67 static int hf_dec_bpdu_flags
= -1;
68 static int hf_dec_bpdu_flags_short_timers
= -1;
69 static int hf_dec_bpdu_flags_tcack
= -1;
70 static int hf_dec_bpdu_flags_tc
= -1;
71 static int hf_dec_bpdu_root_pri
= -1;
72 static int hf_dec_bpdu_root_mac
= -1;
73 static int hf_dec_bpdu_root_cost
= -1;
74 static int hf_dec_bpdu_bridge_pri
= -1;
75 static int hf_dec_bpdu_bridge_mac
= -1;
76 static int hf_dec_bpdu_port_id
= -1;
77 static int hf_dec_bpdu_msg_age
= -1;
78 static int hf_dec_bpdu_hello_time
= -1;
79 static int hf_dec_bpdu_max_age
= -1;
80 static int hf_dec_bpdu_forward_delay
= -1;
82 static gint ett_dec_bpdu
= -1;
83 static gint ett_dec_bpdu_flags
= -1;
85 static const value_string protocol_id_vals
[] = {
86 { 0xe1, "DEC Spanning Tree Protocol" },
90 #define BPDU_TYPE_TOPOLOGY_CHANGE 2
91 #define BPDU_TYPE_HELLO 25
93 static const value_string bpdu_type_vals
[] = {
94 { BPDU_TYPE_TOPOLOGY_CHANGE
, "Topology Change Notification" },
95 { BPDU_TYPE_HELLO
, "Hello Packet" },
99 static const char initial_sep
[] = " (";
100 static const char cont_sep
[] = ", ";
102 #define APPEND_BOOLEAN_FLAG(flag, item, string) \
105 proto_item_append_text(item, string, sep); \
110 dissect_dec_bpdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
114 proto_tree
*bpdu_tree
;
115 proto_tree
*flags_tree
;
119 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DEC_STP");
120 col_clear(pinfo
->cinfo
, COL_INFO
);
122 bpdu_type
= tvb_get_guint8(tvb
, BPDU_TYPE
);
124 col_add_str(pinfo
->cinfo
, COL_INFO
,
125 val_to_str(bpdu_type
, bpdu_type_vals
,
126 "Unknown BPDU type (%u)"));
128 set_actual_length(tvb
, DEC_BPDU_SIZE
);
131 ti
= proto_tree_add_item(tree
, proto_dec_bpdu
, tvb
, 0, DEC_BPDU_SIZE
,
133 bpdu_tree
= proto_item_add_subtree(ti
, ett_dec_bpdu
);
135 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_proto_id
, tvb
,
136 BPDU_DEC_CODE
, 1, ENC_BIG_ENDIAN
);
138 proto_tree_add_uint(bpdu_tree
, hf_dec_bpdu_type
, tvb
,
139 BPDU_TYPE
, 1, bpdu_type
);
141 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_version_id
, tvb
,
142 BPDU_VERSION
, 1, ENC_BIG_ENDIAN
);
144 flags
= tvb_get_guint8(tvb
, BPDU_FLAGS
);
145 ti
= proto_tree_add_uint(bpdu_tree
, hf_dec_bpdu_flags
, tvb
,
146 BPDU_FLAGS
, 1, flags
);
147 flags_tree
= proto_item_add_subtree(ti
, ett_dec_bpdu_flags
);
149 APPEND_BOOLEAN_FLAG(flags
& BPDU_FLAGS_SHORT_TIMERS
, ti
,
150 "%sUse short timers");
151 proto_tree_add_boolean(flags_tree
, hf_dec_bpdu_flags_short_timers
, tvb
,
152 BPDU_FLAGS
, 1, flags
);
153 APPEND_BOOLEAN_FLAG(flags
& BPDU_FLAGS_TCACK
, ti
,
154 "%sTopology Change Acknowledgment");
155 proto_tree_add_boolean(flags_tree
, hf_dec_bpdu_flags_tcack
, tvb
,
156 BPDU_FLAGS
, 1, flags
);
157 APPEND_BOOLEAN_FLAG(flags
& BPDU_FLAGS_TC
, ti
,
158 "%sTopology Change");
159 proto_tree_add_boolean(flags_tree
, hf_dec_bpdu_flags_tc
, tvb
,
160 BPDU_FLAGS
, 1, flags
);
161 if (sep
!= initial_sep
) {
162 /* We put something in; put in the terminating ")" */
163 proto_item_append_text(ti
, ")");
166 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_root_pri
, tvb
,
167 BPDU_ROOT_PRI
, 2, ENC_BIG_ENDIAN
);
168 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_root_mac
, tvb
,
169 BPDU_ROOT_MAC
, 6, ENC_NA
);
170 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_root_cost
, tvb
,
171 BPDU_ROOT_PATH_COST
, 2, ENC_BIG_ENDIAN
);
172 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_bridge_pri
, tvb
,
173 BPDU_BRIDGE_PRI
, 2, ENC_BIG_ENDIAN
);
174 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_bridge_mac
, tvb
,
175 BPDU_BRIDGE_MAC
, 6, ENC_NA
);
176 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_port_id
, tvb
,
177 BPDU_PORT_IDENTIFIER
, 1, ENC_BIG_ENDIAN
);
178 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_msg_age
, tvb
,
179 BPDU_MESSAGE_AGE
, 1, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_hello_time
, tvb
,
181 BPDU_HELLO_TIME
, 1, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_max_age
, tvb
,
183 BPDU_MAX_AGE
, 1, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(bpdu_tree
, hf_dec_bpdu_forward_delay
, tvb
,
185 BPDU_FORWARD_DELAY
, 1, ENC_BIG_ENDIAN
);
191 proto_register_dec_bpdu(void)
194 static hf_register_info hf
[] = {
195 { &hf_dec_bpdu_proto_id
,
196 { "Protocol Identifier", "dec_stp.protocol",
197 FT_UINT8
, BASE_HEX
, VALS(protocol_id_vals
), 0x0,
200 { "BPDU Type", "dec_stp.type",
201 FT_UINT8
, BASE_DEC
, VALS(bpdu_type_vals
), 0x0,
203 { &hf_dec_bpdu_version_id
,
204 { "BPDU Version", "dec_stp.version",
205 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
207 { &hf_dec_bpdu_flags
,
208 { "BPDU flags", "dec_stp.flags",
209 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
211 { &hf_dec_bpdu_flags_short_timers
,
212 { "Use short timers", "dec_stp.flags.short_timers",
213 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), BPDU_FLAGS_SHORT_TIMERS
,
215 { &hf_dec_bpdu_flags_tcack
,
216 { "Topology Change Acknowledgment", "dec_stp.flags.tcack",
217 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), BPDU_FLAGS_TCACK
,
219 { &hf_dec_bpdu_flags_tc
,
220 { "Topology Change", "dec_stp.flags.tc",
221 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), BPDU_FLAGS_TC
,
223 { &hf_dec_bpdu_root_pri
,
224 { "Root Priority", "dec_stp.root.pri",
225 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
227 { &hf_dec_bpdu_root_mac
,
228 { "Root MAC", "dec_stp.root.mac",
229 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
231 { &hf_dec_bpdu_root_cost
,
232 { "Root Path Cost", "dec_stp.root.cost",
233 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
235 { &hf_dec_bpdu_bridge_pri
,
236 { "Bridge Priority", "dec_stp.bridge.pri",
237 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
239 { &hf_dec_bpdu_bridge_mac
,
240 { "Bridge MAC", "dec_stp.bridge.mac",
241 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
243 { &hf_dec_bpdu_port_id
,
244 { "Port identifier", "dec_stp.port",
245 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
247 { &hf_dec_bpdu_msg_age
,
248 { "Message Age", "dec_stp.msg_age",
249 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
251 { &hf_dec_bpdu_hello_time
,
252 { "Hello Time", "dec_stp.hello",
253 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
255 { &hf_dec_bpdu_max_age
,
256 { "Max Age", "dec_stp.max_age",
257 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
259 { &hf_dec_bpdu_forward_delay
,
260 { "Forward Delay", "dec_stp.forward",
261 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
264 static gint
*ett
[] = {
269 proto_dec_bpdu
= proto_register_protocol("DEC Spanning Tree Protocol",
270 "DEC_STP", "dec_stp");
271 proto_register_field_array(proto_dec_bpdu
, hf
, array_length(hf
));
272 proto_register_subtree_array(ett
, array_length(ett
));
276 proto_reg_handoff_dec_bpdu(void)
278 dissector_handle_t dec_bpdu_handle
;
280 dec_bpdu_handle
= create_dissector_handle(dissect_dec_bpdu
,
282 dissector_add_uint("ethertype", ETHERTYPE_DEC_LB
, dec_bpdu_handle
);
283 dissector_add_uint("chdlc.protocol", ETHERTYPE_DEC_LB
, dec_bpdu_handle
);
284 dissector_add_uint("ppp.protocol", PPP_DEC_LB
, dec_bpdu_handle
);