9 #include "bgpd/bgp_open.h"
10 #include "bgpd/bgp_debug.h"
12 #define VT100_RESET "\x1b[0m"
13 #define VT100_RED "\x1b[31m"
14 #define VT100_GREEN "\x1b[32m"
15 #define VT100_YELLOW "\x1b[33m"
22 /* need these to link in libbgp */
23 struct zebra_privs_t
*bgpd_privs
= NULL
;
24 struct thread_master
*master
= NULL
;
26 static int failed
= 0;
29 /* test segments to parse and validate, and use for other tests */
30 static struct test_segment
{
33 const u_char data
[1024];
35 #define SHOULD_PARSE 0
37 int parses
; /* whether it should parse or not */
38 int peek_for
; /* what peek_for_as4_capability should say */
40 /* AFI/SAFI validation */
51 "capability header, and no more",
52 { CAPABILITY_CODE_REFRESH
, 0x0 },
57 "header, no data but length says there is",
63 "valid, with padding",
64 { CAPABILITY_CODE_REFRESH
, 0x2, 0x0, 0x0 },
69 "violates minsize requirement",
70 { CAPABILITY_CODE_ORF
, 0x2, 0x0, 0x0 },
73 { NULL
, NULL
, {0}, 0, 0},
76 static struct test_segment mp_segments
[] =
80 { 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 },
82 1, AFI_IP
, SAFI_UNICAST
, VALID_AFI
,
86 { 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 },
88 1, AFI_IP6
, SAFI_UNICAST
, VALID_AFI
,
93 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x2 },
95 1, AFI_IP
, SAFI_MULTICAST
, VALID_AFI
,
100 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x80 },
101 6, SHOULD_PARSE
, 0, /* parses, but invalid afi,safi */
102 1, AFI_IP6
, BGP_SAFI_VPNV4
, INVALID_AFI
,
107 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x4 },
109 1, AFI_IP6
, SAFI_MPLS_VPN
, VALID_AFI
,
114 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x80 },
116 1, AFI_IP
, BGP_SAFI_VPNV4
, VALID_AFI
,
121 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x81 },
122 6, SHOULD_PARSE
, 0, /* parses, but invalid afi,safi tuple */
123 1, AFI_IP
, BGP_SAFI_VPNV6
, INVALID_AFI
,
128 { CAPABILITY_CODE_MP
, 0x4, 0x0, 0xa, 0x0, 0x81 },
130 1, 0xa, 0x81, INVALID_AFI
, /* parses, but unknown */
134 "MP IP4/Unicast, length too short (< minimum)",
135 { CAPABILITY_CODE_MP
, 0x2, 0x0, 0x1, 0x0, 0x1 },
140 "MP IP4/Unicast, length too long",
141 { CAPABILITY_CODE_MP
, 0x6, 0x0, 0x1, 0x0, 0x1 },
143 1, AFI_IP
, SAFI_UNICAST
, VALID_AFI
,
145 { NULL
, NULL
, {0}, 0, 0}
148 static struct test_segment misc_segments
[] =
152 "ORF, simple, single entry, single tuple",
153 { /* hdr */ CAPABILITY_CODE_ORF
, 0x7,
154 /* mpc */ 0x0, 0x1, 0x0, 0x1,
156 /* tuples */ 0x40, 0x3
162 "ORF, multi entry/tuple",
163 { /* hdr */ CAPABILITY_CODE_ORF
, 0x21,
164 /* mpc */ 0x0, 0x1, 0x0, 0x1,
166 /* tuples */ 0x40, ORF_MODE_BOTH
,
167 0x80, ORF_MODE_RECEIVE
,
169 /* mpc */ 0x0, 0x2, 0x0, 0x1,
171 /* tuples */ 0x40, ORF_MODE_BOTH
,
172 0x80, ORF_MODE_RECEIVE
,
174 /* mpc */ 0x0, 0x2, 0x0, 0x2,
176 /* tuples */ 0x40, ORF_MODE_RECEIVE
,
184 "ORF, multi entry/tuple, hdr length too short",
185 { /* hdr */ CAPABILITY_CODE_ORF
, 0x15,
186 /* mpc */ 0x0, 0x1, 0x0, 0x1,
188 /* tuples */ 0x40, 0x3,
191 /* mpc */ 0x0, 0x1, 0x0, 0x1,
193 /* tuples */ 0x40, 0x3,
196 /* mpc */ 0x0, 0x2, 0x0, 0x2,
198 /* tuples */ 0x40, 0x3,
202 35, SHOULD_ERR
, /* It should error on invalid Route-Refresh.. */
206 "ORF, multi entry/tuple, length too long",
207 { /* hdr */ 0x3, 0x22,
208 /* mpc */ 0x0, 0x1, 0x0, 0x1,
210 /* tuples */ 0x40, 0x3,
213 /* mpc */ 0x0, 0x2, 0x0, 0x1,
215 /* tuples */ 0x40, 0x3,
218 /* mpc */ 0x0, 0x2, 0x0, 0x2,
220 /* tuples */ 0x40, 0x3,
228 "ORF, multi entry/tuple, entry number too long",
229 { /* hdr */ 0x3, 0x21,
230 /* mpc */ 0x0, 0x1, 0x0, 0x1,
232 /* tuples */ 0x40, 0x3,
235 /* mpc */ 0x0, 0x2, 0x0, 0x1,
237 /* tuples */ 0x40, 0x3,
240 /* mpc */ 0x0, 0x2, 0x0, 0x2,
242 /* tuples */ 0x40, 0x3,
246 35, SHOULD_PARSE
, /* parses, but last few tuples should be gibberish */
250 "ORF, multi entry/tuple, entry number too short",
251 { /* hdr */ 0x3, 0x21,
252 /* mpc */ 0x0, 0x1, 0x0, 0x1,
254 /* tuples */ 0x40, 0x3,
257 /* mpc */ 0x0, 0x2, 0x0, 0x1,
259 /* tuples */ 0x40, 0x3,
262 /* mpc */ 0x0, 0x2, 0x0, 0x2,
264 /* tuples */ 0x40, 0x3,
268 35, SHOULD_PARSE
, /* Parses, but should get gibberish afi/safis */
272 "ORF, multi entry/tuple, padded to align",
273 { /* hdr */ 0x3, 0x22,
274 /* mpc */ 0x0, 0x1, 0x0, 0x1,
276 /* tuples */ 0x40, 0x3,
279 /* mpc */ 0x0, 0x2, 0x0, 0x1,
281 /* tuples */ 0x40, 0x3,
284 /* mpc */ 0x0, 0x2, 0x0, 0x2,
286 /* tuples */ 0x40, 0x3,
296 { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 }, /* AS: 2882400018 */
297 6, SHOULD_PARSE
, 2882400018,
302 { /* hdr */ CAPABILITY_CODE_RESTART
, 0xe,
303 /* R-bit, time */ 0xf1, 0x12,
318 "GR capability, but header length too short",
319 { /* hdr */ 0x40, 0xa,
320 /* R-bit, time */ 0xf1, 0x12,
335 "GR capability, but header length too long",
336 { /* hdr */ 0x40, 0xf,
337 /* R-bit, time */ 0xf1, 0x12,
350 "GR capability, but truncated",
351 { /* hdr */ 0x40, 0xf,
352 /* R-bit, time */ 0xf1, 0x12,
366 "GR capability, but empty.",
367 { /* hdr */ 0x40, 0x0,
372 "MP capability, but empty.",
373 { /* hdr */ 0x1, 0x0,
378 "ORF capability, but empty.",
379 { /* hdr */ 0x3, 0x0,
384 "AS4 capability, but empty.",
385 { /* hdr */ 0x41, 0x0,
390 "Dynamic capability, but empty.",
391 { /* hdr */ 0x42, 0x0,
396 "Dynamic capability (deprecated version)",
397 { CAPABILITY_CODE_DYNAMIC
, 0x0 },
400 { NULL
, NULL
, {0}, 0, 0}
403 /* DYNAMIC message */
404 struct test_segment dynamic_cap_msgs
[] =
407 "Dynamic Capability Message, IP/Multicast",
408 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
409 7, SHOULD_PARSE
, /* horrible alignment, just as with ORF */
412 "Dynamic Capability Message, IP/Multicast, truncated",
413 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
417 "Dynamic Capability Message, IP/Multicast, padded",
418 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 },
419 8, SHOULD_ERR
, /* No way to tell padding from data.. */
422 "Dynamic Capability Message, IP/Multicast, cap data padded",
423 { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 },
424 8, SHOULD_PARSE
, /* You can though add padding to the capability data */
426 { "DynCapMPCoverflow",
427 "Dynamic Capability Message, IP/Multicast, cap data != length",
428 { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 },
431 { NULL
, NULL
, {0}, 0, 0}
434 /* Entire Optional-Parameters block */
435 struct test_segment opt_params
[] =
438 "One capability per Optional-Param",
439 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
440 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
441 0x02, 0x02, 0x80, 0x00, /* RR (old) */
442 0x02, 0x02, 0x02, 0x00, /* RR */
447 "Series of capability, one Optional-Param",
449 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
450 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
451 0x80, 0x00, /* RR (old) */
457 "AS4 capability after other caps (singlets)",
458 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
459 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
460 0x02, 0x02, 0x80, 0x00, /* RR (old) */
461 0x02, 0x02, 0x02, 0x00, /* RR */
462 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
464 32, SHOULD_PARSE
, 196614,
467 "AS4 capability, in series of capabilities",
469 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
470 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
471 0x80, 0x00, /* RR (old) */
473 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
475 24, SHOULD_PARSE
, 196614,
478 "AS4 capability, in series of capabilities",
480 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
481 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
482 0x02, 0x02, 0x80, 0x00, /* RR old */
483 0x02, 0x02, 0x02, 0x00, /* RR */
484 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */
486 32, SHOULD_PARSE
, 196614,
489 "AS4 capability, in series of capabilities",
491 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01,
492 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01,
493 0x02, 0x02, 0x80, 0x00,
494 0x02, 0x02, 0x02, 0x00,
495 0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03,
496 0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03,
497 0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
498 0x02, 0x02, 0x42, 0x00,
500 58, SHOULD_PARSE
, 64515,
503 { NULL
, NULL
, {0}, 0, 0}
506 /* basic parsing test */
508 parse_test (struct peer
*peer
, struct test_segment
*t
, int type
)
513 int oldfailed
= failed
;
515 #define RANDOM_FUZZ 35
517 stream_reset (peer
->ibuf
);
518 stream_put (peer
->ibuf
, NULL
, RANDOM_FUZZ
);
519 stream_set_getp (peer
->ibuf
, RANDOM_FUZZ
);
524 stream_putc (peer
->ibuf
, BGP_OPEN_OPT_CAP
);
525 stream_putc (peer
->ibuf
, t
->len
);
528 /* for (i = 0; i < BGP_MARKER_SIZE; i++)
529 stream_putc (peer->, 0xff);
531 stream_putc (s, BGP_MSG_CAPABILITY);*/
534 stream_write (peer
->ibuf
, t
->data
, t
->len
);
536 printf ("%s: %s\n", t
->name
, t
->desc
);
541 len
+= 2; /* to cover the OPT-Param header */
543 printf ("len: %u\n", len
);
544 /* peek_for_as4 wants getp at capibility*/
545 as4
= peek_for_as4_capability (peer
, len
);
546 printf ("peek_for_as4: as4 is %u\n", as4
);
547 /* and it should leave getp as it found it */
548 assert (stream_get_getp (peer
->ibuf
) == RANDOM_FUZZ
);
550 ret
= bgp_open_option_parse (peer
, len
, &capability
);
553 ret
= bgp_capability_receive (peer
, t
->len
);
556 printf ("unknown type %u\n", type
);
560 if (!ret
&& t
->validate_afi
)
562 safi_t safi
= t
->safi
;
564 if (bgp_afi_safi_valid_indices (t
->afi
, &safi
) != t
->afi_valid
)
567 printf ("MP: %u/%u (%u): recv %u, nego %u\n",
568 t
->afi
, t
->safi
, safi
,
569 peer
->afc_recv
[t
->afi
][safi
],
570 peer
->afc_nego
[t
->afi
][safi
]);
572 if (t
->afi_valid
== VALID_AFI
)
575 if (!peer
->afc_recv
[t
->afi
][safi
])
577 if (!peer
->afc_nego
[t
->afi
][safi
])
582 if (as4
!= t
->peek_for
)
584 printf ("as4 %u != %u\n", as4
, t
->peek_for
);
588 printf ("parsed?: %s\n", ret
? "no" : "yes");
590 if (ret
!= t
->parses
)
594 printf ("%s", (failed
> oldfailed
) ? VT100_RED
"failed!" VT100_RESET
595 : VT100_GREEN
"OK" VT100_RESET
);
597 printf ("%s", (failed
> oldfailed
) ? "failed!" : "OK" );
600 printf (" (%u)", failed
);
605 static struct bgp
*bgp
;
606 static as_t asn
= 100;
614 conf_bgp_debug_fsm
= -1UL;
615 conf_bgp_debug_events
= -1UL;
616 conf_bgp_debug_packet
= -1UL;
617 conf_bgp_debug_normal
= -1UL;
618 conf_bgp_debug_as4
= -1UL;
619 term_bgp_debug_fsm
= -1UL;
620 term_bgp_debug_events
= -1UL;
621 term_bgp_debug_packet
= -1UL;
622 term_bgp_debug_normal
= -1UL;
623 term_bgp_debug_as4
= -1UL;
625 master
= thread_master_create ();
628 if (fileno (stdout
) >= 0)
629 tty
= isatty (fileno (stdout
));
631 if (bgp_get (&bgp
, &asn
, NULL
))
634 peer
= peer_create_accept (bgp
);
637 for (i
= AFI_IP
; i
< AFI_MAX
; i
++)
638 for (j
= SAFI_UNICAST
; j
< SAFI_MAX
; j
++)
641 peer
->afc_adv
[i
][j
] = 1;
645 while (mp_segments
[i
].name
)
646 parse_test (peer
, &mp_segments
[i
++], CAPABILITY
);
648 /* These tests assume mp_segments tests set at least
649 * one of the afc_nego's
652 while (test_segments
[i
].name
)
653 parse_test (peer
, &test_segments
[i
++], CAPABILITY
);
656 while (misc_segments
[i
].name
)
657 parse_test (peer
, &misc_segments
[i
++], CAPABILITY
);
660 while (opt_params
[i
].name
)
661 parse_test (peer
, &opt_params
[i
++], OPT_PARAM
);
663 SET_FLAG (peer
->cap
, PEER_CAP_DYNAMIC_ADV
);
664 peer
->status
= Established
;
667 while (dynamic_cap_msgs
[i
].name
)
668 parse_test (peer
, &dynamic_cap_msgs
[i
++], DYNCAP
);
670 printf ("failures: %d\n", failed
);