X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/72da02943f6d9c2c030f5266ca4547cbc28165f7..HEAD:/print-ldp.c diff --git a/print-ldp.c b/print-ldp.c index 680a7e1e..bdf9a138 100644 --- a/print-ldp.c +++ b/print-ldp.c @@ -16,9 +16,7 @@ /* \summary: Label Distribution Protocol (LDP) printer */ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" @@ -29,7 +27,6 @@ #include "l2vpn.h" #include "af.h" - /* * ldp common header * @@ -142,8 +139,10 @@ static const struct tok ldp_msg_values[] = { #define LDP_TLV_ATM_SESSION_PARM 0x0501 #define LDP_TLV_FR_SESSION_PARM 0x0502 #define LDP_TLV_FT_SESSION 0x0503 +#define LDP_TLV_TYPED_WC_FEC_CAP 0x050b /* rfc 5918 */ #define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600 #define LDP_TLV_MTU 0x0601 /* rfc 3988 */ +#define LDP_TLV_DUAL_STACK_CAP 0x0701 /* rfc 7552 */ static const struct tok ldp_tlv_values[] = { { LDP_TLV_FEC, "FEC" }, @@ -165,8 +164,41 @@ static const struct tok ldp_tlv_values[] = { { LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" }, { LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" }, { LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" }, + { LDP_TLV_TYPED_WC_FEC_CAP, "Typed Wildcard FEC Capability" }, { LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" }, { LDP_TLV_MTU, "MTU" }, + { LDP_TLV_DUAL_STACK_CAP, "Dual-Stack Capability" }, + { 0, NULL} +}; + +static const struct tok ldp_status_code_values[] = { + /* rfc 5036 */ + { 0x00000000, "Success" }, + { 0x00000001, "Bad LDP Identifier" }, + { 0x00000002, "Bad Protocol Version" }, + { 0x00000003, "Bad PDU Length" }, + { 0x00000004, "Unknown Message Type" }, + { 0x00000005, "Bad Message Length" }, + { 0x00000006, "Unknown TLV" }, + { 0x00000007, "Bad TLV Length" }, + { 0x00000008, "Malformted TLV Value" }, + { 0x00000009, "Hold Timer Expired" }, + { 0x0000000A, "Shutdown" }, + { 0x0000000B, "Loop Detected" }, + { 0x0000000C, "Unknown FEC" }, + { 0x0000000D, "No Route" }, + { 0x0000000E, "No Label Resources" }, + { 0x0000000F, "Label Resources/Available" }, + { 0x00000010, "Session Rejected/No Hello" }, + { 0x00000011, "Session Rejected/Parameters Advertisement Mode" }, + { 0x00000012, "Session Rejected/Parameters Max PDU Length" }, + { 0x00000013, "Session Rejected/Parameters Label Range" }, + { 0x00000014, "KeepAlive Timer Expired" }, + { 0x00000015, "Label Request Aborted" }, + { 0x00000016, "Missing Message Parameters" }, + { 0x00000017, "Unsupported Address Family" }, + { 0x00000018, "Session Rejected/Bad KeepAlive Time" }, + { 0x00000019, "Internal Error" }, { 0, NULL} }; @@ -211,7 +243,17 @@ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { { 0, NULL} }; -static int ldp_pdu_print(netdissect_options *, const u_char *); +/* rfc 7552 */ +#define LDP_DUAL_STACK_TRANSPORT_PREF_IPV4 0x40 +#define LDP_DUAL_STACK_TRANSPORT_PREF_IPV6 0x60 + +static const struct tok ldp_dual_stack_transport_pref_values[] = { + { LDP_DUAL_STACK_TRANSPORT_PREF_IPV4, "IPv4" }, + { LDP_DUAL_STACK_TRANSPORT_PREF_IPV6, "IPv6" }, + { 0, NULL} +}; + +static u_int ldp_pdu_print(netdissect_options *, const u_char *); /* * ldp tlv header @@ -230,9 +272,6 @@ static int ldp_pdu_print(netdissect_options *, const u_char *); * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define TLV_TCHECK(minlen) \ - ND_TCHECK_LEN(tptr, minlen); if (tlv_tlen < minlen) goto badtlv; - static u_int ldp_tlv_print(netdissect_options *ndo, const u_char *tptr, @@ -245,8 +284,8 @@ ldp_tlv_print(netdissect_options *ndo, const struct ldp_tlv_header *ldp_tlv_header; u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; - u_char fec_type; - u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; + u_char fec_type, transport_pref; + u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len; char buf[100]; int i; @@ -275,7 +314,7 @@ ldp_tlv_print(netdissect_options *ndo, switch(tlv_type) { case LDP_TLV_COMMON_HELLO: - TLV_TCHECK(4); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]", GET_BE_U_2(tptr), (GET_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", @@ -283,38 +322,37 @@ ldp_tlv_print(netdissect_options *ndo, break; case LDP_TLV_IPV4_TRANSPORT_ADDR: - TLV_TCHECK(4); - ND_PRINT("\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); + ND_PRINT("\n\t IPv4 Transport Address: %s", GET_IPADDR_STRING(tptr)); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: - TLV_TCHECK(16); - ND_PRINT("\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 16); + ND_PRINT("\n\t IPv6 Transport Address: %s", GET_IP6ADDR_STRING(tptr)); break; case LDP_TLV_CONFIG_SEQ_NUMBER: - TLV_TCHECK(4); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); ND_PRINT("\n\t Sequence Number: %u", GET_BE_U_4(tptr)); break; case LDP_TLV_ADDRESS_LIST: - TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, + LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = GET_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT("\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af)); switch (af) { - case AFNUM_INET: + case AFNUM_IP: while(tlv_tlen >= sizeof(nd_ipv4)) { - ND_TCHECK_LEN(tptr, sizeof(nd_ipv4)); - ND_PRINT(" %s", ipaddr_string(ndo, tptr)); + ND_PRINT(" %s", GET_IPADDR_STRING(tptr)); tlv_tlen-=sizeof(nd_ipv4); tptr+=sizeof(nd_ipv4); } break; - case AFNUM_INET6: + case AFNUM_IP6: while(tlv_tlen >= sizeof(nd_ipv6)) { - ND_TCHECK_LEN(tptr, sizeof(nd_ipv6)); - ND_PRINT(" %s", ip6addr_string(ndo, tptr)); + ND_PRINT(" %s", GET_IP6ADDR_STRING(tptr)); tlv_tlen-=sizeof(nd_ipv6); tptr+=sizeof(nd_ipv6); } @@ -325,17 +363,40 @@ ldp_tlv_print(netdissect_options *ndo, } break; + case LDP_TLV_HOP_COUNT: + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 1); + ND_PRINT("\n\t Hop Count: %u", GET_U_1(tptr)); + break; + + case LDP_TLV_PATH_VECTOR: + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); + ND_PRINT("\n\t Path Vector: %s", GET_IPADDR_STRING(tptr)); + tptr += 4; + tlv_tlen -= 4; + while (tlv_tlen >= 4) { + ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); + tptr += 4; + tlv_tlen -= 4; + } + break; + case LDP_TLV_COMMON_SESSION: - TLV_TCHECK(8); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 14); ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", GET_BE_U_2(tptr), GET_BE_U_2(tptr + 2), - (GET_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", - (GET_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" + (GET_BE_U_2(tptr + 4)&0x8000) ? "On Demand" : "Unsolicited", + (GET_BE_U_2(tptr + 4)&0x4000) ? "Enabled" : "Disabled" + ); + ND_PRINT("\n\t Path Vector Limit %u, Max-PDU length: %u, Receiver Label-Space-ID %s:%u", + GET_U_1(tptr+5), + GET_BE_U_2(tptr+6), + GET_IPADDR_STRING(tptr+8), + GET_BE_U_2(tptr+12) ); break; case LDP_TLV_FEC: - TLV_TCHECK(1); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 1); fec_type = GET_U_1(tptr); ND_PRINT("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), @@ -348,11 +409,11 @@ ldp_tlv_print(netdissect_options *ndo, case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: - TLV_TCHECK(2); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 2); af = GET_BE_U_2(tptr); - tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; - tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; - if (af == AFNUM_INET) { + tptr+=2; + tlv_tlen-=2; + if (af == AFNUM_IP) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; @@ -362,8 +423,7 @@ ldp_tlv_print(netdissect_options *ndo, ND_PRINT(": IPv4 prefix (invalid length)"); else ND_PRINT(": IPv4 prefix %s", buf); - } - else if (af == AFNUM_INET6) { + } else if (af == AFNUM_IP6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; @@ -373,8 +433,7 @@ ldp_tlv_print(netdissect_options *ndo, ND_PRINT(": IPv6 prefix (invalid length)"); else ND_PRINT(": IPv6 prefix %s", buf); - } - else + } else ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: @@ -384,7 +443,7 @@ ldp_tlv_print(netdissect_options *ndo, * We assume the type was supposed to be one of the MPLS * Pseudowire Types. */ - TLV_TCHECK(7); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 7); vc_info_len = GET_U_1(tptr + 2); /* @@ -402,7 +461,7 @@ ldp_tlv_print(netdissect_options *ndo, } /* Make sure we have the VC ID as well */ - TLV_TCHECK(11); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 11); ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff), GET_BE_U_2(tptr)&0x8000 ? "" : "no ", @@ -419,7 +478,7 @@ ldp_tlv_print(netdissect_options *ndo, /* Skip past the fixed information and the VC ID */ tptr+=11; tlv_tlen-=11; - TLV_TCHECK(vc_info_len); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = GET_U_1(tptr); @@ -441,8 +500,7 @@ ldp_tlv_print(netdissect_options *ndo, case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT(": "); - for (idx = 2; idx < vc_info_tlv_len; idx++) - fn_print_char(ndo, GET_U_1(tptr + idx)); + nd_printjn(ndo, tptr + 2, vc_info_tlv_len - 2); break; case LDP_FEC_MARTINI_IFPARM_VCCV: @@ -468,26 +526,29 @@ ldp_tlv_print(netdissect_options *ndo, break; case LDP_TLV_GENERIC_LABEL: - TLV_TCHECK(4); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); ND_PRINT("\n\t Label: %u", GET_BE_U_4(tptr) & 0xfffff); break; case LDP_TLV_STATUS: - TLV_TCHECK(8); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 10); ui = GET_BE_U_4(tptr); tptr+=4; - ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]", - ui&0x3fffffff, - ui&0x80000000 ? "Fatal error" : "Advisory Notification", - ui&0x40000000 ? "do" : "don't"); + ND_PRINT("\n\t Status Code: %s, Flags: [%s and %s forward]", + tok2str(ldp_status_code_values, "Unknown", ui&0x3fffffff), + ui&0x80000000 ? "Fatal error" : "Advisory Notification", + ui&0x40000000 ? "do" : "don't"); ui = GET_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT(", causing Message ID: 0x%08x", ui); + ui = GET_BE_U_2(tptr); + if (ui) + ND_PRINT(", Message Type: %s", tok2str(ldp_msg_values, "Unknown", ui)); break; case LDP_TLV_FT_SESSION: - TLV_TCHECK(8); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 12); ft_flags = GET_BE_U_2(tptr); ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", @@ -495,6 +556,7 @@ ldp_tlv_print(netdissect_options *ndo, ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't "); + /* 16 bits (FT Flags) + 16 bits (Reserved) */ tptr+=4; ui = GET_BE_U_4(tptr); if (ui) @@ -505,19 +567,30 @@ ldp_tlv_print(netdissect_options *ndo, ND_PRINT(", Recovery Time: %ums", ui); break; + case LDP_TLV_TYPED_WC_FEC_CAP: + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 1); + ND_PRINT("\n\t %s", GET_U_1(tptr)&0x80 ? "Support" : "No Support"); + break; + case LDP_TLV_MTU: - TLV_TCHECK(2); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 2); ND_PRINT("\n\t MTU: %u", GET_BE_U_2(tptr)); break; + case LDP_TLV_DUAL_STACK_CAP: + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 4); + transport_pref = GET_U_1(tptr); + ND_PRINT("\n\t Transport Connection Preference: %s", + tok2str(ldp_dual_stack_transport_pref_values, + "Unknown", + transport_pref)); + break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ - case LDP_TLV_HOP_COUNT: - case LDP_TLV_PATH_VECTOR: case LDP_TLV_ATM_LABEL: case LDP_TLV_FR_LABEL: case LDP_TLV_EXTD_STATUS: @@ -535,11 +608,10 @@ ldp_tlv_print(netdissect_options *ndo, return(tlv_len+4); /* Type & Length fields not included */ trunc: - nd_print_trunc(ndo); - return 0; + nd_trunc_longjmp(ndo); -badtlv: - ND_PRINT("\n\t\t TLV contents go past end of TLV"); +invalid: + nd_print_invalid(ndo); return(tlv_len+4); /* Type & Length fields not included */ } @@ -547,19 +619,24 @@ void ldp_print(netdissect_options *ndo, const u_char *pptr, u_int len) { - int processed; + u_int processed; ndo->ndo_protocol = "ldp"; while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { processed = ldp_pdu_print(ndo, pptr); if (processed == 0) return; + if (len < processed) { + ND_PRINT(" [remaining length %u < %u]", len, processed); + nd_print_invalid(ndo); + break; + } len -= processed; pptr += processed; } } -static int +static u_int ldp_pdu_print(netdissect_options *ndo, const u_char *pptr) { @@ -587,17 +664,17 @@ ldp_pdu_print(netdissect_options *ndo, pdu_len = GET_BE_U_2(ldp_com_header->pdu_length); if (pdu_len < sizeof(struct ldp_common_header)-4) { /* length too short */ - ND_PRINT("%sLDP, pdu-length: %u (too short, < %u)", - (ndo->ndo_vflag < 1) ? "" : "\n\t", - pdu_len, - (u_int)(sizeof(struct ldp_common_header)-4)); + ND_PRINT("%sLDP, pdu-length: %u (too short, < %zu)", + (ndo->ndo_vflag < 1) ? "" : "\n\t", + pdu_len, + sizeof(struct ldp_common_header)-4); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", - ipaddr_string(ndo, ldp_com_header->lsr_id), + GET_IPADDR_STRING(ldp_com_header->lsr_id), GET_BE_U_2(ldp_com_header->label_space), pdu_len); @@ -609,7 +686,7 @@ ldp_pdu_print(netdissect_options *ndo, tptr = pptr + sizeof(struct ldp_common_header); tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */ - while(tlen>0) { + while(tlen != 0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); @@ -620,13 +697,13 @@ ldp_pdu_print(netdissect_options *ndo, if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ - ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %u)", - tok2str(ldp_msg_values, - "Unknown", - msg_type), - msg_type, - msg_len, - (u_int)(sizeof(struct ldp_msg_header)-4)); + ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %zu)", + tok2str(ldp_msg_values, + "Unknown", + msg_type), + msg_type, + msg_len, + sizeof(struct ldp_msg_header)-4); return 0; } @@ -657,6 +734,9 @@ ldp_pdu_print(netdissect_options *ndo, case LDP_MSG_LABEL_MAPPING: case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: + case LDP_MSG_LABEL_REQUEST: + case LDP_MSG_LABEL_RELEASE: + case LDP_MSG_LABEL_ABORT_REQUEST: while(msg_tlen >= 4) { processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) @@ -666,15 +746,6 @@ ldp_pdu_print(netdissect_options *ndo, } break; - /* - * FIXME those are the defined messages that lack a decoder - * you are welcome to contribute code ;-) - */ - - case LDP_MSG_LABEL_REQUEST: - case LDP_MSG_LABEL_RELEASE: - case LDP_MSG_LABEL_ABORT_REQUEST: - default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); @@ -690,6 +761,5 @@ ldp_pdu_print(netdissect_options *ndo, } return pdu_len+4; trunc: - nd_print_trunc(ndo); - return 0; + nd_trunc_longjmp(ndo); }