2 * Copyright (c) 2000 Lennert Buytenhek
4 * This software may be distributed either under the terms of the
5 * BSD-style license that accompanies tcpdump or the GNU General
8 * Format and print IEEE 802.1d spanning tree protocol packets.
9 * Contributed by Lennert Buytenhek <buytenh@gnu.org>
13 static const char rcsid
[] _U_
=
14 "@(#) $Header: /tcpdump/master/tcpdump/print-stp.c,v 1.13.2.2 2007-03-06 15:07:05 hannes Exp $";
21 #include <tcpdump-stdinc.h>
27 #include "interface.h"
28 #include "addrtoname.h"
31 #define RSTP_EXTRACT_PORT_ROLE(x) (((x)&0x0C)>>2)
32 /* STP timers are expressed in multiples of 1/256th second */
33 #define STP_TIME_BASE 256
36 u_int8_t protocol_id
[2];
37 u_int8_t protocol_version
;
41 u_int8_t root_path_cost
[4];
42 u_int8_t bridge_id
[8];
44 u_int8_t message_age
[2];
46 u_int8_t hello_time
[2];
47 u_int8_t forward_delay
[2];
51 #define STP_PROTO_REGULAR 0x00
52 #define STP_PROTO_RAPID 0x02
54 struct tok stp_proto_values
[] = {
55 { STP_PROTO_REGULAR
, "802.1d" },
56 { STP_PROTO_RAPID
, "802.1w" },
60 #define STP_BPDU_TYPE_CONFIG 0x00
61 #define STP_BPDU_TYPE_RSTP 0x02
62 #define STP_BPDU_TYPE_TOPO_CHANGE 0x80
64 struct tok stp_bpdu_flag_values
[] = {
65 { 0x01, "Topology change" },
69 { 0x40, "Agreement" },
70 { 0x80, "Topology change ACK" },
74 struct tok stp_bpdu_type_values
[] = {
75 { STP_BPDU_TYPE_CONFIG
, "Config" },
76 { STP_BPDU_TYPE_RSTP
, "Rapid SPT" },
77 { STP_BPDU_TYPE_TOPO_CHANGE
, "Topology Change" },
81 struct tok rstp_obj_port_role_values
[] = {
83 { 0x01, "Alternate" },
85 { 0x03, "Designated" },
90 stp_print_bridge_id(const u_char
*p
)
92 static char bridge_id_str
[sizeof("pppp.aa:bb:cc:dd:ee:ff")];
94 snprintf(bridge_id_str
, sizeof(bridge_id_str
),
95 "%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
96 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7]);
102 stp_print_config_bpdu(const struct stp_bpdu_
*stp_bpdu
, u_int length
)
104 printf(", Flags [%s]",
105 bittok2str(stp_bpdu_flag_values
, "none", stp_bpdu
->flags
));
107 printf(", bridge-id %s.%04x, length %u",
108 stp_print_bridge_id((const u_char
*)&stp_bpdu
->bridge_id
),
109 EXTRACT_16BITS(&stp_bpdu
->port_id
), length
);
111 /* in non-verbose mode just print the bridge-id */
116 printf("\n\tmessage-age %.2fs, max-age %.2fs"
117 ", hello-time %.2fs, forwarding-delay %.2fs",
118 (float)EXTRACT_16BITS(&stp_bpdu
->message_age
) / STP_TIME_BASE
,
119 (float)EXTRACT_16BITS(&stp_bpdu
->max_age
) / STP_TIME_BASE
,
120 (float)EXTRACT_16BITS(&stp_bpdu
->hello_time
) / STP_TIME_BASE
,
121 (float)EXTRACT_16BITS(&stp_bpdu
->forward_delay
) / STP_TIME_BASE
);
123 printf("\n\troot-id %s, root-pathcost %u",
124 stp_print_bridge_id((const u_char
*)&stp_bpdu
->root_id
),
125 EXTRACT_32BITS(&stp_bpdu
->root_path_cost
) / STP_TIME_BASE
);
127 /* Port role is only valid for 802.1w */
128 if (stp_bpdu
->protocol_version
== STP_PROTO_RAPID
) {
129 printf(", port-role %s",
130 tok2str(rstp_obj_port_role_values
, "Unknown",
131 RSTP_EXTRACT_PORT_ROLE(stp_bpdu
->flags
)));
136 * Print 802.1d / 802.1w packets.
139 stp_print(const u_char
*p
, u_int length
)
141 const struct stp_bpdu_
*stp_bpdu
;
143 stp_bpdu
= (struct stp_bpdu_
*)p
;
145 /* Minimum SPT Frame size. */
149 if (EXTRACT_16BITS(&stp_bpdu
->protocol_id
)) {
150 printf("unknown STP version, length %u", length
);
154 printf("STP %s", tok2str(stp_proto_values
, "Unknown STP protocol (0x%02x)",
155 stp_bpdu
->protocol_version
));
157 switch (stp_bpdu
->protocol_version
) {
158 case STP_PROTO_REGULAR
:
159 case STP_PROTO_RAPID
:
165 printf(", %s", tok2str(stp_bpdu_type_values
, "Unknown BPDU Type (0x%02x)",
166 stp_bpdu
->bpdu_type
));
168 switch (stp_bpdu
->bpdu_type
) {
169 case STP_BPDU_TYPE_CONFIG
:
170 if (length
< sizeof(struct stp_bpdu_
) - 1) {
173 stp_print_config_bpdu(stp_bpdu
, length
);
176 case STP_BPDU_TYPE_RSTP
:
177 if (length
< sizeof(struct stp_bpdu_
)) {
180 stp_print_config_bpdu(stp_bpdu
, length
);
183 case STP_BPDU_TYPE_TOPO_CHANGE
:
184 /* always empty message - just break out */
193 printf("[|stp %d]", length
);
198 * c-style: whitesmith