summaryrefslogtreecommitdiffstats
path: root/tests/bgpd/test_mp_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/bgpd/test_mp_attr.c')
-rw-r--r--tests/bgpd/test_mp_attr.c1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
new file mode 100644
index 0000000..bda453b
--- /dev/null
+++ b/tests/bgpd/test_mp_attr.c
@@ -0,0 +1,1130 @@
+/*
+ * Copyright (C) 2008 Sun Microsystems, Inc.
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "qobj.h"
+#include "vty.h"
+#include "stream.h"
+#include "privs.h"
+#include "memory.h"
+#include "queue.h"
+#include "filter.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr.h"
+#include "bgpd/bgp_open.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_nexthop.h"
+#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_network.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 = {};
+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 uint8_t data[1024];
+ int len;
+#define SHOULD_PARSE 0
+#define SHOULD_ERR -1
+ int parses; /* whether it should parse or not */
+} 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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "IPv4-VPNv4",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+ {
+ "IPv4-VPNv4-bogus-plen",
+ "IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len",
+ {
+ /* AFI / SAFI */ 0x0,
+ AFI_IP,
+ IANA_SAFI_MPLS_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 */
+ },
+ (3 + 1 + 3 * 4 + 1 + 3 + 4 + 1),
+ SHOULD_ERR,
+ },
+ {
+ "IPv4-VPNv4-plen1-short",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+ {
+ "IPv4-VPNv4-plen1-long",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+ {
+ "IPv4-VPNv4-plenn-long",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+ {
+ "IPv4-VPNv4-plenn-short",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+ {
+ "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, IANA_SAFI_MPLS_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,
+ },
+ {
+ "IPv4-VPNv4-0-nlri",
+ "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_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,
+ },
+
+ /* 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,
+ },
+ {
+ .name = "IPv4",
+ .desc = "IPV4 MP Reach, flowspec, 1 NLRI",
+ .data = {
+ /* AFI / SAFI */ 0x0,
+ AFI_IP,
+ IANA_SAFI_FLOWSPEC,
+ 0x00, /* no NH */
+ 0x00,
+ 0x06, /* FS Length */
+ 0x01, /* FS dest prefix ID */
+ 0x1e, /* IP */
+ 0x1e,
+ 0x28,
+ 0x28,
+ 0x0
+ },
+ .len = 12,
+ .parses = SHOULD_PARSE,
+ },
+ {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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "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,
+ },
+ {
+ "IPv4-unreach-VPNv4",
+ "IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs",
+ {
+ /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
+ /* 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 + (1 + 3 + 8 + 2) + (1 + 3 + 8 + 3)),
+ SHOULD_PARSE,
+ },
+ {
+ .name = "IPv4",
+ .desc = "IPV4 MP Unreach, flowspec, 1 NLRI",
+ .data = {
+ /* AFI / SAFI */ 0x0,
+ AFI_IP,
+ IANA_SAFI_FLOWSPEC,
+ 0x06, /* FS Length */
+ 0x01, /* FS dest prefix ID */
+ 0x1e, /* IP */
+ 0x1e,
+ 0x28,
+ 0x28,
+ 0x0
+ },
+ .len = 10,
+ .parses = SHOULD_PARSE,
+ },
+ {NULL, NULL, {0}, 0, 0}};
+
+static struct test_segment mp_prefix_sid[] = {
+ {
+ "PREFIX-SID",
+ "PREFIX-SID Test 1",
+ {
+ /* TLV[0] Latel-Index TLV */
+ 0x01, /* Type 0x01:Label-Index */
+ 0x00, 0x07, /* Length */
+ 0x00, /* RESERVED */
+ 0x00, 0x00, /* Flags */
+ 0x00, 0x00, 0x00, 0x02, /* Label Index */
+
+ /* TLV[1] SRGB TLV */
+ 0x03, /* Type 0x03:SRGB */
+ 0x00, 0x08, /* Length */
+ 0x00, 0x00, /* Flags */
+ 0x0a, 0x1b, 0xfe, /* SRGB[0] first label */
+ 0x00, 0x00, 0x0a /* SRBG[0] nb-labels in range */
+ },
+ .len = 21,
+ .parses = SHOULD_PARSE,
+ },
+ {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;
+
+ 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 parse_ret = 0, nlri_ret = 0;
+ struct attr attr = {};
+ struct bgp_nlri nlri = {};
+ struct bgp_attr_parser_args attr_args = {
+ .peer = peer,
+ .length = t->len,
+ .total = 1,
+ .attr = &attr,
+ .type = type,
+ .flags = BGP_ATTR_FLAG_OPTIONAL,
+ .startp = BGP_INPUT_PNT(peer),
+ };
+#define RANDOM_FUZZ 35
+ stream_reset(peer->curr);
+ stream_put(peer->curr, NULL, RANDOM_FUZZ);
+ stream_set_getp(peer->curr, RANDOM_FUZZ);
+
+ stream_write(peer->curr, t->data, t->len);
+
+ printf("%s: %s\n", t->name, t->desc);
+
+ switch (type) {
+ case BGP_ATTR_MP_REACH_NLRI:
+ parse_ret = bgp_mp_reach_parse(&attr_args, &nlri);
+ break;
+ case BGP_ATTR_MP_UNREACH_NLRI:
+ parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
+ break;
+ case BGP_ATTR_PREFIX_SID:
+ parse_ret = bgp_attr_prefix_sid(&attr_args);
+ break;
+ default:
+ printf("unknown type");
+ return;
+ }
+ if (!parse_ret) {
+ iana_afi_t pkt_afi;
+ iana_safi_t pkt_safi;
+
+ /* Convert AFI, SAFI to internal values, check. */
+ if (bgp_map_afi_safi_int2iana(nlri.afi, nlri.safi, &pkt_afi,
+ &pkt_safi))
+ assert(0);
+
+ printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", nlri.afi,
+ pkt_afi, nlri.safi, pkt_safi,
+ peer->afc_recv[nlri.afi][nlri.safi],
+ peer->afc_nego[nlri.afi][nlri.safi]);
+ }
+
+ if (!parse_ret) {
+ if (type == BGP_ATTR_MP_REACH_NLRI)
+ nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, false);
+ else if (type == BGP_ATTR_MP_UNREACH_NLRI)
+ nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, true);
+ }
+ handle_result(peer, t, parse_ret, nlri_ret);
+}
+
+static struct bgp *bgp;
+static as_t asn = 100;
+
+int main(void)
+{
+ struct interface ifp;
+ struct peer *peer;
+ int i, j;
+
+ conf_bgp_debug_neighbor_events = -1UL;
+ conf_bgp_debug_packet = -1UL;
+ conf_bgp_debug_as4 = -1UL;
+ conf_bgp_debug_flowspec = -1UL;
+ term_bgp_debug_neighbor_events = -1UL;
+ term_bgp_debug_packet = -1UL;
+ term_bgp_debug_as4 = -1UL;
+ term_bgp_debug_flowspec = -1UL;
+
+ qobj_init();
+ cmd_init(0);
+ bgp_vty_init();
+ master = thread_master_create("test mp attr");
+ bgp_master_init(master, BGP_SOCKET_SNDBUF_SIZE, list_new());
+ vrf_init(NULL, NULL, NULL, NULL);
+ bgp_option_set(BGP_OPT_NO_LISTEN);
+ bgp_attr_init();
+
+ if (fileno(stdout) >= 0)
+ tty = isatty(fileno(stdout));
+
+ if (bgp_get(&bgp, &asn, NULL, BGP_INSTANCE_TYPE_DEFAULT) < 0)
+ return -1;
+
+ peer = peer_create_accept(bgp);
+ peer->host = (char *)"foo";
+ peer->status = Established;
+ peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
+
+ ifp.ifindex = 0;
+ peer->nexthop.ifp = &ifp;
+
+ 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);
+
+ i = 0;
+ while (mp_prefix_sid[i].name)
+ parse_test(peer, &mp_prefix_sid[i++],
+ BGP_ATTR_PREFIX_SID);
+ printf("failures: %d\n", failed);
+ return failed;
+}