summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_mplsvpn.c
diff options
context:
space:
mode:
authorPaul Jakma <paul.jakma@hpe.com>2016-01-27 16:37:33 +0000
committerPaul Jakma <paul.jakma@hpe.com>2016-03-08 17:53:10 +0000
commit18ab08b71e6b29e67b36df5e2261569d381b1708 (patch)
tree1160aff3b43a6e0bdf5e8b553425ad5bea12640f /bgpd/bgp_mplsvpn.c
parentc49a2747f6a6199dba27c0c413f4de6112fa649e (diff)
downloadquagga-18ab08b71e6b29e67b36df5e2261569d381b1708.tar.bz2
quagga-18ab08b71e6b29e67b36df5e2261569d381b1708.tar.xz
bgpd: Regularise BGP NLRI sanity checks a bit
* bgp_route.h: (bgp_nlri_sanity_check) The bulk of the args are equivalent to a (struct bgp_nlri), consolidate. * bgp_route.c: (bgp_nlri_sanity_check) Make this a frontend for all afi/safis. Including SAFI_MPLS_LABELED_VPN. (bgp_nlri_sanity_check_ip) Regular IP NLRI sanity check based on the existing code, and adjusted for (struct bgp_nlri *) arg. * bgp_attr.c: (bgp_mp_reach_parse) Adjust for passing (struct bgp_nlri *) to bgp_nlri_sanity_check. Get rid of special-casing to not sanity check VPN. (bgp_mp_unreach_parse) Ditto. * bgp_mplsvpn.c: Use the same VPN parsing code for both the sanity check and the actual parse. (bgp_nlri_parse_vpn) renamed to bgp_nlri_parse_vpn_body and made internal. (bgp_nlri_parse_vpn_body) Added (bool) argument to control whether it is sanity checking or whether it should update routing state for each NLRI. Send a NOTIFY and reset the session, if there's a parsing error, as bgp_nlri_sanity_check_ip does, and as is required by the RFC. (bgp_nlri_parse_vpn) now a wrapper to call _body with update. (bgp_nlri_sanity_check_vpn) wrapper to call parser without updating. * bgp_mplsvpn.h: (bgp_nlri_sanity_check_vpn) export for bgp_nlri_sanity_check. * bgp_packet.c: (bgp_update_receive) Adjust for bgp_nlri_sanity_check argument changes. * test/bgp_mp_attr_test.c: Extend to also test the NLRI parsing functions, if the initial MP-attr parsing has succeeded. Fix the NLRI in the VPN cases. Add further VPN tests. * tests/bgpd.tests/testbgpmpattr.exp: Add the new test cases. This commit a joint effort of: Lou Berger <lberger@labn.net> Donald Sharp <sharpd@cumulusnetworks.com> Paul Jakma <paul.jakma@hpe.com> / <paul@jakma.org>
Diffstat (limited to 'bgpd/bgp_mplsvpn.c')
-rw-r--r--bgpd/bgp_mplsvpn.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index f8b43df8..900bc487 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -32,6 +32,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_packet.h"
static u_int16_t
decode_rd_type (u_char *pnt)
@@ -91,9 +92,9 @@ decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
rd_ip->val |= (u_int16_t) *pnt;
}
-int
-bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
- struct bgp_nlri *packet)
+static int
+bgp_nlri_parse_vpn_body (struct peer *peer, struct attr *attr,
+ struct bgp_nlri *packet, bool update)
{
u_char *pnt;
u_char *lim;
@@ -129,30 +130,53 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
psize = PSIZE (prefixlen);
/* sanity check against packet data */
- if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8 || (pnt + psize) > lim)
+ if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8)
+ {
+ plog_err (peer->log,
+ "%s [Error] Update packet error / VPNv4"
+ " (prefix length %d less than VPNv4 min length)",
+ peer->host, prefixlen);
+ bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
+ return -1;
+ }
+ if ((pnt + psize) > lim)
{
- zlog_err ("prefix length (%d) is less than 88"
- " or larger than received (%u)",
+ plog_err (peer->log,
+ "%s [Error] Update packet error / VPNv4"
+ " (psize %u exceeds packet size (%u)",
+ peer->host,
prefixlen, (uint)(lim-pnt));
+ bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
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)",
+ plog_err (peer->log,
+ "%s [Error] Update packet error / VPNv4"
+ " (psize %u exceeds storage size (%zu)",
+ peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8, sizeof(p.u));
+ bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
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)",
+ plog_err (peer->log,
+ "%s [Error] Update packet error / VPNv4"
+ " (psize %u exceeds family (%u) max byte len %u)",
+ peer->host,
prefixlen - VPN_PREFIXLEN_MIN_BYTES*8,
p.family, prefix_blen (&p));
+ bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
return -1;
-
}
/* Copyr label to prefix. */
@@ -187,22 +211,46 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES,
psize - VPN_PREFIXLEN_MIN_BYTES);
- if (attr)
- bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
- else
- bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
+ if (update)
+ {
+ if (attr)
+ bgp_update (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
+ else
+ bgp_withdraw (peer, &p, attr, packet->afi, SAFI_MPLS_VPN,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
+ }
}
/* Packet length consistency check. */
if (pnt != lim)
- return -1;
+ {
+ plog_err (peer->log,
+ "%s [Error] Update packet error / VPNv4"
+ " (%zu data remaining after parsing)",
+ peer->host, lim - pnt);
+ bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR);
+ return -1;
+ }
return 0;
#undef VPN_PREFIXLEN_MIN_BYTES
}
int
+bgp_nlri_sanity_check_vpn (struct peer *peer, struct bgp_nlri *nlri)
+{
+ return bgp_nlri_parse_vpn_body (peer, NULL, nlri, false);
+}
+
+int
+bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
+ struct bgp_nlri *packet)
+{
+ return bgp_nlri_parse_vpn_body (peer, attr, packet, true);
+}
+
+int
str2prefix_rd (const char *str, struct prefix_rd *prd)
{
int ret; /* ret of called functions */