X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/bbedebc666a341d8e14922dce37a92766400c798..6ec714988caac3bf9fedc766ae51a2248896ec80:/print-ldp.c diff --git a/print-ldp.c b/print-ldp.c index 98256659..ab4f6c63 100644 --- a/print-ldp.c +++ b/print-ldp.c @@ -10,18 +10,19 @@ * 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 +/* \summary: Label Distribution Protocol (LDP) printer */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include +#include -#include "interface.h" +#include "netdissect.h" #include "extract.h" #include "addrtoname.h" @@ -44,10 +45,10 @@ */ struct ldp_common_header { - u_int8_t version[2]; - u_int8_t pdu_length[2]; - u_int8_t lsr_id[4]; - u_int8_t label_space[2]; + uint8_t version[2]; + uint8_t pdu_length[2]; + uint8_t lsr_id[4]; + uint8_t label_space[2]; }; #define LDP_VERSION 1 @@ -77,9 +78,9 @@ struct ldp_common_header { */ struct ldp_msg_header { - u_int8_t type[2]; - u_int8_t length[2]; - u_int8_t id[4]; + uint8_t type[2]; + uint8_t length[2]; + uint8_t id[4]; }; #define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) @@ -209,7 +210,7 @@ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { { 0, NULL} }; -static int ldp_msg_print(netdissect_options *, register const u_char *); +static int ldp_pdu_print(netdissect_options *, const u_char *); /* * ldp tlv header @@ -229,15 +230,16 @@ static int ldp_msg_print(netdissect_options *, register const u_char *); */ #define TLV_TCHECK(minlen) \ - ND_TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; + ND_TCHECK_LEN(tptr, minlen); if (tlv_tlen < minlen) goto badtlv; static int ldp_tlv_print(netdissect_options *ndo, - register const u_char *tptr) { - + const u_char *tptr, + u_short msg_tlen) +{ struct ldp_tlv_header { - u_int8_t type[2]; - u_int8_t length[2]; + uint8_t type[2]; + uint8_t length[2]; }; const struct ldp_tlv_header *ldp_tlv_header; @@ -248,9 +250,14 @@ ldp_tlv_print(netdissect_options *ndo, int i; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; - tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); + ND_TCHECK(*ldp_tlv_header); + tlv_len=EXTRACT_BE_U_2(ldp_tlv_header->length); + if (tlv_len + 4 > msg_tlen) { + ND_PRINT((ndo, "\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(EXTRACT_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]", @@ -259,8 +266,8 @@ ldp_tlv_print(netdissect_options *ndo, 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(EXTRACT_BE_U_2(&ldp_tlv_header->type)) ? "continue processing" : "ignore", + LDP_MASK_F_BIT(EXTRACT_BE_U_2(&ldp_tlv_header->type)) ? "do" : "don't")); tptr+=sizeof(struct ldp_tlv_header); @@ -269,29 +276,27 @@ ldp_tlv_print(netdissect_options *ndo, 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" : "")); + EXTRACT_BE_U_2(tptr), + (EXTRACT_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", + (EXTRACT_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))); 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))); break; -#endif case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); - ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_32BITS(tptr))); + ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_BE_U_4(tptr))); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); - af = EXTRACT_16BITS(tptr); + af = EXTRACT_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", @@ -299,22 +304,20 @@ ldp_tlv_print(netdissect_options *ndo, switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { - ND_TCHECK2(*tptr, sizeof(struct in_addr)); + ND_TCHECK_LEN(tptr, sizeof(struct in_addr)); ND_PRINT((ndo, " %s", ipaddr_string(ndo, tptr))); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } break; -#ifdef INET6 case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { - ND_TCHECK2(*tptr, sizeof(struct in6_addr)); + ND_TCHECK_LEN(tptr, sizeof(struct in6_addr)); ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr))); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } break; -#endif default: /* unknown AF */ break; @@ -324,15 +327,15 @@ ldp_tlv_print(netdissect_options *ndo, 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" + EXTRACT_BE_U_2(tptr), EXTRACT_BE_U_2(tptr + 2), + (EXTRACT_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", + (EXTRACT_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" )); break; case LDP_TLV_FEC: TLV_TCHECK(1); - fec_type = *tptr; + fec_type = EXTRACT_U_1(tptr); ND_PRINT((ndo, "\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type)); @@ -345,7 +348,7 @@ ldp_tlv_print(netdissect_options *ndo, break; case LDP_FEC_PREFIX: TLV_TCHECK(2); - af = EXTRACT_16BITS(tptr); + af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { @@ -359,7 +362,6 @@ ldp_tlv_print(netdissect_options *ndo, else ND_PRINT((ndo, ": IPv4 prefix %s", buf)); } -#ifdef INET6 else if (af == AFNUM_INET6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) @@ -371,26 +373,29 @@ ldp_tlv_print(netdissect_options *ndo, else ND_PRINT((ndo, ": IPv6 prefix %s", buf)); } -#endif else ND_PRINT((ndo, ": 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. + */ + TLV_TCHECK(7); + vc_info_len = EXTRACT_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), + tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), + EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", + EXTRACT_BE_U_4(tptr + 3), vc_info_len)); break; } @@ -398,13 +403,16 @@ ldp_tlv_print(netdissect_options *ndo, /* 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)); - if (vc_info_len < 4) - goto trunc; /* minimum 4, for the VC ID */ + tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), + EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", + EXTRACT_BE_U_4(tptr + 3), + EXTRACT_BE_U_4(tptr + 7), + vc_info_len)); + if (vc_info_len < 4) { + /* minimum 4, for the VC ID */ + ND_PRINT((ndo, " (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 */ /* Skip past the fixed information and the VC ID */ @@ -413,8 +421,8 @@ ldp_tlv_print(netdissect_options *ndo, TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { - vc_info_tlv_type = *tptr; - vc_info_tlv_len = *(tptr+1); + vc_info_tlv_type = EXTRACT_U_1(tptr); + vc_info_tlv_len = EXTRACT_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) @@ -427,22 +435,22 @@ ldp_tlv_print(netdissect_options *ndo, switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: - ND_PRINT((ndo, ": %u", EXTRACT_16BITS(tptr+2))); + ND_PRINT((ndo, ": %u", EXTRACT_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)); + safeputchar(ndo, EXTRACT_U_1(tptr + idx)); 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)))); + EXTRACT_U_1((tptr + 2)), + bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", EXTRACT_U_1((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)))); + EXTRACT_U_1((tptr + 3)), + bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", EXTRACT_U_1((tptr + 3))))); break; default: @@ -460,18 +468,18 @@ ldp_tlv_print(netdissect_options *ndo, case LDP_TLV_GENERIC_LABEL: TLV_TCHECK(4); - ND_PRINT((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff)); + ND_PRINT((ndo, "\n\t Label: %u", EXTRACT_BE_U_4(tptr) & 0xfffff)); break; case LDP_TLV_STATUS: TLV_TCHECK(8); - ui = EXTRACT_32BITS(tptr); + ui = EXTRACT_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); + ui = EXTRACT_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui)); @@ -479,7 +487,7 @@ ldp_tlv_print(netdissect_options *ndo, case LDP_TLV_FT_SESSION: TLV_TCHECK(8); - ft_flags = EXTRACT_16BITS(tptr); + ft_flags = EXTRACT_BE_U_2(tptr); ND_PRINT((ndo, "\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", ft_flags&0x8 ? "" : "Don't ", @@ -487,18 +495,18 @@ ldp_tlv_print(netdissect_options *ndo, ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't ")); tptr+=4; - ui = EXTRACT_32BITS(tptr); + ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui)); tptr+=4; - ui = EXTRACT_32BITS(tptr); + ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT((ndo, ", Recovery Time: %ums", ui)); break; case LDP_TLV_MTU: TLV_TCHECK(2); - ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(tptr))); + ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_BE_U_2(tptr))); break; @@ -536,11 +544,11 @@ badtlv: void ldp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + const u_char *pptr, u_int len) +{ int processed; while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { - processed = ldp_msg_print(ndo, pptr); + processed = ldp_pdu_print(ndo, pptr); if (processed == 0) return; len -= processed; @@ -549,9 +557,9 @@ ldp_print(netdissect_options *ndo, } static int -ldp_msg_print(netdissect_options *ndo, - register const u_char *pptr) { - +ldp_pdu_print(netdissect_options *ndo, + 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; @@ -559,26 +567,34 @@ ldp_msg_print(netdissect_options *ndo, u_short pdu_len,msg_len,msg_type,msg_tlen; int hexdump,processed; - tptr=pptr; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK(*ldp_com_header); /* * Sanity checking of the header. */ - if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { + if (EXTRACT_BE_U_2(&ldp_com_header->version) != LDP_VERSION) { ND_PRINT((ndo, "%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", - EXTRACT_16BITS(&ldp_com_header->version))); + EXTRACT_BE_U_2(&ldp_com_header->version))); return 0; } + pdu_len = EXTRACT_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(struct ldp_common_header)-4))); + return 0; + } + /* print the LSR-ID, label-space & length */ - pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); ND_PRINT((ndo, "%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), + EXTRACT_BE_U_2(&ldp_com_header->label_space), pdu_len)); /* bail out if non-verbose */ @@ -586,18 +602,29 @@ ldp_msg_print(netdissect_options *ndo, return 0; /* ok they seem to want to know everything - lets fully decode it */ - tlen=pdu_len; - - tptr += sizeof(const struct ldp_common_header); - tlen -= 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) { /* 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=EXTRACT_BE_U_2(ldp_msg_header->length); + msg_type=LDP_MASK_MSG_TYPE(EXTRACT_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))); + 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]", @@ -606,17 +633,14 @@ ldp_msg_print(netdissect_options *ndo, 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")); - - if (msg_len == 0) /* infinite loop protection */ - return 0; + EXTRACT_BE_U_4(&ldp_msg_header->id), + LDP_MASK_U_BIT(EXTRACT_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 */ + 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) { @@ -630,7 +654,7 @@ ldp_msg_print(netdissect_options *ndo, case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: while(msg_tlen >= 4) { - processed = ldp_tlv_print(ndo, msg_tptr); + processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) break; msg_tlen-=processed;