X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/a9e42111da1bb839deccb2f393ee4bce9561c2d6..HEAD:/print-ldp.c diff --git a/print-ldp.c b/print-ldp.c index f387affd..bdf9a138 100644 --- a/print-ldp.c +++ b/print-ldp.c @@ -10,18 +10,17 @@ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) * and Steinar Haug (sthaug@nethelp.no) */ -#define NETDISSECT_REWORKED -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +/* \summary: Label Distribution Protocol (LDP) printer */ -#include +#include -#include "interface.h" +#include "netdissect-stdinc.h" + +#include "netdissect.h" #include "extract.h" #include "addrtoname.h" @@ -44,10 +43,10 @@ */ struct ldp_common_header { - uint8_t version[2]; - uint8_t pdu_length[2]; - uint8_t lsr_id[4]; - uint8_t label_space[2]; + nd_uint16_t version; + nd_uint16_t pdu_length; + nd_ipv4 lsr_id; + nd_uint16_t label_space; }; #define LDP_VERSION 1 @@ -77,9 +76,9 @@ struct ldp_common_header { */ struct ldp_msg_header { - uint8_t type[2]; - uint8_t length[2]; - uint8_t id[4]; + nd_uint16_t type; + nd_uint16_t length; + nd_uint32_t id; }; #define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) @@ -140,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" }, @@ -163,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} }; @@ -209,7 +243,17 @@ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { { 0, NULL} }; -static int ldp_pdu_print(netdissect_options *, register 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 @@ -228,120 +272,135 @@ static int ldp_pdu_print(netdissect_options *, register const u_char *); * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define TLV_TCHECK(minlen) \ - ND_TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; - -static int +static u_int ldp_tlv_print(netdissect_options *ndo, - register const u_char *tptr, - u_short msg_tlen) { - + const u_char *tptr, + u_int msg_tlen) +{ struct ldp_tlv_header { - uint8_t type[2]; - uint8_t length[2]; + nd_uint16_t type; + nd_uint16_t length; }; 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; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; - ND_TCHECK(*ldp_tlv_header); - tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); - if (tlv_len + 4 > msg_tlen) { - ND_PRINT((ndo, "\n\t\t TLV contents go past end of message")); + ND_TCHECK_SIZE(ldp_tlv_header); + tlv_len=GET_BE_U_2(ldp_tlv_header->length); + if (tlv_len + 4U > msg_tlen) { + ND_PRINT("\n\t\t TLV contents go past end of message"); return 0; } tlv_tlen=tlv_len; - tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); + tlv_type=LDP_MASK_TLV_TYPE(GET_BE_U_2(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ - ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", + ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", tok2str(ldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len, - LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", - LDP_MASK_F_BIT(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "do" : "don't")); + LDP_MASK_U_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore", + LDP_MASK_F_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't"); tptr+=sizeof(struct ldp_tlv_header); switch(tlv_type) { case LDP_TLV_COMMON_HELLO: - TLV_TCHECK(4); - ND_PRINT((ndo, "\n\t Hold Time: %us, Flags: [%s Hello%s]", - EXTRACT_16BITS(tptr), - (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", - (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "")); + 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", + (GET_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : ""); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: - TLV_TCHECK(4); - ND_PRINT((ndo, "\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; -#ifdef INET6 case LDP_TLV_IPV6_TRANSPORT_ADDR: - TLV_TCHECK(16); - ND_PRINT((ndo, "\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; -#endif case LDP_TLV_CONFIG_SEQ_NUMBER: - TLV_TCHECK(4); - ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_32BITS(tptr))); + 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); - af = EXTRACT_16BITS(tptr); + 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((ndo, "\n\t Address Family: %s, addresses", - tok2str(af_values, "Unknown (%u)", af))); + ND_PRINT("\n\t Address Family: %s, addresses", + tok2str(af_values, "Unknown (%u)", af)); switch (af) { - case AFNUM_INET: - while(tlv_tlen >= sizeof(struct in_addr)) { - ND_TCHECK2(*tptr, sizeof(struct in_addr)); - ND_PRINT((ndo, " %s", ipaddr_string(ndo, tptr))); - tlv_tlen-=sizeof(struct in_addr); - tptr+=sizeof(struct in_addr); + case AFNUM_IP: + while(tlv_tlen >= sizeof(nd_ipv4)) { + ND_PRINT(" %s", GET_IPADDR_STRING(tptr)); + tlv_tlen-=sizeof(nd_ipv4); + tptr+=sizeof(nd_ipv4); } break; -#ifdef INET6 - case AFNUM_INET6: - while(tlv_tlen >= sizeof(struct in6_addr)) { - ND_TCHECK2(*tptr, sizeof(struct in6_addr)); - ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr))); - tlv_tlen-=sizeof(struct in6_addr); - tptr+=sizeof(struct in6_addr); + case AFNUM_IP6: + while(tlv_tlen >= sizeof(nd_ipv6)) { + ND_PRINT(" %s", GET_IP6ADDR_STRING(tptr)); + tlv_tlen-=sizeof(nd_ipv6); + tptr+=sizeof(nd_ipv6); } break; -#endif default: /* unknown AF */ break; } 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_PRINT((ndo, "\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", - EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), - (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", - (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" - )); + 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 + 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); - fec_type = *tptr; - ND_PRINT((ndo, "\n\t %s FEC (0x%02x)", + 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), - fec_type)); + fec_type); tptr+=1; tlv_tlen-=1; @@ -350,68 +409,68 @@ ldp_tlv_print(netdissect_options *ndo, case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: - TLV_TCHECK(2); - af = EXTRACT_16BITS(tptr); - tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; - tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; - if (af == AFNUM_INET) { + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 2); + af = GET_BE_U_2(tptr); + tptr+=2; + tlv_tlen-=2; + if (af == AFNUM_IP) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) - ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)")); + ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) - ND_PRINT((ndo, ": IPv4 prefix (invalid length)")); + ND_PRINT(": IPv4 prefix (invalid length)"); else - ND_PRINT((ndo, ": IPv4 prefix %s", buf)); - } -#ifdef INET6 - else if (af == AFNUM_INET6) { + ND_PRINT(": IPv4 prefix %s", buf); + } else if (af == AFNUM_IP6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) - ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)")); + ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) - ND_PRINT((ndo, ": IPv6 prefix (invalid length)")); + ND_PRINT(": IPv6 prefix (invalid length)"); else - ND_PRINT((ndo, ": IPv6 prefix %s", buf)); - } -#endif - else - ND_PRINT((ndo, ": Address family %u prefix", af)); + ND_PRINT(": IPv6 prefix %s", buf); + } else + ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: + /* + * We assume the type was supposed to be one of the MPLS + * Pseudowire Types. + */ + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 7); + vc_info_len = GET_U_1(tptr + 2); + /* * According to RFC 4908, the VC info Length field can be zero, * in which case not only are there no interface parameters, * there's no VC ID. */ - TLV_TCHECK(7); - vc_info_len = *(tptr+2); - if (vc_info_len == 0) { - ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u", - tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), - EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", - EXTRACT_32BITS(tptr+3), - vc_info_len)); + ND_PRINT(": %s, %scontrol word, group-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 ", + GET_BE_U_4(tptr + 3), + vc_info_len); break; } /* Make sure we have the VC ID as well */ - TLV_TCHECK(11); - ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", - tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), - EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", - EXTRACT_32BITS(tptr+3), - EXTRACT_32BITS(tptr+7), - vc_info_len)); + 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 ", + GET_BE_U_4(tptr + 3), + GET_BE_U_4(tptr + 7), + vc_info_len); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ - ND_PRINT((ndo, " (invalid, < 4")); + ND_PRINT(" (invalid, < 4"); return(tlv_len+4); /* Type & Length fields not included */ } vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ @@ -419,39 +478,38 @@ 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 = *tptr; - vc_info_tlv_len = *(tptr+1); + vc_info_tlv_type = GET_U_1(tptr); + vc_info_tlv_len = GET_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; - ND_PRINT((ndo, "\n\t\tInterface Parameter: %s (0x%02x), len %u", + ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u", tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), vc_info_tlv_type, - vc_info_tlv_len)); + vc_info_tlv_len); switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: - ND_PRINT((ndo, ": %u", EXTRACT_16BITS(tptr+2))); + ND_PRINT(": %u", GET_BE_U_2(tptr + 2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: - ND_PRINT((ndo, ": ")); - for (idx = 2; idx < vc_info_tlv_len; idx++) - safeputchar(ndo, *(tptr + idx)); + ND_PRINT(": "); + nd_printjn(ndo, tptr + 2, vc_info_tlv_len - 2); break; case LDP_FEC_MARTINI_IFPARM_VCCV: - ND_PRINT((ndo, "\n\t\t Control Channels (0x%02x) = [%s]", - *(tptr+2), - bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2)))); - ND_PRINT((ndo, "\n\t\t CV Types (0x%02x) = [%s]", - *(tptr+3), - bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(tptr+3)))); + ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]", + GET_U_1((tptr + 2)), + bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", GET_U_1((tptr + 2)))); + ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]", + GET_U_1((tptr + 3)), + bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", GET_U_1((tptr + 3)))); break; default: @@ -468,56 +526,71 @@ ldp_tlv_print(netdissect_options *ndo, break; case LDP_TLV_GENERIC_LABEL: - TLV_TCHECK(4); - ND_PRINT((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff)); + 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); - ui = EXTRACT_32BITS(tptr); + ND_ICHECKMSG_U("tlv length", tlv_tlen, <, 10); + ui = GET_BE_U_4(tptr); tptr+=4; - ND_PRINT((ndo, "\n\t Status: 0x%02x, Flags: [%s and %s forward]", - ui&0x3fffffff, - ui&0x80000000 ? "Fatal error" : "Advisory Notification", - ui&0x40000000 ? "do" : "don't")); - ui = EXTRACT_32BITS(tptr); + 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((ndo, ", causing Message ID: 0x%08x", 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); - ft_flags = EXTRACT_16BITS(tptr); - ND_PRINT((ndo, "\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", + 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 ", ft_flags&0x8 ? "" : "Don't ", ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", - ft_flags&0x1 ? "" : "Don't ")); + ft_flags&0x1 ? "" : "Don't "); + /* 16 bits (FT Flags) + 16 bits (Reserved) */ tptr+=4; - ui = EXTRACT_32BITS(tptr); + ui = GET_BE_U_4(tptr); if (ui) - ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui)); + ND_PRINT(", Reconnect Timeout: %ums", ui); tptr+=4; - ui = EXTRACT_32BITS(tptr); + ui = GET_BE_U_4(tptr); if (ui) - ND_PRINT((ndo, ", Recovery Time: %ums", ui)); + 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_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(tptr))); + 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,113 +608,120 @@ ldp_tlv_print(netdissect_options *ndo, return(tlv_len+4); /* Type & Length fields not included */ trunc: - ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); - return 0; + nd_trunc_longjmp(ndo); -badtlv: - ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV")); +invalid: + nd_print_invalid(ndo); return(tlv_len+4); /* Type & Length fields not included */ } void ldp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { + const u_char *pptr, u_int len) +{ + u_int processed; - 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, - register const u_char *pptr) { - + const u_char *pptr) +{ const struct ldp_common_header *ldp_com_header; const struct ldp_msg_header *ldp_msg_header; const u_char *tptr,*msg_tptr; u_short tlen; - u_short pdu_len,msg_len,msg_type,msg_tlen; + u_short pdu_len,msg_len,msg_type; + u_int msg_tlen; int hexdump,processed; ldp_com_header = (const struct ldp_common_header *)pptr; - ND_TCHECK(*ldp_com_header); + ND_TCHECK_SIZE(ldp_com_header); /* * Sanity checking of the header. */ - if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { - ND_PRINT((ndo, "%sLDP version %u packet not supported", + if (GET_BE_U_2(ldp_com_header->version) != LDP_VERSION) { + ND_PRINT("%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", - EXTRACT_16BITS(&ldp_com_header->version))); + GET_BE_U_2(ldp_com_header->version)); return 0; } - pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); - if (pdu_len < sizeof(const struct ldp_common_header)-4) { + 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((ndo, "%sLDP, pdu-length: %u (too short, < %u)", - (ndo->ndo_vflag < 1) ? "" : "\n\t", - pdu_len, - (u_int)(sizeof(const 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((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", + 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), - EXTRACT_16BITS(&ldp_com_header->label_space), - pdu_len)); + GET_IPADDR_STRING(ldp_com_header->lsr_id), + GET_BE_U_2(ldp_com_header->label_space), + pdu_len); /* bail out if non-verbose */ if (ndo->ndo_vflag < 1) return 0; /* ok they seem to want to know everything - lets fully decode it */ - tptr = pptr + sizeof(const struct ldp_common_header); - tlen = pdu_len - (sizeof(const struct ldp_common_header)-4); /* Type & Length fields not included */ + 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_TCHECK2(*tptr, sizeof(struct ldp_msg_header)); + ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; - msg_len=EXTRACT_16BITS(ldp_msg_header->length); - msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); + msg_len=GET_BE_U_2(ldp_msg_header->length); + msg_type=LDP_MASK_MSG_TYPE(GET_BE_U_2(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ - ND_PRINT((ndo, "\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; } /* FIXME vendor private / experimental check */ - ND_PRINT((ndo, "\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", + ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, - EXTRACT_32BITS(&ldp_msg_header->id), - LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore")); + GET_BE_U_4(ldp_msg_header->id), + LDP_MASK_U_BIT(GET_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore"); msg_tptr=tptr+sizeof(struct ldp_msg_header); msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ - ND_TCHECK2(*tptr, msg_len); + ND_TCHECK_LEN(tptr, msg_len); hexdump=FALSE; switch(msg_type) { @@ -654,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) @@ -663,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); @@ -687,13 +761,5 @@ ldp_pdu_print(netdissect_options *ndo, } return pdu_len+4; trunc: - ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); - return 0; + nd_trunc_longjmp(ndo); } - -/* - * Local Variables: - * c-style: whitesmith - * c-basic-offset: 8 - * End: - */