From Aaron Woo (via Jeff Weston): Optimized Link State Routing Protocol
[obnox/wireshark/wip.git] / packet-bpdu.c
index 8cfdf8abc037654e837fa9f8888a9edcc6b1d7c1..48db6c4502a1a04f338b8974426b720a7ca39d0e 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-bpdu.c
  * Routines for BPDU (Spanning Tree Protocol) disassembly
  *
- * $Id: packet-bpdu.c,v 1.44 2003/01/11 10:01:51 guy Exp $
+ * $Id: packet-bpdu.c,v 1.50 2004/01/08 20:05:20 guy Exp $
  *
  * Copyright 1999 Christophe Tronche <ch.tronche@computer.org>
  *
@@ -34,6 +34,7 @@
 #include <epan/packet.h>
 #include "llcsaps.h"
 #include "ppptypes.h"
+#include "chdlctypes.h"
 #include <epan/resolv.h>
 
 /* Offsets of fields within a BPDU */
@@ -70,7 +71,7 @@
 #define CONF_BPDU_SIZE         35
 #define TC_BPDU_SIZE           4
 #define RST_BPDU_SIZE          36
-#define VERSION_3_STATIC_LENGTH 64
+#define VERSION_3_STATIC_LENGTH 66
 #define        MSTI_MESSAGE_SIZE       16
 
 /* Flag bits */
@@ -338,7 +339,33 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
       case BPDU_TYPE_RST:
        if (protocol_version_identifier == 3) {
            version_3_length = tvb_get_ntohs(tvb, BPDU_VERSION_3_LENGTH);
-           set_actual_length(tvb, RST_BPDU_SIZE + 2 + version_3_length);
+           /*
+            * XXX - there appears to be an ambiguity in the 802.1s spec.
+            * In 14.6.q and Figure 14-1, the "Version 3 Length" field
+            * "is the number of octets taken by the parameters that
+            * follow in the BPDU", but item 14.4.e.3 speaks of "a
+            * Version 3 length representing an integral number, from 0
+            * to 64 inclusive, of MSTI Configuration Messages".
+            *
+            * According to mail from a member of the stds-802-1@ieee.org
+            * list, item 14.4.e.3 is just saying that the length must
+            * not have a value that implies that there's a partial
+            * MSTI message in the packet, and that it's in units of
+            * bytes, not messages.
+            *
+            * However, it appears that Cisco's C3550 software
+            * (C3550-I5Q3L2-M, Version 12.1(12c)EA1) might be sending out
+            * lengths in units of messages.
+            *
+            * So if the length is too short, we assume it's because it's
+            * in units of messages, not bytes.
+            */
+           if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+               set_actual_length(tvb, RST_BPDU_SIZE +
+                                 VERSION_3_STATIC_LENGTH +
+                                 version_3_length * MSTI_MESSAGE_SIZE);
+           } else
+               set_actual_length(tvb, RST_BPDU_SIZE + 2 + version_3_length);
        } else
            set_actual_length(tvb, RST_BPDU_SIZE);
         break;
@@ -478,9 +505,21 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
                mstp_item = proto_tree_add_uint(bpdu_tree, hf_bpdu_version_3_length, tvb,
                        BPDU_VERSION_3_LENGTH, 2, version_3_length);
+               /*
+                * XXX - see comment above about the interpretation of the
+                * "Version 3 Length" field not being clear.
+                */
+               if (version_3_length < VERSION_3_STATIC_LENGTH - 2) {
+                   proto_item_append_text(mstp_item,
+                                          " (Malformed: number of MSTI messages!!! Must be %u)",
+                                          (VERSION_3_STATIC_LENGTH - 2 + version_3_length * MSTI_MESSAGE_SIZE));
+               } else {
+                   proto_item_append_text(mstp_item,
+                                          " (Number of MSTI messages: %u)",
+                                          (version_3_length - (VERSION_3_STATIC_LENGTH - 2)) / MSTI_MESSAGE_SIZE);
+               }
                mstp_tree = proto_item_add_subtree(mstp_item, ett_mstp);
 
-
                mst_config_format_selector = tvb_get_guint8(tvb, BPDU_MST_CONFIG_FORMAT_SELECTOR);
                proto_tree_add_uint(mstp_tree, hf_bpdu_mst_config_format_selector, tvb,
                        BPDU_MST_CONFIG_FORMAT_SELECTOR, 1, mst_config_format_selector);
@@ -513,14 +552,14 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        BPDU_CIST_REMAINING_HOPS, 1, cist_remaining_hops);
 
        /* MSTI messages */
-               length = version_3_length - VERSION_3_STATIC_LENGTH;
                offset = BPDU_MSTI;
+               length = tvb_reported_length_remaining(tvb, offset);
                msti = 1;
                while (length >= MSTI_MESSAGE_SIZE) {
                    msti_regional_root_mstid = tvb_get_guint8(tvb,  offset+ MSTI_REGIONAL_ROOT);
                    msti_regional_root_priority = (msti_regional_root_mstid &0xf0) << 8;
                    msti_regional_root_mstid = ((msti_regional_root_mstid & 0x0f) << 8) +
-                               tvb_get_guint8(tvb,  offset+ MSTI_REGIONAL_ROOT+1);;
+                               tvb_get_guint8(tvb,  offset+ MSTI_REGIONAL_ROOT+1);
                    msti_regional_root_mac = tvb_get_ptr(tvb, offset+ MSTI_REGIONAL_ROOT + 2, 6);
                    msti_regional_root_mac_str = ether_to_str(msti_regional_root_mac);
 
@@ -531,23 +570,39 @@ dissect_bpdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                    msti_tree = proto_item_add_subtree(msti_item, ett_msti);
 
                    /* flags */
+                   flags = tvb_get_guint8(tvb, offset+MSTI_FLAGS);
                    flags_item = proto_tree_add_uint(msti_tree, hf_bpdu_msti_flags, tvb,
                        offset+MSTI_FLAGS, 1, flags);
+                   flags_tree = proto_item_add_subtree(flags_item, ett_bpdu_flags);
 
                    sep = initial_sep;
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TCACK, flags_item, "%sMaster");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tcack, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_AGREEMENT, flags_item, "%sAgreement");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_agreement, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_FORWARDING, flags_item, "%sForwarding");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_forwarding, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_LEARNING, flags_item, "%sLearning");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_learning, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    if (flags_item) {
                        guint8 port_role;
                        port_role = (flags & BPDU_FLAGS_PORT_ROLE_MASK) >> BPDU_FLAGS_PORT_ROLE_SHIFT;
                        proto_item_append_text(flags_item, "%sPort Role: %s", sep,
                                       val_to_str(port_role, role_vals, "Unknown (%u)"));
                    }
+                   proto_tree_add_uint(flags_tree, hf_bpdu_flags_port_role, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    sep = cont_sep;
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_PROPOSAL, flags_item, "%sProposal");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_proposal, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    APPEND_BOOLEAN_FLAG(flags & BPDU_FLAGS_TC, flags_item, "%sTopology Change");
+                   proto_tree_add_boolean(flags_tree, hf_bpdu_flags_tc, tvb,
+                       offset+MSTI_FLAGS, 1, flags);
                    if (sep != initial_sep) {         /* We put something in; put in the terminating ")" */
                        proto_item_append_text(flags_item, ")");
                    }
@@ -768,5 +823,5 @@ proto_reg_handoff_bpdu(void)
   bpdu_handle = find_dissector("bpdu");
   dissector_add("llc.dsap", SAP_BPDU, bpdu_handle);
   dissector_add("ppp.protocol", PPP_BPDU, bpdu_handle);
-  dissector_add("chdlctype", 0x4242, bpdu_handle);
+  dissector_add("chdlctype", CHDLCTYPE_BPDU, bpdu_handle);
 }