X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ff8464bffd24a451a5a4c08c6c6ab7d0a2c88785..1a04b92e365f5ed01ca38619b41bcc4fc9cbd63c:/print-cfm.c?ds=sidebyside diff --git a/print-cfm.c b/print-cfm.c index 09199fa5..bc5125f1 100644 --- a/print-cfm.c +++ b/print-cfm.c @@ -27,7 +27,6 @@ #include "netdissect.h" #include "extract.h" -#include "ether.h" #include "addrtoname.h" #include "oui.h" #include "af.h" @@ -116,8 +115,8 @@ struct cfm_lbm_t { struct cfm_ltm_t { uint8_t transaction_id[4]; uint8_t ttl; - uint8_t original_mac[ETHER_ADDR_LEN]; - uint8_t target_mac[ETHER_ADDR_LEN]; + nd_mac_addr original_mac; + nd_mac_addr target_mac; }; static const struct tok cfm_ltm_flag_values[] = { @@ -217,17 +216,22 @@ static const struct tok cfm_tlv_senderid_chassisid_values[] = { static int cfm_network_addr_print(netdissect_options *ndo, - register const u_char *tptr) + const u_char *tptr, const u_int length) { u_int network_addr_type; u_int hexdump = FALSE; /* - * Altough AFIs are tpically 2 octects wide, + * Although AFIs are typically 2 octects wide, * 802.1ab specifies that this field width - * is only once octet + * is only one octet. */ - network_addr_type = *tptr; + if (length < 1) { + ND_PRINT((ndo, "\n\t Network Address Type (invalid, no data")); + return hexdump; + } + /* The calling function must make any due ND_TCHECK calls. */ + network_addr_type = EXTRACT_U_1(tptr); ND_PRINT((ndo, "\n\t Network Address Type %s (%u)", tok2str(af_values, "Unknown", network_addr_type), network_addr_type)); @@ -237,10 +241,20 @@ cfm_network_addr_print(netdissect_options *ndo, */ switch(network_addr_type) { case AFNUM_INET: + if (length != 1 + 4) { + ND_PRINT((ndo, "(invalid IPv4 address length %u)", length - 1)); + hexdump = TRUE; + break; + } ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr + 1))); break; case AFNUM_INET6: + if (length != 1 + 16) { + ND_PRINT((ndo, "(invalid IPv6 address length %u)", length - 1)); + hexdump = TRUE; + break; + } ND_PRINT((ndo, ", %s", ip6addr_string(ndo, tptr + 1))); break; @@ -254,7 +268,7 @@ cfm_network_addr_print(netdissect_options *ndo, void cfm_print(netdissect_options *ndo, - register const u_char *pptr, register u_int length) + const u_char *pptr, u_int length) { const struct cfm_common_header_t *cfm_common_header; const struct cfm_tlv_header_t *cfm_tlv_header; @@ -305,7 +319,7 @@ cfm_print(netdissect_options *ndo, ND_PRINT((ndo, "\n\tFirst TLV offset %u", cfm_common_header->first_tlv_offset)); - tptr += sizeof(const struct cfm_common_header_t); + tptr += sizeof(struct cfm_common_header_t); tlen = length - sizeof(struct cfm_common_header_t); /* @@ -346,8 +360,8 @@ cfm_print(netdissect_options *ndo, } ND_PRINT((ndo, "\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x", - EXTRACT_32BITS(msg_ptr.cfm_ccm->sequence), - EXTRACT_16BITS(msg_ptr.cfm_ccm->ma_epi))); + EXTRACT_BE_U_4(msg_ptr.cfm_ccm->sequence), + EXTRACT_BE_U_2(msg_ptr.cfm_ccm->ma_epi))); namesp = msg_ptr.cfm_ccm->names; names_data_remaining = sizeof(msg_ptr.cfm_ccm->names); @@ -355,11 +369,11 @@ cfm_print(netdissect_options *ndo, /* * Resolve the MD fields. */ - md_nameformat = *namesp; + md_nameformat = EXTRACT_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ if (md_nameformat != CFM_CCM_MD_FORMAT_NONE) { - md_namelength = *namesp; + md_namelength = EXTRACT_U_1(namesp); namesp++; names_data_remaining--; /* We know this is !=0 */ ND_PRINT((ndo, "\n\t MD Name Format %s (%u), MD Name length %u", @@ -368,8 +382,11 @@ cfm_print(netdissect_options *ndo, md_nameformat, md_namelength)); - /* -2 for the MA short name format and length */ - if (md_namelength > names_data_remaining - 2) { + /* + * -3 for the MA short name format and length and one byte + * of MA short name. + */ + if (md_namelength > names_data_remaining - 3) { ND_PRINT((ndo, " (too large, must be <= %u)", names_data_remaining - 2)); return; } @@ -410,10 +427,10 @@ cfm_print(netdissect_options *ndo, /* * Resolve the MA fields. */ - ma_nameformat = *namesp; + ma_nameformat = EXTRACT_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ - ma_namelength = *namesp; + ma_namelength = EXTRACT_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ ND_PRINT((ndo, "\n\t MA Name-Format %s (%u), MA name length %u", @@ -459,7 +476,7 @@ cfm_print(netdissect_options *ndo, bittok2str(cfm_ltm_flag_values, "none", cfm_common_header->flags))); ND_PRINT((ndo, "\n\t Transaction-ID 0x%08x, ttl %u", - EXTRACT_32BITS(msg_ptr.cfm_ltm->transaction_id), + EXTRACT_BE_U_4(msg_ptr.cfm_ltm->transaction_id), msg_ptr.cfm_ltm->ttl)); ND_PRINT((ndo, "\n\t Original-MAC %s, Target-MAC %s", @@ -482,7 +499,7 @@ cfm_print(netdissect_options *ndo, bittok2str(cfm_ltr_flag_values, "none", cfm_common_header->flags))); ND_PRINT((ndo, "\n\t Transaction-ID 0x%08x, ttl %u", - EXTRACT_32BITS(msg_ptr.cfm_ltr->transaction_id), + EXTRACT_BE_U_4(msg_ptr.cfm_ltr->transaction_id), msg_ptr.cfm_ltr->ttl)); ND_PRINT((ndo, "\n\t Replay-Action %s (%u)", @@ -511,7 +528,7 @@ cfm_print(netdissect_options *ndo, cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr; /* Enough to read the tlv type ? */ - ND_TCHECK2(*tptr, 1); + ND_TCHECK_1(tptr); cfm_tlv_type=cfm_tlv_header->type; ND_PRINT((ndo, "\n\t%s TLV (0x%02x)", @@ -526,8 +543,8 @@ cfm_print(netdissect_options *ndo, /* do we have the full tlv header ? */ if (tlen < sizeof(struct cfm_tlv_header_t)) goto tooshort; - ND_TCHECK2(*tptr, sizeof(struct cfm_tlv_header_t)); - cfm_tlv_len=EXTRACT_16BITS(&cfm_tlv_header->length); + ND_TCHECK_LEN(tptr, sizeof(struct cfm_tlv_header_t)); + cfm_tlv_len=EXTRACT_BE_U_2(&cfm_tlv_header->length); ND_PRINT((ndo, ", length %u", cfm_tlv_len)); @@ -538,7 +555,7 @@ cfm_print(netdissect_options *ndo, /* do we have the full tlv ? */ if (tlen < cfm_tlv_len) goto tooshort; - ND_TCHECK2(*tptr, cfm_tlv_len); + ND_TCHECK_LEN(tptr, cfm_tlv_len); hexdump = FALSE; switch(cfm_tlv_type) { @@ -548,8 +565,8 @@ cfm_print(netdissect_options *ndo, return; } ND_PRINT((ndo, ", Status: %s (%u)", - tok2str(cfm_tlv_port_status_values, "Unknown", *tptr), - *tptr)); + tok2str(cfm_tlv_port_status_values, "Unknown", EXTRACT_U_1(tptr)), + EXTRACT_U_1(tptr))); break; case CFM_TLV_INTERFACE_STATUS: @@ -558,8 +575,8 @@ cfm_print(netdissect_options *ndo, return; } ND_PRINT((ndo, ", Status: %s (%u)", - tok2str(cfm_tlv_interface_status_values, "Unknown", *tptr), - *tptr)); + tok2str(cfm_tlv_interface_status_values, "Unknown", EXTRACT_U_1(tptr)), + EXTRACT_U_1(tptr))); break; case CFM_TLV_PRIVATE: @@ -568,9 +585,9 @@ cfm_print(netdissect_options *ndo, return; } ND_PRINT((ndo, ", Vendor: %s (%u), Sub-Type %u", - tok2str(oui_values,"Unknown", EXTRACT_24BITS(tptr)), - EXTRACT_24BITS(tptr), - *(tptr + 3))); + tok2str(oui_values,"Unknown", EXTRACT_BE_U_3(tptr)), + EXTRACT_BE_U_3(tptr), + EXTRACT_U_1(tptr + 3))); hexdump = TRUE; break; @@ -581,23 +598,29 @@ cfm_print(netdissect_options *ndo, if (cfm_tlv_len < 1) { ND_PRINT((ndo, " (too short, must be >= 1)")); - return; + goto next_tlv; } /* * Get the Chassis ID length and check it. + * IEEE 802.1Q-2014 Section 21.5.3.1 */ - chassis_id_length = *tptr; + 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)")); - return; + goto next_tlv; } - chassis_id_type = *tptr; + 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, @@ -608,16 +631,22 @@ cfm_print(netdissect_options *ndo, if (cfm_tlv_len < chassis_id_length) { ND_PRINT((ndo, "\n\t (TLV too short)")); - return; + 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 != MAC_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); + hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length); break; case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */ @@ -640,38 +669,53 @@ cfm_print(netdissect_options *ndo, /* * 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. */ - return; + break; } - mgmt_addr_length = *tptr; + /* 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)")); - return; + 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, "\n\t (TLV too short)")); - return; + ND_PRINT((ndo, " (Management Address Length is missing)")); + hexdump = TRUE; + break; } - - mgmt_addr_length = *tptr; + + /* 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; @@ -680,6 +724,7 @@ cfm_print(netdissect_options *ndo, /* * 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; } @@ -703,6 +748,7 @@ cfm_print(netdissect_options *ndo, if (hexdump || ndo->ndo_vflag > 1) print_unknown_data(ndo, tlv_ptr, "\n\t ", cfm_tlv_len); +next_tlv: tptr+=cfm_tlv_len; tlen-=cfm_tlv_len; }