--- embedaddon/quagga/isisd/isis_tlv.c 2012/10/09 09:22:28 1.1.1.2 +++ embedaddon/quagga/isisd/isis_tlv.c 2013/07/21 23:54:39 1.1.1.3 @@ -117,7 +117,7 @@ parse_tlvs (char *areatag, u_char * stream, int size, #endif /* HAVE_IPV6 */ u_char virtual; int value_len, retval = ISIS_OK; - u_char *start = stream, *pnt = stream; + u_char *start = stream, *pnt = stream, *endpnt; *found = 0; memset (tlvs, 0, sizeof (struct tlvs)); @@ -584,11 +584,20 @@ parse_tlvs (char *areatag, u_char * stream, int size, zlog_debug ("ISIS-TLV (%s): IPv4 extended Reachability length %d", areatag, length); #endif /* EXTREME_TLV_DEBUG */ + endpnt = pnt + length; if (*expected & TLVFLAG_TE_IPV4_REACHABILITY) { while (length > value_len) { te_ipv4_reach = (struct te_ipv4_reachability *) pnt; + if ((te_ipv4_reach->control & 0x3F) > IPV4_MAX_BITLEN) + { + zlog_warn ("ISIS-TLV (%s): invalid IPv4 extended reach" + "ability prefix length %d", areatag, + te_ipv4_reach->control & 0x3F); + retval = ISIS_WARNING; + break; + } if (!tlvs->te_ipv4_reachs) tlvs->te_ipv4_reachs = list_new (); listnode_add (tlvs->te_ipv4_reachs, te_ipv4_reach); @@ -600,10 +609,8 @@ parse_tlvs (char *areatag, u_char * stream, int size, ((((te_ipv4_reach->control & 0x3F) - 1) >> 3) + 1) : 0); } } - else - { - pnt += length; - } + + pnt = endpnt; break; #ifdef HAVE_IPV6 @@ -648,11 +655,22 @@ parse_tlvs (char *areatag, u_char * stream, int size, * +---------------------------------------------------------------+ */ *found |= TLVFLAG_IPV6_REACHABILITY; + endpnt = pnt + length; + if (*expected & TLVFLAG_IPV6_REACHABILITY) { while (length > value_len) { ipv6_reach = (struct ipv6_reachability *) pnt; + if (ipv6_reach->prefix_len > IPV6_MAX_BITLEN) + { + zlog_warn ("ISIS-TLV (%s): invalid IPv6 extended reach" + "ability prefix length %d", areatag, + ipv6_reach->prefix_len); + retval = ISIS_WARNING; + break; + } + prefix_octets = ((ipv6_reach->prefix_len + 7) / 8); value_len += prefix_octets + 6; pnt += prefix_octets + 6; @@ -662,10 +680,8 @@ parse_tlvs (char *areatag, u_char * stream, int size, listnode_add (tlvs->ipv6_reachs, ipv6_reach); } } - else - { - pnt += length; - } + + pnt = endpnt; break; #endif /* HAVE_IPV6 */ @@ -696,6 +712,7 @@ parse_tlvs (char *areatag, u_char * stream, int size, Neighbor Extended Local Circuit ID (four octets, if Neighbor System ID is present) */ pnt += length; + value_len += length; } } else @@ -916,10 +933,9 @@ tlv_add_ip_addrs (struct list *ip_addrs, struct stream { if (pos - value + IPV4_MAX_BYTELEN > 255) { - retval = add_tlv (IPV4_ADDR, pos - value, value, stream); - if (retval != ISIS_OK) - return retval; - pos = value; + /* RFC 1195 s4.2: only one tuple of 63 allowed. */ + zlog_warn ("tlv_add_ip_addrs(): cutting off at 63 IP addresses"); + break; } *(u_int32_t *) pos = ipv4->prefix.s_addr; pos += IPV4_MAX_BYTELEN;