X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ee68aa36460d7efeca48747f33b7f2adc0900bfb..37800b45d586bcf7bb0a1e00ac46a69240614f0b:/print-pim.c diff --git a/print-pim.c b/print-pim.c index 5b1d61bc..35fb476e 100644 --- a/print-pim.c +++ b/print-pim.c @@ -118,6 +118,23 @@ static const struct tok pimv2_register_flag_values[] = { { 0, NULL} }; +#define PIMV2_DF_ELECTION_OFFER 1 +#define PIMV2_DF_ELECTION_WINNER 2 +#define PIMV2_DF_ELECTION_BACKOFF 3 +#define PIMV2_DF_ELECTION_PASS 4 + +static struct tok pimv2_df_election_flag_values[] = { + { PIMV2_DF_ELECTION_OFFER, "Offer" }, + { PIMV2_DF_ELECTION_WINNER, "Winner" }, + { PIMV2_DF_ELECTION_BACKOFF, "Backoff" }, + { PIMV2_DF_ELECTION_PASS, "Pass" }, + { 0, NULL} +}; + +#define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x) ( \ + x == PIMV2_DF_ELECTION_BACKOFF ? "offer" : "new winner" ) + + /* * XXX: We consider a case where IPv6 is not ready yet for portability, * but PIM dependent defintions should be independent of IPv6... @@ -133,7 +150,8 @@ struct pim { */ #define PIM_VER(x) (((x) & 0xf0) >> 4) #define PIM_TYPE(x) ((x) & 0x0f) - nd_uint8_t pim_rsv; /* Reserved in v1, address length in v2 */ + nd_uint8_t pim_rsv; /* Reserved in v1, subtype+address length in v2 */ +#define PIM_SUBTYPE(x) (((x) & 0xf0) >> 4) nd_uint16_t pim_cksum; /* IP style check sum */ }; @@ -705,21 +723,29 @@ pimv2_print(netdissect_options *ndo, { const struct pim *pim = (const struct pim *)bp; int advance; + int subtype; enum checksum_status cksum_status; u_int pim_typever; u_int pimv2_addr_len; ndo->ndo_protocol = "pimv2"; - if (len < 2) - goto trunc; + if (len < 2) { + ND_PRINT("[length %u < 2]", len); + nd_print_invalid(ndo); + return; + } ND_TCHECK_1(pim->pim_rsv); pim_typever = GET_U_1(pim->pim_typever); - pimv2_addr_len = GET_U_1(pim->pim_rsv); + /* RFC5015 allocates the high 4 bits of pim_rsv for "subtype". */ + pimv2_addr_len = GET_U_1(pim->pim_rsv) & 0x0f; if (pimv2_addr_len != 0) ND_PRINT(", RFC2117-encoding"); - if (len < 4) - goto trunc; + if (len < 4) { + ND_PRINT("[length %u < 4]", len); + nd_print_invalid(ndo); + return; + } ND_TCHECK_2(pim->pim_cksum); ND_PRINT(", cksum 0x%04x ", GET_BE_U_2(pim->pim_cksum)); if (GET_BE_U_2(pim->pim_cksum) == 0) { @@ -787,7 +813,9 @@ pimv2_print(netdissect_options *ndo, switch (otype) { case PIMV2_HELLO_OPTION_HOLDTIME: if (olen != 2) { - ND_PRINT("ERROR: Option Length != 2 Bytes (%u)", olen); + ND_PRINT("[option length %u != 2]", olen); + nd_print_invalid(ndo); + return; } else { unsigned_relts_print(ndo, GET_BE_U_2(bp)); @@ -796,7 +824,9 @@ pimv2_print(netdissect_options *ndo, case PIMV2_HELLO_OPTION_LANPRUNEDELAY: if (olen != 4) { - ND_PRINT("ERROR: Option Length != 4 Bytes (%u)", olen); + ND_PRINT("[option length %u != 4]", olen); + nd_print_invalid(ndo); + return; } else { char t_bit; uint16_t lan_delay, override_interval; @@ -819,14 +849,18 @@ pimv2_print(netdissect_options *ndo, ND_PRINT("%u", GET_BE_U_4(bp)); break; default: - ND_PRINT("ERROR: Option Length != 4 Bytes (%u)", olen); + ND_PRINT("[option length %u != 4]", olen); + nd_print_invalid(ndo); + return; break; } break; case PIMV2_HELLO_OPTION_GENID: if (olen != 4) { - ND_PRINT("ERROR: Option Length != 4 Bytes (%u)", olen); + ND_PRINT("[option length %u != 4]", olen); + nd_print_invalid(ndo); + return; } else { ND_PRINT("0x%08x", GET_BE_U_4(bp)); } @@ -834,7 +868,9 @@ pimv2_print(netdissect_options *ndo, case PIMV2_HELLO_OPTION_REFRESH_CAP: if (olen != 4) { - ND_PRINT("ERROR: Option Length != 4 Bytes (%u)", olen); + ND_PRINT("[option length %u != 4]", olen); + nd_print_invalid(ndo); + return; } else { ND_PRINT("v%u", GET_U_1(bp)); if (GET_U_1(bp + 1) != 0) { @@ -1192,6 +1228,48 @@ pimv2_print(netdissect_options *ndo, unsigned_relts_print(ndo, GET_BE_U_2(bp)); break; + case PIMV2_TYPE_DF_ELECTION: + subtype = PIM_SUBTYPE(GET_U_1(pim->pim_rsv)); + ND_PRINT("\n\t %s,", tok2str( pimv2_df_election_flag_values, + "Unknown", subtype) ); + + ND_PRINT(" rpa="); + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) { + goto trunc; + } + bp += advance; + len -= advance; + ND_PRINT(" sender pref=%u", GET_BE_U_4(bp) ); + ND_PRINT(" sender metric=%u", GET_BE_U_4(bp + 4)); + + bp += 8; + len -= 8; + + switch (subtype) { + case PIMV2_DF_ELECTION_BACKOFF: + case PIMV2_DF_ELECTION_PASS: + ND_PRINT("\n\t %s addr=", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype)); + if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) { + goto trunc; + } + bp += advance; + len -= advance; + + ND_PRINT(" %s pref=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp) ); + ND_PRINT(" %s metric=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp + 4)); + + bp += 8; + len -= 8; + + if (subtype == PIMV2_DF_ELECTION_BACKOFF) { + ND_PRINT(" interval %dms", GET_BE_U_2(bp)); + } + + break; + default: + break; + } + break; default: ND_PRINT(" [type %u]", PIM_TYPE(pim_typever));