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 "Dynamic capability (deprecated version)",
367 { CAPABILITY_CODE_DYNAMIC
, 0x0 },
370 { NULL
, NULL
, {0}, 0, 0}
373 /* DYNAMIC message */
374 struct test_segment dynamic_cap_msgs
[] =
377 "Dynamic Capability Message, IP/Multicast",
378 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
379 7, SHOULD_PARSE
, /* horrible alignment, just as with ORF */
382 "Dynamic Capability Message, IP/Multicast, truncated",
383 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
387 "Dynamic Capability Message, IP/Multicast, padded",
388 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 },
389 8, SHOULD_ERR
, /* No way to tell padding from data.. */
392 "Dynamic Capability Message, IP/Multicast, cap data padded",
393 { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 },
394 8, SHOULD_PARSE
, /* You can though add padding to the capability data */
396 { "DynCapMPCoverflow",
397 "Dynamic Capability Message, IP/Multicast, cap data != length",
398 { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 },
401 { NULL
, NULL
, {0}, 0, 0}
404 /* Entire Optional-Parameters block */
405 struct test_segment opt_params
[] =
408 "One capability per Optional-Param",
409 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
410 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
411 0x02, 0x02, 0x80, 0x00, /* RR (old) */
412 0x02, 0x02, 0x02, 0x00, /* RR */
417 "Series of capability, one Optional-Param",
419 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
420 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
421 0x80, 0x00, /* RR (old) */
427 "AS4 capability after other caps (singlets)",
428 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
429 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
430 0x02, 0x02, 0x80, 0x00, /* RR (old) */
431 0x02, 0x02, 0x02, 0x00, /* RR */
432 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
434 32, SHOULD_PARSE
, 196614,
437 "AS4 capability, in series of capabilities",
439 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
440 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
441 0x80, 0x00, /* RR (old) */
443 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
445 24, SHOULD_PARSE
, 196614,
448 "AS4 capability, in series of capabilities",
450 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
451 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
452 0x02, 0x02, 0x80, 0x00, /* RR old */
453 0x02, 0x02, 0x02, 0x00, /* RR */
454 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */
456 32, SHOULD_PARSE
, 196614,
459 "AS4 capability, in series of capabilities",
461 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01,
462 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01,
463 0x02, 0x02, 0x80, 0x00,
464 0x02, 0x02, 0x02, 0x00,
465 0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03,
466 0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03,
467 0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
468 0x02, 0x02, 0x42, 0x00,
470 58, SHOULD_PARSE
, 64515,
473 { NULL
, NULL
, {0}, 0, 0}
476 /* basic parsing test */
478 parse_test (struct peer
*peer
, struct test_segment
*t
, int type
)
483 int oldfailed
= failed
;
485 #define RANDOM_FUZZ 35
487 stream_reset (peer
->ibuf
);
488 stream_put (peer
->ibuf
, NULL
, RANDOM_FUZZ
);
489 stream_set_getp (peer
->ibuf
, RANDOM_FUZZ
);
494 stream_putc (peer
->ibuf
, BGP_OPEN_OPT_CAP
);
495 stream_putc (peer
->ibuf
, t
->len
);
498 /* for (i = 0; i < BGP_MARKER_SIZE; i++)
499 stream_putc (peer->, 0xff);
501 stream_putc (s, BGP_MSG_CAPABILITY);*/
504 stream_write (peer
->ibuf
, t
->data
, t
->len
);
506 printf ("%s: %s\n", t
->name
, t
->desc
);
511 len
+= 2; /* to cover the OPT-Param header */
513 printf ("len: %u\n", len
);
514 /* peek_for_as4 wants getp at capibility*/
515 as4
= peek_for_as4_capability (peer
, len
);
516 printf ("peek_for_as4: as4 is %u\n", as4
);
517 /* and it should leave getp as it found it */
518 assert (stream_get_getp (peer
->ibuf
) == RANDOM_FUZZ
);
520 ret
= bgp_open_option_parse (peer
, len
, &capability
);
523 ret
= bgp_capability_receive (peer
, t
->len
);
526 printf ("unknown type %u\n", type
);
530 if (!ret
&& t
->validate_afi
)
532 safi_t safi
= t
->safi
;
534 if (bgp_afi_safi_valid_indices (t
->afi
, &safi
) != t
->afi_valid
)
537 printf ("MP: %u/%u (%u): recv %u, nego %u\n",
538 t
->afi
, t
->safi
, safi
,
539 peer
->afc_recv
[t
->afi
][safi
],
540 peer
->afc_nego
[t
->afi
][safi
]);
542 if (t
->afi_valid
== VALID_AFI
)
545 if (!peer
->afc_recv
[t
->afi
][safi
])
547 if (!peer
->afc_nego
[t
->afi
][safi
])
552 if (as4
!= t
->peek_for
)
554 printf ("as4 %u != %u\n", as4
, t
->peek_for
);
558 printf ("parsed?: %s\n", ret
? "no" : "yes");
560 if (ret
!= t
->parses
)
564 printf ("%s", (failed
> oldfailed
) ? VT100_RED
"failed!" VT100_RESET
565 : VT100_GREEN
"OK" VT100_RESET
);
567 printf ("%s", (failed
> oldfailed
) ? "failed!" : "OK" );
570 printf (" (%u)", failed
);
575 static struct bgp
*bgp
;
576 static as_t asn
= 100;
584 conf_bgp_debug_fsm
= -1UL;
585 conf_bgp_debug_events
= -1UL;
586 conf_bgp_debug_packet
= -1UL;
587 conf_bgp_debug_normal
= -1UL;
588 conf_bgp_debug_as4
= -1UL;
589 term_bgp_debug_fsm
= -1UL;
590 term_bgp_debug_events
= -1UL;
591 term_bgp_debug_packet
= -1UL;
592 term_bgp_debug_normal
= -1UL;
593 term_bgp_debug_as4
= -1UL;
595 master
= thread_master_create ();
598 if (fileno (stdout
) >= 0)
599 tty
= isatty (fileno (stdout
));
601 if (bgp_get (&bgp
, &asn
, NULL
))
604 peer
= peer_create_accept (bgp
);
607 for (i
= AFI_IP
; i
< AFI_MAX
; i
++)
608 for (j
= SAFI_UNICAST
; j
< SAFI_MAX
; j
++)
611 peer
->afc_adv
[i
][j
] = 1;
615 while (mp_segments
[i
].name
)
616 parse_test (peer
, &mp_segments
[i
++], CAPABILITY
);
618 /* These tests assume mp_segments tests set at least
619 * one of the afc_nego's
622 while (test_segments
[i
].name
)
623 parse_test (peer
, &test_segments
[i
++], CAPABILITY
);
626 while (misc_segments
[i
].name
)
627 parse_test (peer
, &misc_segments
[i
++], CAPABILITY
);
630 while (opt_params
[i
].name
)
631 parse_test (peer
, &opt_params
[i
++], OPT_PARAM
);
633 SET_FLAG (peer
->cap
, PEER_CAP_DYNAMIC_ADV
);
634 peer
->status
= Established
;
637 while (dynamic_cap_msgs
[i
].name
)
638 parse_test (peer
, &dynamic_cap_msgs
[i
++], DYNCAP
);
640 printf ("failures: %d\n", failed
);