diff options
author | Paul Jakma <paul.jakma@hpe.com> | 2016-01-27 16:37:33 +0000 |
---|---|---|
committer | Paul Jakma <paul.jakma@hpe.com> | 2016-03-08 17:53:10 +0000 |
commit | 18ab08b71e6b29e67b36df5e2261569d381b1708 (patch) | |
tree | 1160aff3b43a6e0bdf5e8b553425ad5bea12640f /bgpd/bgp_mplsvpn.c | |
parent | c49a2747f6a6199dba27c0c413f4de6112fa649e (diff) | |
download | quagga-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.c | 80 |
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 */ |