diff options
-rw-r--r-- | tests/bgp_mp_attr_test.c | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c new file mode 100644 index 00000000..dde0df2f --- /dev/null +++ b/tests/bgp_mp_attr_test.c @@ -0,0 +1,535 @@ +#include <zebra.h> + +#include "vty.h" +#include "stream.h" +#include "privs.h" +#include "memory.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_open.h" +#include "bgpd/bgp_debug.h" + +#define VT100_RESET "\x1b[0m" +#define VT100_RED "\x1b[31m" +#define VT100_GREEN "\x1b[32m" +#define VT100_YELLOW "\x1b[33m" + + +#define CAPABILITY 0 +#define DYNCAP 1 +#define OPT_PARAM 2 + +/* need these to link in libbgp */ +struct zebra_privs_t *bgpd_privs = NULL; +struct thread_master *master = NULL; + +static int failed = 0; +static int tty = 0; + +/* test segments to parse and validate, and use for other tests */ +static struct test_segment { + const char *name; + const char *desc; + const u_char data[1024]; + int len; +#define SHOULD_PARSE 0 +#define SHOULD_ERR -1 + int parses; /* whether it should parse or not */ + + /* AFI/SAFI validation */ + afi_t afi; + safi_t safi; +#define VALID_AFI 1 +#define INVALID_AFI 0 + int afi_valid; +} mp_reach_segments [] = +{ + { "IPv6", + "IPV6 MP Reach, global nexthop, 1 NLRI", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + }, + (4 + 16 + 1 + 5), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-2", + "IPV6 MP Reach, global nexthop, 2 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* ffee:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + }, + (4 + 16 + 1 + 5 + 9), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-default", + "IPV6 MP Reach, global nexthop, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (4 + 16 + 1 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-lnh", + "IPV6 MP Reach, global+local nexthops, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ + 0x0, 0x0, 0x0, 0x0, + 0x2, 0x10, 0x2, 0xff, + 0x1, 0x2, 0x3, 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-nhlen", + "IPV6 MP Reach, inappropriate nexthop length", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 4, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ + 0x0, 0x0, 0x0, 0x0, + 0x2, 0x10, 0x2, 0xff, + 0x1, 0x2, 0x3, 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-nhlen2", + "IPV6 MP Reach, invalid nexthop length", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 5, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ + 0x0, 0x0, 0x0, 0x0, + 0x2, 0x10, 0x2, 0xff, + 0x1, 0x2, 0x3, 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-nhlen3", + "IPV6 MP Reach, nexthop length overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + }, + (4 + 16), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-nhlen4", + "IPV6 MP Reach, nexthop length short", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 16, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ + 0x0, 0x0, 0x0, 0x0, + 0x2, 0x10, 0x2, 0xff, + 0x1, 0x2, 0x3, 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-nlri", + "IPV6 MP Reach, NLRI bitlen overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* nexthop bytes */ 32, + /* Nexthop (global) */ 0xff, 0xfe, 0x1, 0x2, /* fffe:102:... */ + 0xaa, 0xbb, 0xcc, 0xdd, + 0x3, 0x4, 0x5, 0x6, + 0xa1, 0xa2, 0xa3, 0xa4, + /* Nexthop (local) */ 0xfe, 0x80, 0x0, 0x0, /* fe80::210:2ff:.. */ + 0x0, 0x0, 0x0, 0x0, + 0x2, 0x10, 0x2, 0xff, + 0x1, 0x2, 0x3, 0x4, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 120, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0, /* ::/0 */ + }, + (4 + 32 + 1 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4", + "IPv4 MP Reach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 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 */ + }, + (4 + 4 + 1 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-nhlen", + "IPv4 MP Reach, nexthop lenth overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 32, + /* 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 */ + }, + (4 + 4 + 1 + 3 + 4 + 1), + SHOULD_ERR, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-nlrilen", + "IPv4 MP Reach, nlri lenth overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* nexthop bytes */ 4, + /* Nexthop */ 192, 168, 0, 1, + /* SNPA (defunct, MBZ) */ 0x0, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 30, 10, + 0, /* 0/0 */ + }, + (4 + 4 + 1 + 3 + 2 + 1), + SHOULD_ERR, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-vpnv4", + "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP, BGP_SAFI_VPNV4, + /* 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 */ + }, + (4 + 12 + 1 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + /* From bug #385 */ + { "IPv6-bug", + "IPv6, global nexthop, 1 default NLRI", + { + /* AFI / SAFI */ 0x0, 0x2, 0x1, + /* nexthop bytes */ 0x20, + /* Nexthop (global) */ 0x20, 0x01, 0x04, 0x70, + 0x00, 0x01, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + /* Nexthop (local) */ 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x02, 0x0c, 0xdb, 0xff, + 0xfe, 0xfe, 0xeb, 0x00, + /* SNPA (defunct, MBZ) */ 0, + /* NLRI tuples */ /* Should have 0 here for ::/0, but dont */ + }, + 37, + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + + { NULL, NULL, {0}, 0, 0} +}; + +/* MP_UNREACH_NLRI tests */ +static struct test_segment mp_unreach_segments [] = +{ + { "IPv6-unreach", + "IPV6 MP Unreach, 1 NLRI", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + }, + (3 + 5), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-unreach2", + "IPV6 MP Unreach, 2 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + }, + (3 + 5 + 9), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-unreach-default", + "IPV6 MP Unreach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 32, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0x0, /* ::/0 */ + }, + (3 + 5 + 9 + 1), + SHOULD_PARSE, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv6-unreach-nlri", + "IPV6 MP Unreach, NLRI bitlen overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP6, SAFI_UNICAST, + /* NLRI tuples */ 120, + 0xff, 0xfe, 0x1, 0x2, /* fffe:102::/32 */ + 64, + 0xff, 0xfe, 0x0, 0x1, /* fffe:1:2:3::/64 */ + 0x0, 0x2, 0x0, 0x3, + 0, /* ::/0 */ + }, + (3 + 5 + 9 + 1), + SHOULD_ERR, + AFI_IP6, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-unreach", + "IPv4 MP Unreach, 2 NLRIs + default", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 17, 10, 2, 3, /* 10.2.3/17 */ + 0, /* 0/0 */ + }, + (3 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-unreach-nlrilen", + "IPv4 MP Unreach, nlri length overflow", + { + /* AFI / SAFI */ 0x0, AFI_IP, SAFI_UNICAST, + /* NLRI tuples */ 16, 10, 1, /* 10.1/16 */ + 30, 10, + 0, /* 0/0 */ + }, + (3 + 3 + 2 + 1), + SHOULD_ERR, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { "IPv4-unreach-vpnv4", + "IPv4/VPNv4 MP Unreach, RD, 3 NLRIs", + { + /* AFI / SAFI */ 0x0, AFI_IP, BGP_SAFI_VPNV4, + /* 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 */ + }, + (3 + 3 + 4 + 1), + SHOULD_PARSE, + AFI_IP, SAFI_UNICAST, VALID_AFI, + }, + { NULL, NULL, {0}, 0, 0} +}; + + +/* basic parsing test */ +static void +parse_test (struct peer *peer, struct test_segment *t, int type) +{ + int ret; + int oldfailed = failed; + struct attr attr; + struct bgp_nlri nlri; +#define RANDOM_FUZZ 35 + + stream_reset (peer->ibuf); + stream_put (peer->ibuf, NULL, RANDOM_FUZZ); + stream_set_getp (peer->ibuf, RANDOM_FUZZ); + + stream_write (peer->ibuf, t->data, t->len); + + printf ("%s: %s\n", t->name, t->desc); + + if (type == BGP_ATTR_MP_REACH_NLRI) + ret = bgp_mp_reach_parse (peer, t->len, &attr, &nlri); + else + ret = bgp_mp_unreach_parse (peer, t->len, &nlri); + + if (!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 ("parsed?: %s\n", ret ? "no" : "yes"); + + if (ret != t->parses) + 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"); +} + +static struct bgp *bgp; +static as_t asn = 100; + +int +main (void) +{ + struct peer *peer; + int i, j; + + conf_bgp_debug_fsm = -1UL; + conf_bgp_debug_events = -1UL; + conf_bgp_debug_packet = -1UL; + conf_bgp_debug_normal = -1UL; + conf_bgp_debug_as4 = -1UL; + term_bgp_debug_fsm = -1UL; + term_bgp_debug_events = -1UL; + term_bgp_debug_packet = -1UL; + term_bgp_debug_normal = -1UL; + term_bgp_debug_as4 = -1UL; + + master = thread_master_create (); + bgp_master_init (); + + if (fileno (stdout) >= 0) + tty = isatty (fileno (stdout)); + + if (bgp_get (&bgp, &asn, NULL)) + return -1; + + peer = peer_create_accept (bgp); + peer->host = "foo"; + + for (i = AFI_IP; i < AFI_MAX; i++) + for (j = SAFI_UNICAST; j < SAFI_MAX; j++) + { + peer->afc[i][j] = 1; + peer->afc_adv[i][j] = 1; + } + + i = 0; + while (mp_reach_segments[i].name) + parse_test (peer, &mp_reach_segments[i++], BGP_ATTR_MP_REACH_NLRI); + + i = 0; + while (mp_unreach_segments[i].name) + parse_test (peer, &mp_unreach_segments[i++], BGP_ATTR_MP_UNREACH_NLRI); + + printf ("failures: %d\n", failed); + return failed; +} |