X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/95d8b612de327d61287f3bdf4c7c652066c29e3c..25d016f61a3b38e9c048090980c6921b30d047f3:/print-ldp.c diff --git a/print-ldp.c b/print-ldp.c index ede1653a..bff0455f 100644 --- a/print-ldp.c +++ b/print-ldp.c @@ -14,11 +14,6 @@ * and Steinar Haug (sthaug@nethelp.no) */ -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.19 2006-03-28 07:06:21 hannes Exp $"; -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -91,8 +86,8 @@ struct ldp_msg_header { u_int8_t id[4]; }; -#define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) -#define LDP_MASK_U_BIT(x) ((x)&0x8000) +#define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) +#define LDP_MASK_U_BIT(x) ((x)&0x8000) #define LDP_MSG_NOTIF 0x0001 #define LDP_MSG_HELLO 0x0100 @@ -126,8 +121,8 @@ static const struct tok ldp_msg_values[] = { { 0, NULL} }; -#define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff) -#define LDP_MASK_F_BIT(x) ((x)&0x4000) +#define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff) +#define LDP_MASK_F_BIT(x) ((x)&0x4000) #define LDP_TLV_FEC 0x0100 #define LDP_TLV_ADDRESS_LIST 0x0101 @@ -180,7 +175,7 @@ static const struct tok ldp_tlv_values[] = { #define LDP_FEC_WILDCARD 0x01 #define LDP_FEC_PREFIX 0x02 #define LDP_FEC_HOSTADDRESS 0x03 -/* From draft-martini-l2circuit-trans-mpls-13.txt */ +/* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */ #define LDP_FEC_MARTINI_VC 0x80 static const struct tok ldp_fec_values[] = { @@ -218,13 +213,10 @@ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { { 0, NULL} }; -#define FALSE 0 -#define TRUE 1 - int ldp_msg_print(register const u_char *); int ldp_tlv_print(register const u_char *); - -/* + +/* * ldp tlv header * * 0 1 2 3 @@ -241,6 +233,9 @@ int ldp_tlv_print(register const u_char *); * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +#define TLV_TCHECK(minlen) \ + TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; + int ldp_tlv_print(register const u_char *tptr) { @@ -256,7 +251,7 @@ ldp_tlv_print(register const u_char *tptr) { char buf[100]; int i; - ldp_tlv_header = (const struct ldp_tlv_header *)tptr; + ldp_tlv_header = (const struct ldp_tlv_header *)tptr; tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); @@ -276,6 +271,7 @@ ldp_tlv_print(register const u_char *tptr) { switch(tlv_type) { case LDP_TLV_COMMON_HELLO: + TLV_TCHECK(4); printf("\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_16BITS(tptr), (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", @@ -283,18 +279,22 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_IPV4_TRANSPORT_ADDR: + TLV_TCHECK(4); printf("\n\t IPv4 Transport Address: %s", ipaddr_string(tptr)); break; #ifdef INET6 case LDP_TLV_IPV6_TRANSPORT_ADDR: + TLV_TCHECK(16); printf("\n\t IPv6 Transport Address: %s", ip6addr_string(tptr)); break; #endif case LDP_TLV_CONFIG_SEQ_NUMBER: + TLV_TCHECK(4); printf("\n\t Sequence Number: %u", EXTRACT_32BITS(tptr)); break; case LDP_TLV_ADDRESS_LIST: + TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_16BITS(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; @@ -303,17 +303,19 @@ ldp_tlv_print(register const u_char *tptr) { switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { + TCHECK2(*tptr, sizeof(struct in_addr)); printf(" %s",ipaddr_string(tptr)); tlv_tlen-=sizeof(struct in_addr); - tptr+=sizeof(struct in_addr); + tptr+=sizeof(struct in_addr); } break; #ifdef INET6 case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { + TCHECK2(*tptr, sizeof(struct in6_addr)); printf(" %s",ip6addr_string(tptr)); tlv_tlen-=sizeof(struct in6_addr); - tptr+=sizeof(struct in6_addr); + tptr+=sizeof(struct in6_addr); } break; #endif @@ -324,6 +326,7 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_COMMON_SESSION: + TLV_TCHECK(8); printf("\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", @@ -332,50 +335,86 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_FEC: + TLV_TCHECK(1); fec_type = *tptr; printf("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; + tlv_tlen-=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: + TLV_TCHECK(2); af = EXTRACT_16BITS(tptr); - tptr+=2; + tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; + tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { - i=decode_prefix4(tptr,buf,sizeof(buf)); - printf(": IPv4 prefix %s",buf); + i=decode_prefix4(tptr,tlv_tlen,buf,sizeof(buf)); + if (i == -2) + goto trunc; + if (i == -3) + printf(": IPv4 prefix (goes past end of TLV)"); + else if (i == -1) + printf(": IPv4 prefix (invalid length)"); + else + printf(": IPv4 prefix %s",buf); } #ifdef INET6 else if (af == AFNUM_INET6) { - i=decode_prefix6(tptr,buf,sizeof(buf)); - printf(": IPv6 prefix %s",buf); + i=decode_prefix6(tptr,tlv_tlen,buf,sizeof(buf)); + if (i == -2) + goto trunc; + if (i == -3) + printf(": IPv4 prefix (goes past end of TLV)"); + else if (i == -1) + printf(": IPv6 prefix (invalid length)"); + else + printf(": IPv6 prefix %s",buf); } #endif + else + printf(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: - if (!TTEST2(*tptr, 11)) - goto trunc; + /* + * 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) { + printf(": %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); + break; + } + + /* Make sure we have the VC ID as well */ + TLV_TCHECK(11); printf(": %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); + if (vc_info_len < 4) + goto trunc; /* minimum 4, for the VC ID */ + vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ - if (vc_info_len == 0) /* infinite loop protection */ - break; - + /* Skip past the fixed information and the VC ID */ tptr+=11; - if (!TTEST2(*tptr, vc_info_len)) - goto trunc; + tlv_tlen-=11; + TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = *tptr; @@ -411,7 +450,7 @@ ldp_tlv_print(register const u_char *tptr) { break; default: - print_unknown_data(tptr+2,"\n\t\t ",vc_info_tlv_len-2); + print_unknown_data(gndo,tptr+2,"\n\t\t ",vc_info_tlv_len-2); break; } @@ -424,10 +463,12 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_GENERIC_LABEL: + TLV_TCHECK(4); printf("\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff); break; case LDP_TLV_STATUS: + TLV_TCHECK(8); ui = EXTRACT_32BITS(tptr); tptr+=4; printf("\n\t Status: 0x%02x, Flags: [%s and %s forward]", @@ -441,6 +482,7 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_FT_SESSION: + TLV_TCHECK(8); ft_flags = EXTRACT_16BITS(tptr); printf("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", @@ -459,6 +501,7 @@ ldp_tlv_print(register const u_char *tptr) { break; case LDP_TLV_MTU: + TLV_TCHECK(2); printf("\n\t MTU: %u", EXTRACT_16BITS(tptr)); break; @@ -481,14 +524,18 @@ ldp_tlv_print(register const u_char *tptr) { default: if (vflag <= 1) - print_unknown_data(tptr,"\n\t ",tlv_tlen); + print_unknown_data(gndo,tptr,"\n\t ",tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ - + trunc: printf("\n\t\t packet exceeded snapshot"); return 0; + +badtlv: + printf("\n\t\t TLV contents go past end of TLV"); + return(tlv_len+4); /* Type & Length fields not included */ } void @@ -537,7 +584,7 @@ ldp_msg_print(register const u_char *pptr) { EXTRACT_16BITS(&ldp_com_header->label_space), pdu_len); - /* bail out if non-verbose */ + /* bail out if non-verbose */ if (vflag < 1) return 0; @@ -549,8 +596,7 @@ ldp_msg_print(register const u_char *pptr) { while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ - if (!TTEST2(*tptr, sizeof(struct ldp_msg_header))) - goto trunc; + TCHECK2(*tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_16BITS(ldp_msg_header->length); @@ -573,12 +619,11 @@ ldp_msg_print(register const u_char *pptr) { msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ - if (!TTEST2(*tptr, msg_len)) - goto trunc; + TCHECK2(*tptr, msg_len); hexdump=FALSE; switch(msg_type) { - + case LDP_MSG_NOTIF: case LDP_MSG_HELLO: case LDP_MSG_INIT: @@ -607,12 +652,12 @@ ldp_msg_print(register const u_char *pptr) { default: if (vflag <= 1) - print_unknown_data(msg_tptr,"\n\t ",msg_tlen); + print_unknown_data(gndo,msg_tptr,"\n\t ",msg_tlen); break; } /* do we want to see an additionally hexdump ? */ if (vflag > 1 || hexdump==TRUE) - print_unknown_data(tptr+sizeof(sizeof(struct ldp_msg_header)),"\n\t ", + print_unknown_data(gndo,tptr+sizeof(struct ldp_msg_header),"\n\t ", msg_len); tptr += msg_len+4; @@ -624,3 +669,9 @@ trunc: return 0; } +/* + * Local Variables: + * c-style: whitesmith + * c-basic-offset: 8 + * End: + */