+ case CFM_TLV_PORT_STATUS:
+ if (cfm_tlv_len < 1) {
+ ND_PRINT((ndo, " (too short, must be >= 1)"));
+ return;
+ }
+ ND_PRINT((ndo, ", Status: %s (%u)",
+ tok2str(cfm_tlv_port_status_values, "Unknown", EXTRACT_U_1(tptr)),
+ EXTRACT_U_1(tptr)));
+ break;
+
+ case CFM_TLV_INTERFACE_STATUS:
+ if (cfm_tlv_len < 1) {
+ ND_PRINT((ndo, " (too short, must be >= 1)"));
+ return;
+ }
+ ND_PRINT((ndo, ", Status: %s (%u)",
+ tok2str(cfm_tlv_interface_status_values, "Unknown", EXTRACT_U_1(tptr)),
+ EXTRACT_U_1(tptr)));
+ break;
+
+ case CFM_TLV_PRIVATE:
+ if (cfm_tlv_len < 4) {
+ ND_PRINT((ndo, " (too short, must be >= 4)"));
+ return;
+ }
+ ND_PRINT((ndo, ", Vendor: %s (%u), Sub-Type %u",
+ tok2str(oui_values,"Unknown", EXTRACT_BE_U_3(tptr)),
+ EXTRACT_BE_U_3(tptr),
+ EXTRACT_U_1(tptr + 3)));
+ hexdump = TRUE;
+ break;
+
+ case CFM_TLV_SENDER_ID:
+ {
+ u_int chassis_id_type, chassis_id_length;
+ u_int mgmt_addr_length;
+
+ if (cfm_tlv_len < 1) {
+ ND_PRINT((ndo, " (too short, must be >= 1)"));
+ goto next_tlv;
+ }
+
+ /*
+ * Get the Chassis ID length and check it.
+ * IEEE 802.1Q-2014 Section 21.5.3.1
+ */
+ chassis_id_length = EXTRACT_U_1(tptr);
+ tptr++;
+ tlen--;
+ cfm_tlv_len--;
+
+ if (chassis_id_length) {
+ /*
+ * IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references
+ * IEEE 802.1AB-2005 Section 9.5.2.2, subsequently
+ * IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype
+ */
+ if (cfm_tlv_len < 1) {
+ ND_PRINT((ndo, "\n\t (TLV too short)"));
+ goto next_tlv;
+ }
+ chassis_id_type = EXTRACT_U_1(tptr);
+ cfm_tlv_len--;
+ ND_PRINT((ndo, "\n\t Chassis-ID Type %s (%u), Chassis-ID length %u",
+ tok2str(cfm_tlv_senderid_chassisid_values,
+ "Unknown",
+ chassis_id_type),
+ chassis_id_type,
+ chassis_id_length));
+
+ if (cfm_tlv_len < chassis_id_length) {
+ ND_PRINT((ndo, "\n\t (TLV too short)"));
+ goto next_tlv;
+ }
+
+ /* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */
+ switch (chassis_id_type) {
+ case CFM_CHASSIS_ID_MAC_ADDRESS:
+ if (chassis_id_length != ETHER_ADDR_LEN) {
+ ND_PRINT((ndo, " (invalid MAC address length)"));
+ hexdump = TRUE;
+ break;
+ }
+ ND_PRINT((ndo, "\n\t MAC %s", etheraddr_string(ndo, tptr + 1)));
+ break;
+
+ case CFM_CHASSIS_ID_NETWORK_ADDRESS:
+ hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length);
+ break;
+
+ case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */
+ case CFM_CHASSIS_ID_INTERFACE_ALIAS:
+ case CFM_CHASSIS_ID_LOCAL:
+ case CFM_CHASSIS_ID_CHASSIS_COMPONENT:
+ case CFM_CHASSIS_ID_PORT_COMPONENT:
+ safeputs(ndo, tptr + 1, chassis_id_length);
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ cfm_tlv_len -= chassis_id_length;
+
+ tptr += 1 + chassis_id_length;
+ tlen -= 1 + chassis_id_length;
+ }
+
+ /*
+ * Check if there is a Management Address.
+ * IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length
+ * This and all subsequent fields are not present if the TLV length
+ * allows only the above fields.
+ */
+ if (cfm_tlv_len == 0) {
+ /* No, there isn't; we're done. */
+ break;
+ }
+
+ /* Here mgmt_addr_length stands for the management domain length. */
+ mgmt_addr_length = EXTRACT_U_1(tptr);
+ tptr++;
+ tlen--;
+ cfm_tlv_len--;
+ ND_PRINT((ndo, "\n\t Management Address Domain Length %u", mgmt_addr_length));
+ if (mgmt_addr_length) {
+ /* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */
+ if (cfm_tlv_len < mgmt_addr_length) {
+ ND_PRINT((ndo, "\n\t (TLV too short)"));
+ goto next_tlv;
+ }
+ cfm_tlv_len -= mgmt_addr_length;
+ /*
+ * XXX - this is an OID; print it as such.
+ */
+ hex_print(ndo, "\n\t Management Address Domain: ", tptr, mgmt_addr_length);
+ tptr += mgmt_addr_length;
+ tlen -= mgmt_addr_length;
+
+ /*
+ * IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length
+ * This field is present if Management Address Domain Length is not 0.
+ */
+ if (cfm_tlv_len < 1) {
+ ND_PRINT((ndo, " (Management Address Length is missing)"));
+ hexdump = TRUE;
+ break;
+ }
+
+ /* Here mgmt_addr_length stands for the management address length. */
+ mgmt_addr_length = EXTRACT_U_1(tptr);
+ tptr++;
+ tlen--;
+ cfm_tlv_len--;
+ ND_PRINT((ndo, "\n\t Management Address Length %u", mgmt_addr_length));
+ if (mgmt_addr_length) {
+ /* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */
+ if (cfm_tlv_len < mgmt_addr_length) {
+ ND_PRINT((ndo, "\n\t (TLV too short)"));
+ return;
+ }
+ cfm_tlv_len -= mgmt_addr_length;
+ /*
+ * XXX - this is a TransportDomain; print it as such.
+ */
+ hex_print(ndo, "\n\t Management Address: ", tptr, mgmt_addr_length);
+ tptr += mgmt_addr_length;
+ tlen -= mgmt_addr_length;
+ }
+ }
+ break;
+ }