mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 12:37:10 +00:00
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>
This commit is contained in:
parent
423a9d6497
commit
48a5452b5b
@ -1860,24 +1860,20 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||
__func__, peer->host);
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
}
|
||||
|
||||
if (safi != SAFI_MPLS_LABELED_VPN)
|
||||
{
|
||||
ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
|
||||
nlri_len, &num_mp_pfx);
|
||||
if (ret < 0)
|
||||
{
|
||||
zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
|
||||
__func__, peer->host);
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
}
|
||||
}
|
||||
|
||||
mp_update->afi = afi;
|
||||
mp_update->safi = safi;
|
||||
mp_update->nlri = stream_pnt (s);
|
||||
mp_update->length = nlri_len;
|
||||
|
||||
ret = bgp_nlri_sanity_check (peer, mp_update, &num_mp_pfx);
|
||||
if (ret < 0)
|
||||
{
|
||||
zlog_info ("%s: (%s) NLRI doesn't pass sanity check",
|
||||
__func__, peer->host);
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
}
|
||||
|
||||
stream_forward_getp (s, nlri_len);
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI);
|
||||
@ -1895,7 +1891,6 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
u_int16_t withdraw_len;
|
||||
int ret;
|
||||
int num_mp_pfx = 0;
|
||||
struct peer *const peer = args->peer;
|
||||
struct attr *const attr = args->attr;
|
||||
@ -1912,19 +1907,14 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
|
||||
|
||||
withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
|
||||
|
||||
if (safi != SAFI_MPLS_LABELED_VPN)
|
||||
{
|
||||
ret = bgp_nlri_sanity_check (peer, afi, safi, stream_pnt (s),
|
||||
withdraw_len, &num_mp_pfx);
|
||||
if (ret < 0)
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
}
|
||||
|
||||
mp_withdraw->afi = afi;
|
||||
mp_withdraw->safi = safi;
|
||||
mp_withdraw->nlri = stream_pnt (s);
|
||||
mp_withdraw->length = withdraw_len;
|
||||
|
||||
if (bgp_nlri_sanity_check (peer, mp_withdraw, &num_mp_pfx) < 0)
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
|
||||
stream_forward_getp (s, withdraw_len);
|
||||
|
||||
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI);
|
||||
|
@ -34,6 +34,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"
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
#include "bgpd/rfapi/rfapi_backend.h"
|
||||
@ -134,9 +135,9 @@ decode_rd_vnc_eth (u_char *pnt, struct rd_vnc_eth *rd_vnc_eth)
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
@ -195,37 +196,47 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
|
||||
p.family = afi2family (packet->afi);
|
||||
psize = PSIZE (prefixlen);
|
||||
|
||||
if (prefixlen < 88)
|
||||
if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8)
|
||||
{
|
||||
zlog_err ("prefix length is less than 88: %d", prefixlen);
|
||||
zlog_err ("%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;
|
||||
}
|
||||
|
||||
/* sanity check against packet data */
|
||||
if (prefixlen < VPN_PREFIXLEN_MIN_BYTES*8 || (pnt + psize) > lim)
|
||||
if ((pnt + psize) > lim)
|
||||
{
|
||||
zlog_err ("prefix length (%d) is less than 88"
|
||||
" or larger than received (%u)",
|
||||
zlog_err ("%s [Error] Update packet error / VPNv4 (prefix length %d 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)",
|
||||
zlog_err ("%s [Error] Update packet error / VPNv4 (psize %d 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)",
|
||||
zlog_err ("%s [Error] Update packet error / VPNv4 (psize %d 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;
|
||||
|
||||
}
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
@ -269,34 +280,57 @@ 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)
|
||||
if (update)
|
||||
{
|
||||
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
|
||||
if (attr)
|
||||
{
|
||||
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
|
||||
#if ENABLE_BGP_VNC
|
||||
rfapiProcessUpdate(peer, NULL, &p, &prd, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&label);
|
||||
rfapiProcessUpdate(peer, NULL, &p, &prd, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
|
||||
&label);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENABLE_BGP_VNC
|
||||
rfapiProcessWithdraw(peer, NULL, &p, &prd, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, 0);
|
||||
rfapiProcessWithdraw(peer, NULL, &p, &prd, attr, packet->afi,
|
||||
SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, 0);
|
||||
#endif
|
||||
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
|
||||
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Packet length consistency check. */
|
||||
if (pnt != lim)
|
||||
return -1;
|
||||
|
||||
{
|
||||
zlog_err ("%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, int *numpfx)
|
||||
{
|
||||
*numpfx = 0;
|
||||
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)
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ extern u_int16_t decode_rd_type (u_char *);
|
||||
extern void encode_rd_type (u_int16_t, u_char *);
|
||||
extern void bgp_mplsvpn_init (void);
|
||||
extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
|
||||
extern int bgp_nlri_sanity_check_vpn (struct peer *, struct bgp_nlri *, int *);
|
||||
extern u_int32_t decode_label (u_char *);
|
||||
extern void encode_label(u_int32_t, u_char *);
|
||||
extern void decode_rd_as (u_char *, struct rd_as *);
|
||||
|
@ -1393,15 +1393,14 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
||||
/* Unfeasible Route packet format check. */
|
||||
if (withdraw_len > 0)
|
||||
{
|
||||
ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
|
||||
withdraw_len, &num_pfx_wd);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
withdraw.afi = AFI_IP;
|
||||
withdraw.safi = SAFI_UNICAST;
|
||||
withdraw.nlri = stream_pnt (s);
|
||||
withdraw.length = withdraw_len;
|
||||
ret = bgp_nlri_sanity_check (peer, &withdraw, &num_pfx_wd);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
stream_forward_getp (s, withdraw_len);
|
||||
}
|
||||
|
||||
@ -1478,20 +1477,20 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
||||
|
||||
if (update_len)
|
||||
{
|
||||
/* Set NLRI portion to structure. */
|
||||
update.afi = AFI_IP;
|
||||
update.safi = SAFI_UNICAST;
|
||||
update.nlri = stream_pnt (s);
|
||||
update.length = update_len;
|
||||
|
||||
/* Check NLRI packet format and prefix length. */
|
||||
ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s),
|
||||
update_len, &num_pfx_adv);
|
||||
ret = bgp_nlri_sanity_check (peer, &update, &num_pfx_adv);
|
||||
if (ret < 0)
|
||||
{
|
||||
bgp_attr_unintern_sub (&attr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set NLRI portion to structure. */
|
||||
update.afi = AFI_IP;
|
||||
update.safi = SAFI_UNICAST;
|
||||
update.nlri = stream_pnt (s);
|
||||
update.length = update_len;
|
||||
stream_forward_getp (s, update_len);
|
||||
}
|
||||
|
||||
|
@ -3521,17 +3521,19 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
|
||||
}
|
||||
|
||||
/* NLRI encode syntax check routine. */
|
||||
int
|
||||
bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, u_char *pnt,
|
||||
bgp_size_t length, int *numpfx)
|
||||
static int
|
||||
bgp_nlri_sanity_check_ip (struct peer *peer, struct bgp_nlri *nlri, int *numpfx)
|
||||
{
|
||||
u_char *end;
|
||||
u_char prefixlen;
|
||||
int psize;
|
||||
int addpath_encoded;
|
||||
u_char *pnt = nlri->nlri;
|
||||
afi_t afi = nlri->afi;
|
||||
safi_t safi = nlri->safi;
|
||||
|
||||
*numpfx = 0;
|
||||
end = pnt + length;
|
||||
end = pnt + nlri->length;
|
||||
addpath_encoded = bgp_addpath_encode_rx (peer, afi, safi);
|
||||
|
||||
/* RFC1771 6.3 The NLRI field in the UPDATE message is checked for
|
||||
@ -3611,6 +3613,21 @@ bgp_nlri_sanity_check (struct peer *peer, int afi, safi_t safi, u_char *pnt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
bgp_nlri_sanity_check (struct peer *peer, struct bgp_nlri *nlri, int *numpfx)
|
||||
{
|
||||
switch (nlri->safi)
|
||||
{
|
||||
case SAFI_MPLS_LABELED_VPN:
|
||||
return bgp_nlri_sanity_check_vpn (peer, nlri, numpfx);
|
||||
case SAFI_UNICAST:
|
||||
case SAFI_MULTICAST:
|
||||
return bgp_nlri_sanity_check_ip (peer, nlri, numpfx);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct bgp_static *
|
||||
bgp_static_new (void)
|
||||
{
|
||||
|
@ -264,7 +264,7 @@ extern void bgp_info_set_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
|
||||
extern void bgp_info_unset_flag (struct bgp_node *, struct bgp_info *, u_int32_t);
|
||||
extern void bgp_info_path_with_addpath_rx_str (struct bgp_info *ri, char *buf);
|
||||
|
||||
extern int bgp_nlri_sanity_check (struct peer *, int, safi_t, u_char *, bgp_size_t, int *);
|
||||
extern int bgp_nlri_sanity_check (struct peer *, struct bgp_nlri *, int *);
|
||||
extern int bgp_nlri_parse (struct peer *, struct attr *, struct bgp_nlri *);
|
||||
|
||||
extern int bgp_maximum_prefix_overflow (struct peer *, afi_t, safi_t, int);
|
||||
|
@ -33,6 +33,9 @@
|
||||
#include "bgpd/bgp_attr.h"
|
||||
#include "bgpd/bgp_open.h"
|
||||
#include "bgpd/bgp_debug.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
#include "bgpd/bgp_mplsvpn.h"
|
||||
#include "bgpd/bgp_nexthop.h"
|
||||
|
||||
#define VT100_RESET "\x1b[0m"
|
||||
#define VT100_RED "\x1b[31m"
|
||||
@ -310,8 +313,34 @@ static struct test_segment {
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-MLVPN",
|
||||
"IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, 3 NLRIs",
|
||||
{ "IPv4-VPNv4",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-bogus-plen",
|
||||
"IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
@ -323,10 +352,169 @@ static struct test_segment {
|
||||
17, 10, 2, 3, /* 10.2.3/17 */
|
||||
0, /* 0/0 */
|
||||
},
|
||||
(4 + 12 + 1 + 3 + 4 + 1),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||
(3 + 1 + 3*4 + 1 + 3 + 4 + 1),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plen1-short",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 1,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plen1-long",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 32,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plenn-long",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
88 + 1, /* bogus */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plenn-short",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 2,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-bogus-rd-type",
|
||||
"IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0xff, 0, /* Bogus RD */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-0-nlri",
|
||||
"IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
0 /* 0/0, bogus for vpnv4 ?? */
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
|
||||
/* From bug #385 */
|
||||
{ "IPv6-bug",
|
||||
"IPv6, global nexthop, 1 default NLRI",
|
||||
@ -433,33 +621,79 @@ static struct test_segment mp_unreach_segments [] =
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-unreach-MLVPN",
|
||||
{ "IPv4-unreach-VPNv4",
|
||||
"IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs",
|
||||
{
|
||||
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN,
|
||||
/* nexthop bytes */ 12,
|
||||
/* RD */ 0, 0, 1, 2,
|
||||
0, 0xff, 3, 4,
|
||||
/* Nexthop */ 192, 168, 0, 1,
|
||||
/* SNPA (defunct, MBZ) */ 0x0,
|
||||
/* NLRI tuples */ 16, 10, 1, /* 10.1/16 */
|
||||
17, 10, 2, 3, /* 10.2.3/17 */
|
||||
0, /* 0/0 */
|
||||
/* NLRI tuples */ 88 + 16,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_AS */
|
||||
0, 2, 0, 0xff, 3, 4, /* AS(2):val(4) */
|
||||
10, 1, /* 10.1/16 */
|
||||
88 + 17,
|
||||
0xff, 0, 0, /* tag */
|
||||
/* rd, 8 octets */
|
||||
0, 0, /* RD_TYPE_IP */
|
||||
192, 168, 0, 1, /* IPv4 */
|
||||
10, 2, 3, /* 10.2.3/17 */
|
||||
},
|
||||
(3 + 3 + 4 + 1),
|
||||
(3 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_UNICAST, VALID_AFI,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
},
|
||||
{ NULL, NULL, {0}, 0, 0}
|
||||
};
|
||||
|
||||
/* nlri_parse indicates 0 on successful parse, and -1 otherwise.
|
||||
* attr_parse indicates BGP_ATTR_PARSE_PROCEED/0 on success,
|
||||
* and BGP_ATTR_PARSE_ERROR/-1 or lower negative ret on err.
|
||||
*/
|
||||
static void
|
||||
handle_result (struct peer *peer, struct test_segment *t,
|
||||
int parse_ret, int nlri_ret)
|
||||
{
|
||||
int oldfailed = failed;
|
||||
|
||||
if (!parse_ret)
|
||||
{
|
||||
safi_t safi = t->safi;
|
||||
|
||||
if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid)
|
||||
failed++;
|
||||
|
||||
printf ("MP: %u/%u (%u): recv %u, nego %u\n",
|
||||
t->afi, t->safi, safi,
|
||||
peer->afc_recv[t->afi][safi],
|
||||
peer->afc_nego[t->afi][safi]);
|
||||
}
|
||||
|
||||
printf ("mp attr parsed?: %s\n", parse_ret ? "no" : "yes");
|
||||
if (!parse_ret)
|
||||
printf ("nrli parsed?: %s\n", nlri_ret ? "no" : "yes");
|
||||
printf ("should parse?: %s\n", t->parses ? "no" : "yes");
|
||||
|
||||
if ((parse_ret != 0 || nlri_ret != 0) != (t->parses != 0))
|
||||
failed++;
|
||||
|
||||
|
||||
if (tty)
|
||||
printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
|
||||
: VT100_GREEN "OK" VT100_RESET);
|
||||
else
|
||||
printf ("%s", (failed > oldfailed) ? "failed!" : "OK" );
|
||||
|
||||
if (failed)
|
||||
printf (" (%u)", failed);
|
||||
|
||||
printf ("\n\n");
|
||||
}
|
||||
|
||||
/* basic parsing test */
|
||||
static void
|
||||
parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||
{
|
||||
int ret;
|
||||
int oldfailed = failed;
|
||||
int parse_ret = 0, nlri_ret = 0;
|
||||
struct attr attr = { };
|
||||
struct bgp_nlri nlri = { };
|
||||
struct bgp_attr_parser_args attr_args = {
|
||||
@ -467,7 +701,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||
.length = t->len,
|
||||
.total = 1,
|
||||
.attr = &attr,
|
||||
.type = BGP_ATTR_MP_REACH_NLRI,
|
||||
.type = type,
|
||||
.flags = BGP_ATTR_FLAG_OPTIONAL,
|
||||
.startp = BGP_INPUT_PNT (peer),
|
||||
};
|
||||
@ -481,40 +715,29 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||
|
||||
printf ("%s: %s\n", t->name, t->desc);
|
||||
|
||||
|
||||
if (type == BGP_ATTR_MP_REACH_NLRI)
|
||||
ret = bgp_mp_reach_parse (&attr_args, &nlri);
|
||||
parse_ret = bgp_mp_reach_parse (&attr_args, &nlri);
|
||||
else
|
||||
ret = bgp_mp_unreach_parse (&attr_args, &nlri);
|
||||
|
||||
if (!ret)
|
||||
parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri);
|
||||
|
||||
if (parse_ret == 0 && t->afi_valid == VALID_AFI)
|
||||
assert (nlri.afi == t->afi && nlri.safi == t->safi);
|
||||
|
||||
if (!parse_ret)
|
||||
{
|
||||
safi_t safi = t->safi;
|
||||
int (*f) (struct peer *, struct attr *, struct bgp_nlri *)
|
||||
= bgp_nlri_parse;
|
||||
|
||||
if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid)
|
||||
failed++;
|
||||
if (t->safi == SAFI_MPLS_LABELED_VPN)
|
||||
f = bgp_nlri_parse_vpn;
|
||||
|
||||
printf ("MP: %u/%u (%u): recv %u, nego %u\n",
|
||||
t->afi, t->safi, safi,
|
||||
peer->afc_recv[t->afi][safi],
|
||||
peer->afc_nego[t->afi][safi]);
|
||||
if (type == BGP_ATTR_MP_REACH_NLRI)
|
||||
nlri_ret = f (peer, &attr, &nlri);
|
||||
else
|
||||
nlri_ret = f (peer, NULL, &nlri);
|
||||
}
|
||||
|
||||
printf ("parsed?: %s\n", ret ? "no" : "yes");
|
||||
|
||||
if ((ret == 0) != (t->parses == 0))
|
||||
failed++;
|
||||
|
||||
if (tty)
|
||||
printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
|
||||
: VT100_GREEN "OK" VT100_RESET);
|
||||
else
|
||||
printf ("%s", (failed > oldfailed) ? "failed!" : "OK" );
|
||||
|
||||
if (failed)
|
||||
printf (" (%u)", failed);
|
||||
|
||||
printf ("\n\n");
|
||||
handle_result (peer, t, parse_ret, nlri_ret);
|
||||
}
|
||||
|
||||
static struct bgp *bgp;
|
||||
@ -538,6 +761,7 @@ main (void)
|
||||
bgp_master_init ();
|
||||
vrf_init ();
|
||||
bgp_option_set (BGP_OPT_NO_LISTEN);
|
||||
bgp_attr_init ();
|
||||
|
||||
if (fileno (stdout) >= 0)
|
||||
tty = isatty (fileno (stdout));
|
||||
@ -547,6 +771,7 @@ main (void)
|
||||
|
||||
peer = peer_create_accept (bgp);
|
||||
peer->host = (char *)"foo";
|
||||
peer->status = Established;
|
||||
|
||||
for (i = AFI_IP; i < AFI_MAX; i++)
|
||||
for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
|
||||
|
@ -19,7 +19,14 @@ simpletest "IPv6-nlri: IPV6 MP Reach, NLRI bitlen overflow"
|
||||
simpletest "IPv4: IPv4 MP Reach, 2 NLRIs + default"
|
||||
simpletest "IPv4-nhlen: IPv4 MP Reach, nexthop lenth overflow"
|
||||
simpletest "IPv4-nlrilen: IPv4 MP Reach, nlri lenth overflow"
|
||||
simpletest "IPv4-MLVPN: IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, 3 NLRIs"
|
||||
simpletest "IPv4-VPNv4: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs"
|
||||
simpletest "IPv4-VPNv4-bogus-plen: IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len"
|
||||
simpletest "IPv4-VPNv4-plen1-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short"
|
||||
simpletest "IPv4-VPNv4-plen1-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long"
|
||||
simpletest "IPv4-VPNv4-plenn-long: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long"
|
||||
simpletest "IPv4-VPNv4-plenn-short: IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short"
|
||||
simpletest "IPv4-VPNv4-bogus-rd-type: IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)"
|
||||
simpletest "IPv4-VPNv4-0-nlri: IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus"
|
||||
simpletest "IPv6-bug: IPv6, global nexthop, 1 default NLRI"
|
||||
simpletest "IPv6-unreach: IPV6 MP Unreach, 1 NLRI"
|
||||
simpletest "IPv6-unreach2: IPV6 MP Unreach, 2 NLRIs"
|
||||
@ -27,5 +34,5 @@ simpletest "IPv6-unreach-default: IPV6 MP Unreach, 2 NLRIs + default"
|
||||
simpletest "IPv6-unreach-nlri: IPV6 MP Unreach, NLRI bitlen overflow"
|
||||
simpletest "IPv4-unreach: IPv4 MP Unreach, 2 NLRIs + default"
|
||||
simpletest "IPv4-unreach-nlrilen: IPv4 MP Unreach, nlri length overflow"
|
||||
simpletest "IPv4-unreach-MLVPN: IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs"
|
||||
simpletest "IPv4-unreach-VPNv4: IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user