+ nd_print_trunc(ndo);
+ return ep;
+}
+
+static const u_char *
+of10_bsn_message_print(netdissect_options *ndo,
+ const u_char *cp, const u_char *ep, const u_int len)
+{
+ const u_char *cp0 = cp;
+ uint32_t subtype;
+
+ if (len < 4)
+ goto invalid;
+ /* subtype */
+ ND_TCHECK_4(cp);
+ subtype = GET_BE_U_4(cp);
+ cp += 4;
+ ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
+ switch (subtype) {
+ case BSN_GET_IP_MASK_REQUEST:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | index | pad |
+ * +---------------+---------------+---------------+---------------+
+ * | pad |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 12)
+ goto invalid;
+ /* index */
+ ND_TCHECK_1(cp);
+ ND_PRINT(", index %u", GET_U_1(cp));
+ cp += 1;
+ /* pad */
+ ND_TCHECK_7(cp);
+ cp += 7;
+ break;
+ case BSN_SET_IP_MASK:
+ case BSN_GET_IP_MASK_REPLY:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | index | pad |
+ * +---------------+---------------+---------------+---------------+
+ * | mask |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 12)
+ goto invalid;
+ /* index */
+ ND_TCHECK_1(cp);
+ ND_PRINT(", index %u", GET_U_1(cp));
+ cp += 1;
+ /* pad */
+ ND_TCHECK_3(cp);
+ cp += 3;
+ /* mask */
+ ND_TCHECK_4(cp);
+ ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
+ cp += 4;
+ break;
+ case BSN_SET_MIRRORING:
+ case BSN_GET_MIRRORING_REQUEST:
+ case BSN_GET_MIRRORING_REPLY:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | report m. p. | pad |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 8)
+ goto invalid;
+ /* report_mirror_ports */
+ ND_TCHECK_1(cp);
+ ND_PRINT(", report_mirror_ports %s",
+ tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
+ cp += 1;
+ /* pad */
+ ND_TCHECK_3(cp);
+ cp += 3;
+ break;
+ case BSN_GET_INTERFACES_REQUEST:
+ case BSN_GET_L2_TABLE_REQUEST:
+ case BSN_BW_ENABLE_GET_REQUEST:
+ case BSN_BW_CLEAR_DATA_REQUEST:
+ case BSN_HYBRID_GET_REQUEST:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 4)
+ goto invalid;
+ break;
+ case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | vport_no |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 8)
+ goto invalid;
+ /* vport_no */
+ ND_TCHECK_4(cp);
+ ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
+ cp += 4;
+ break;
+ case BSN_SHELL_COMMAND:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | service |
+ * +---------------+---------------+---------------+---------------+
+ * | data ...
+ * +---------------+---------------+--------
+ *
+ */
+ if (len < 8)
+ goto invalid;
+ /* service */
+ ND_TCHECK_4(cp);
+ ND_PRINT(", service %u", GET_BE_U_4(cp));
+ cp += 4;
+ /* data */
+ ND_PRINT(", data '");
+ if (nd_printn(ndo, cp, len - 8, ep)) {
+ ND_PRINT("'");
+ goto trunc;
+ }
+ ND_PRINT("'");
+ cp += len - 8;
+ break;
+ case BSN_SHELL_OUTPUT:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | data ...
+ * +---------------+---------------+--------
+ *
+ */
+ /* already checked that len >= 4 */
+ /* data */
+ ND_PRINT(", data '");
+ if (nd_printn(ndo, cp, len - 4, ep)) {
+ ND_PRINT("'");
+ goto trunc;
+ }
+ ND_PRINT("'");
+ cp += len - 4;
+ break;
+ case BSN_SHELL_STATUS:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | status |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 8)
+ goto invalid;
+ /* status */
+ ND_TCHECK_4(cp);
+ ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
+ cp += 4;
+ break;
+ default:
+ ND_TCHECK_LEN(cp, len - 4);
+ cp += len - 4;
+ }
+ return cp;
+
+invalid: /* skip the undersized data */
+ nd_print_invalid(ndo);
+ ND_TCHECK_LEN(cp0, len);
+ return cp0 + len;
+trunc:
+ nd_print_trunc(ndo);
+ return ep;
+}
+
+static const u_char *
+of10_bsn_actions_print(netdissect_options *ndo,
+ const u_char *cp, const u_char *ep, const u_int len)
+{
+ const u_char *cp0 = cp;
+ uint32_t subtype, vlan_tag;
+
+ if (len < 4)
+ goto invalid;
+ /* subtype */
+ ND_TCHECK_4(cp);
+ subtype = GET_BE_U_4(cp);
+ cp += 4;
+ ND_PRINT("\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
+ switch (subtype) {
+ case BSN_ACTION_MIRROR:
+ /*
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +---------------+---------------+---------------+---------------+
+ * | subtype |
+ * +---------------+---------------+---------------+---------------+
+ * | dest_port |
+ * +---------------+---------------+---------------+---------------+
+ * | vlan_tag |
+ * +---------------+---------------+---------------+---------------+
+ * | copy_stage | pad |
+ * +---------------+---------------+---------------+---------------+
+ *
+ */
+ if (len != 16)
+ goto invalid;
+ /* dest_port */
+ ND_TCHECK_4(cp);
+ ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
+ cp += 4;
+ /* vlan_tag */
+ ND_TCHECK_4(cp);
+ vlan_tag = GET_BE_U_4(cp);
+ cp += 4;
+ switch (vlan_tag >> 16) {
+ case 0:
+ ND_PRINT(", vlan_tag none");
+ break;
+ case ETHERTYPE_8021Q:
+ ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
+ break;
+ default:
+ ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
+ }
+ /* copy_stage */
+ ND_TCHECK_1(cp);
+ ND_PRINT(", copy_stage %s",
+ tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
+ cp += 1;
+ /* pad */
+ ND_TCHECK_3(cp);
+ cp += 3;
+ break;
+ default:
+ ND_TCHECK_LEN(cp, len - 4);
+ cp += len - 4;
+ }
+
+ return cp;
+
+invalid:
+ nd_print_invalid(ndo);
+ ND_TCHECK_LEN(cp0, len);
+ return cp0 + len;
+trunc:
+ nd_print_trunc(ndo);
+ return ep;
+}
+
+static const u_char *
+of10_vendor_action_print(netdissect_options *ndo,
+ const u_char *cp, const u_char *ep, const u_int len)
+{
+ uint32_t vendor;
+ const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, const u_int);
+
+ if (len < 4)
+ goto invalid;
+ /* vendor */
+ ND_TCHECK_4(cp);
+ vendor = GET_BE_U_4(cp);
+ cp += 4;
+ ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
+ /* data */
+ decoder =
+ vendor == OUI_BSN ? of10_bsn_actions_print :
+ of10_data_print;
+ return decoder(ndo, cp, ep, len - 4);
+
+invalid: /* skip the undersized data */
+ nd_print_invalid(ndo);
+ ND_TCHECK_LEN(cp, len);
+ return cp + len;
+trunc:
+ nd_print_trunc(ndo);
+ return ep;
+}
+
+static const u_char *
+of10_vendor_message_print(netdissect_options *ndo,
+ const u_char *cp, const u_char *ep, const u_int len)
+{
+ uint32_t vendor;
+ const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, u_int);
+
+ if (len < 4)
+ goto invalid;
+ /* vendor */
+ ND_TCHECK_4(cp);
+ vendor = GET_BE_U_4(cp);
+ cp += 4;
+ ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
+ /* data */
+ decoder =
+ vendor == OUI_BSN ? of10_bsn_message_print :
+ of10_data_print;
+ return decoder(ndo, cp, ep, len - 4);
+
+invalid: /* skip the undersized data */
+ nd_print_invalid(ndo);
+ ND_TCHECK_LEN(cp, len);
+ return cp + len;
+trunc:
+ nd_print_trunc(ndo);