summaryrefslogtreecommitdiff
path: root/isisd
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2012-05-08 13:15:45 +0200
committerDavid Lamparter <equinox@opensourcerouting.org>2012-10-25 10:15:59 -0700
commitf02a09925db53d3e1d29b1917ebbcaa8edf72c12 (patch)
tree8c8fefac30fa372f4e04c6a9f8ceed6569f55570 /isisd
parent948b6bef7f9cf841a98fe3ea40419696500c8c4c (diff)
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>
Diffstat (limited to 'isisd')
-rw-r--r--isisd/isis_tlv.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/isisd/isis_tlv.c b/isisd/isis_tlv.c
index bb57bd6b..f3b2c338 100644
--- a/isisd/isis_tlv.c
+++ b/isisd/isis_tlv.c
@@ -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 */