summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_mplsvpn.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index a72d5ede..75c90cd7 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -101,6 +101,7 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
pnt = packet->nlri;
lim = pnt + packet->length;
+#define VPN_PREFIXLEN_MIN_BYTES (3 + 8) /* label + RD */
for (; pnt < lim; pnt += psize)
{
/* Clear prefix structure. */
@@ -108,17 +109,38 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
/* Fetch prefix length. */
prefixlen = *pnt++;
- p.family = AF_INET;
+ p.family = afi2family (packet->afi);
psize = PSIZE (prefixlen);
-
- if (prefixlen < 88)
- {
- zlog_err ("prefix length is less than 88: %d", prefixlen);
- return -1;
- }
-
+
+ /* sanity check against packet data */
+ if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8 || (pnt + psize) > lim)
+ {
+ zlog_err ("prefix length (%d) is less than 88"
+ " or larger than received (%u)",
+ prefixlen, (uint)(lim-pnt));
+ return -1;
+ }
+
+ /* sanity check against storage for the IP address portion */
+ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > (ssize_t) sizeof(p.u))
+ {
+ zlog_err ("prefix length (%d) exceeds prefix storage (%zu)",
+ prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u));
+ return -1;
+ }
+
+ /* Sanity check against max bitlen of the address family */
+ if ((psize - VPN_PREFIXLEN_MIN_BYTES) > prefix_blen (&p))
+ {
+ zlog_err ("prefix length (%d) exceeds family (%u) max byte length (%u)",
+ prefixlen - VPN_PREFIXLEN_MIN_BYTES*8,
+ p.family, prefix_blen (&p));
+ return -1;
+
+ }
+
/* Copyr label to prefix. */
- tagpnt = pnt;;
+ tagpnt = pnt;
/* Copy routing distinguisher to rd. */
memcpy (&prd.val, pnt + 3, 8);
@@ -137,8 +159,9 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
return -1;
}
- p.prefixlen = prefixlen - 88;
- memcpy (&p.u.prefix, pnt + 11, psize - 11);
+ p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
+ memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
+ psize - VPN_PREFIXLEN_MIN_BYTES);
#if 0
if (type == RD_TYPE_AS)
@@ -149,9 +172,6 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
rd_ip.val, inet_ntoa (p.u.prefix4), p.prefixlen);
#endif /* 0 */
- if (pnt + psize > lim)
- return -1;
-
if (attr)
bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
@@ -159,12 +179,12 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
}
-
/* Packet length consistency check. */
if (pnt != lim)
return -1;
-
+
return 0;
+#undef VPN_PREFIXLEN_MIN_BYTES
}
int