isisd: don't process invalid prefixes from TLVs

it's possible to feed invalid prefixes (1.2.3.4/40 or dead::beef/200) on
IS-IS.  if this is not checked, it will later cause an assert in
processing.  let's simply abort processing the TLV if the prefix is
invalid.

  * isisd/isis_tlv.c: check prefix lengths for validity

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2012-05-08 13:15:45 +02:00
parent 948b6bef7f
commit f02a09925d

View File

@ -117,7 +117,7 @@ parse_tlvs (char *areatag, u_char * stream, int size, u_int32_t * expected,
#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, u_int32_t * expected,
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, u_int32_t * expected,
((((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, u_int32_t * expected,
* +---------------------------------------------------------------+
*/
*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, u_int32_t * expected,
listnode_add (tlvs->ipv6_reachs, ipv6_reach);
}
}
else
{
pnt += length;
}
pnt = endpnt;
break;
#endif /* HAVE_IPV6 */