diff options
Diffstat (limited to 'contrib/tcpdump/print-ospf6.c')
-rw-r--r-- | contrib/tcpdump/print-ospf6.c | 203 |
1 files changed, 129 insertions, 74 deletions
diff --git a/contrib/tcpdump/print-ospf6.c b/contrib/tcpdump/print-ospf6.c index 1100485..fb62b39 100644 --- a/contrib/tcpdump/print-ospf6.c +++ b/contrib/tcpdump/print-ospf6.c @@ -160,17 +160,25 @@ trunc: } static int -ospf6_print_lsaprefix(register const struct lsa6_prefix *lsapp) +ospf6_print_lsaprefix(const u_int8_t *tptr, u_int lsa_length) { + const struct lsa6_prefix *lsapp = (struct lsa6_prefix *)tptr; u_int wordlen; struct in6_addr prefix; - TCHECK(*lsapp); + if (lsa_length < sizeof (*lsapp) - 4) + goto trunc; + lsa_length -= sizeof (*lsapp) - 4; + TCHECK2(*lsapp, sizeof (*lsapp) - 4); wordlen = (lsapp->lsa_p_len + 31) / 32; if (wordlen * 4 > sizeof(struct in6_addr)) { printf(" bogus prefixlen /%d", lsapp->lsa_p_len); goto trunc; } + if (lsa_length < wordlen * 4) + goto trunc; + lsa_length -= wordlen * 4; + TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); memset(&prefix, 0, sizeof(prefix)); memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); printf("\n\t\t%s/%d", ip6addr_string(&prefix), @@ -194,7 +202,6 @@ trunc: static int ospf6_print_lsa(register const struct lsa6 *lsap) { - register const u_char *ls_end, *ls_opt; register const struct rlalink6 *rlp; #if 0 register const struct tos_metric *tosp; @@ -210,34 +217,45 @@ ospf6_print_lsa(register const struct lsa6 *lsap) register const u_int32_t *lp; #endif register u_int prefixes; - register int bytelen, length, lsa_length; + register int bytelen; + register u_int length, lsa_length; u_int32_t flags32; - u_int8_t *tptr; + const u_int8_t *tptr; if (ospf6_print_lshdr(&lsap->ls_hdr)) return (1); TCHECK(lsap->ls_hdr.ls_length); length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); + + /* + * The LSA length includes the length of the header; + * it must have a value that's at least that length. + * If it does, find the length of what follows the + * header. + */ + if (length < sizeof(struct lsa6_hdr)) + return (1); lsa_length = length - sizeof(struct lsa6_hdr); - ls_end = (u_char *)lsap + length; tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr); switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { case LS_TYPE_ROUTER | LS_SCOPE_AREA: + if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); TCHECK(lsap->lsa_un.un_rla.rla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))); - - TCHECK(lsap->lsa_un.un_rla.rla_flags); printf(", RLA-Flags [%s]", bittok2str(ospf6_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags)); - - TCHECK(lsap->lsa_un.un_rla.rla_link); rlp = lsap->lsa_un.un_rla.rla_link; - while (rlp + 1 <= (struct rlalink6 *)ls_end) { + while (lsa_length != 0) { + if (lsa_length < sizeof (*rlp)) + return (1); + lsa_length -= sizeof (*rlp); TCHECK(*rlp); switch (rlp->link_type) { @@ -276,13 +294,20 @@ ospf6_print_lsa(register const struct lsa6 *lsap) break; case LS_TYPE_NETWORK | LS_SCOPE_AREA: + if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); TCHECK(lsap->lsa_un.un_nla.nla_options); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))); + printf("\n\t Connected Routers:"); ap = lsap->lsa_un.un_nla.nla_router; - while ((u_char *)ap < ls_end) { + while (lsa_length != 0) { + if (lsa_length < sizeof (*ap)) + return (1); + lsa_length -= sizeof (*ap); TCHECK(*ap); printf("\n\t\t%s", ipaddr_string(ap)); ++ap; @@ -290,18 +315,27 @@ ospf6_print_lsa(register const struct lsa6 *lsap) break; case LS_TYPE_INTER_AP | LS_SCOPE_AREA: + if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); printf(", metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); - lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix; - while (lsapp + sizeof(lsapp) <= (struct lsa6_prefix *)ls_end) { - bytelen = ospf6_print_lsaprefix(lsapp); - if (bytelen) + + tptr = (u_int8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; + while (lsa_length != 0) { + bytelen = ospf6_print_lsaprefix(tptr, lsa_length); + if (bytelen < 0) goto trunc; - lsapp = (struct lsa6_prefix *)(((u_char *)lsapp) + bytelen); + lsa_length -= bytelen; + tptr += bytelen; } break; - case LS_SCOPE_AS | LS_TYPE_ASE: + + case LS_TYPE_ASE | LS_SCOPE_AS: + if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); TCHECK(lsap->lsa_un.un_asla.asla_metric); flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); printf("\n\t Flags [%s]", @@ -309,48 +343,63 @@ ospf6_print_lsa(register const struct lsa6 *lsap) printf(" metric %u", EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & ASLA_MASK_METRIC); - lsapp = lsap->lsa_un.un_asla.asla_prefix; - bytelen = ospf6_print_lsaprefix(lsapp); + + tptr = (u_int8_t *)lsap->lsa_un.un_asla.asla_prefix; + lsapp = (struct lsa6_prefix *)tptr; + bytelen = ospf6_print_lsaprefix(tptr, lsa_length); if (bytelen < 0) goto trunc; - if ((ls_opt = (u_char *)(((u_char *)lsapp) + bytelen)) < ls_end) { - struct in6_addr *fwdaddr6; + lsa_length -= bytelen; + tptr += bytelen; - if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { - fwdaddr6 = (struct in6_addr *)ls_opt; - TCHECK(*fwdaddr6); - printf(" forward %s", - ip6addr_string(fwdaddr6)); - - ls_opt += sizeof(struct in6_addr); - } - - if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { - TCHECK(*(u_int32_t *)ls_opt); - printf(" tag %s", - ipaddr_string((u_int32_t *)ls_opt)); + if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { + struct in6_addr *fwdaddr6; - ls_opt += sizeof(u_int32_t); - } + fwdaddr6 = (struct in6_addr *)tptr; + if (lsa_length < sizeof (*fwdaddr6)) + return (1); + lsa_length -= sizeof (*fwdaddr6); + TCHECK(*fwdaddr6); + printf(" forward %s", + ip6addr_string(fwdaddr6)); + tptr += sizeof(*fwdaddr6); + } - if (lsapp->lsa_p_metric) { - TCHECK(*(u_int32_t *)ls_opt); - printf(" RefLSID: %s", - ipaddr_string((u_int32_t *)ls_opt)); + if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { + if (lsa_length < sizeof (u_int32_t)) + return (1); + lsa_length -= sizeof (u_int32_t); + TCHECK(*(u_int32_t *)tptr); + printf(" tag %s", + ipaddr_string((u_int32_t *)tptr)); + tptr += sizeof(u_int32_t); + } - ls_opt += sizeof(u_int32_t); - } + if (lsapp->lsa_p_metric) { + if (lsa_length < sizeof (u_int32_t)) + return (1); + lsa_length -= sizeof (u_int32_t); + TCHECK(*(u_int32_t *)tptr); + printf(" RefLSID: %s", + ipaddr_string((u_int32_t *)tptr)); + tptr += sizeof(u_int32_t); } break; case LS_TYPE_LINK: /* Link LSA */ llsap = &lsap->lsa_un.un_llsa; - TCHECK(llsap->llsa_options); + if (lsa_length < sizeof (llsap->llsa_priandopt)) + return (1); + lsa_length -= sizeof (llsap->llsa_priandopt); + TCHECK(llsap->llsa_priandopt); printf("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", EXTRACT_32BITS(&llsap->llsa_options))); - TCHECK(llsap->llsa_nprefix); + + if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) + return (1); + lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); printf("\n\t Priority %d, Link-local address %s, Prefixes %d:", llsap->llsa_priority, @@ -358,57 +407,63 @@ ospf6_print_lsa(register const struct lsa6 *lsap) prefixes); tptr = (u_int8_t *)llsap->llsa_prefix; - while (prefixes > 0) { - lsapp = (struct lsa6_prefix *)tptr; - if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) { - goto trunc; - } - prefixes--; - tptr += bytelen; - } + while (prefixes > 0) { + bytelen = ospf6_print_lsaprefix(tptr, lsa_length); + if (bytelen < 0) + goto trunc; + prefixes--; + lsa_length -= bytelen; + tptr += bytelen; + } break; case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: /* Intra-Area-Prefix LSA */ + if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); ospf6_print_ls_type( EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), &lsap->lsa_un.un_intra_ap.intra_ap_lsid); + + if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) + return (1); + lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); printf("\n\t Prefixes %d:", prefixes); - tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; - - while (prefixes > 0) { - lsapp = (struct lsa6_prefix *)tptr; - if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) { - goto trunc; - } - prefixes--; - tptr += bytelen; - } + tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; + while (prefixes > 0) { + bytelen = ospf6_print_lsaprefix(tptr, lsa_length); + if (bytelen < 0) + goto trunc; + prefixes--; + lsa_length -= bytelen; + tptr += bytelen; + } break; case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: if (ospf_print_grace_lsa(tptr, lsa_length) == -1) { return 1; } - - break; + break; case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: - if (ospf_print_te_lsa(tptr, lsa_length) == -1) { - return 1; - } - break; + if (ospf_print_te_lsa(tptr, lsa_length) == -1) { + return 1; + } + break; default: - if(!print_unknown_data(tptr, - "\n\t ", - lsa_length)) { - return (1); - } + if(!print_unknown_data(tptr, + "\n\t ", + lsa_length)) { + return (1); + } + break; } return (0); |