2 * Copyright (C) 2007 Sun Microsystems, Inc.
4 * This file is part of Quagga.
6 * Quagga is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * Quagga is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Quagga; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_open.h"
32 #include "bgpd/bgp_debug.h"
33 #include "bgpd/bgp_packet.h"
35 #define VT100_RESET "\x1b[0m"
36 #define VT100_RED "\x1b[31m"
37 #define VT100_GREEN "\x1b[32m"
38 #define VT100_YELLOW "\x1b[33m"
45 /* need these to link in libbgp */
46 struct zebra_privs_t *bgpd_privs = NULL;
47 struct thread_master *master = NULL;
49 static int failed = 0;
52 /* test segments to parse and validate, and use for other tests */
53 static struct test_segment {
56 const u_char data[1024];
58 #define SHOULD_PARSE 0
60 int parses; /* whether it should parse or not */
61 as_t peek_for; /* what peek_for_as4_capability should say */
63 /* AFI/SAFI validation */
74 "capability header, and no more",
75 { CAPABILITY_CODE_REFRESH, 0x0 },
80 "header, no data but length says there is",
86 "valid, with padding",
87 { CAPABILITY_CODE_REFRESH, 0x2, 0x0, 0x0 },
92 "violates minsize requirement",
93 { CAPABILITY_CODE_ORF, 0x2, 0x0, 0x0 },
96 { NULL, NULL, {0}, 0, 0},
99 static struct test_segment mp_segments[] =
103 { 0x1, 0x4, 0x0, 0x1, 0x0, 0x1 },
105 1, AFI_IP, SAFI_UNICAST, VALID_AFI,
109 { 0x1, 0x4, 0x0, 0x2, 0x0, 0x1 },
111 1, AFI_IP6, SAFI_UNICAST, VALID_AFI,
116 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x2 },
118 1, AFI_IP, SAFI_MULTICAST, VALID_AFI,
122 "MP IP6/MPLS-labeled VPN",
123 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
125 1, AFI_IP6, SAFI_MPLS_LABELED_VPN, VALID_AFI,
130 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
132 1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI,
136 "MP IP4/MPLS-laveled VPN",
137 { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
139 1, AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
143 "MP unknown AFI/SAFI",
144 { CAPABILITY_CODE_MP, 0x4, 0x0, 0xa, 0x0, 0x81 },
146 1, 0xa, 0x81, INVALID_AFI, /* parses, but unknown */
150 "MP IP4/Unicast, length too short (< minimum)",
151 { CAPABILITY_CODE_MP, 0x2, 0x0, 0x1, 0x0, 0x1 },
156 "MP IP4/Unicast, length too long",
157 { CAPABILITY_CODE_MP, 0x6, 0x0, 0x1, 0x0, 0x1 },
159 1, AFI_IP, SAFI_UNICAST, VALID_AFI,
161 { NULL, NULL, {0}, 0, 0}
164 static struct test_segment misc_segments[] =
168 "ORF, simple, single entry, single tuple",
169 { /* hdr */ CAPABILITY_CODE_ORF, 0x7,
170 /* mpc */ 0x0, 0x1, 0x0, 0x1,
172 /* tuples */ 0x40, 0x3
178 "ORF, multi entry/tuple",
179 { /* hdr */ CAPABILITY_CODE_ORF, 0x21,
180 /* mpc */ 0x0, 0x1, 0x0, 0x1,
182 /* tuples */ 0x40, ORF_MODE_BOTH,
183 0x80, ORF_MODE_RECEIVE,
185 /* mpc */ 0x0, 0x2, 0x0, 0x1,
187 /* tuples */ 0x40, ORF_MODE_BOTH,
188 0x80, ORF_MODE_RECEIVE,
190 /* mpc */ 0x0, 0x2, 0x0, 0x2,
192 /* tuples */ 0x40, ORF_MODE_RECEIVE,
200 "ORF, multi entry/tuple, hdr length too short",
201 { /* hdr */ CAPABILITY_CODE_ORF, 0x15,
202 /* mpc */ 0x0, 0x1, 0x0, 0x1,
204 /* tuples */ 0x40, 0x3,
207 /* mpc */ 0x0, 0x1, 0x0, 0x1,
209 /* tuples */ 0x40, 0x3,
212 /* mpc */ 0x0, 0x2, 0x0, 0x2,
214 /* tuples */ 0x40, 0x3,
218 35, SHOULD_ERR, /* It should error on invalid Route-Refresh.. */
222 "ORF, multi entry/tuple, length too long",
223 { /* hdr */ 0x3, 0x22,
224 /* mpc */ 0x0, 0x1, 0x0, 0x1,
226 /* tuples */ 0x40, 0x3,
229 /* mpc */ 0x0, 0x2, 0x0, 0x1,
231 /* tuples */ 0x40, 0x3,
234 /* mpc */ 0x0, 0x2, 0x0, 0x2,
236 /* tuples */ 0x40, 0x3,
244 "ORF, multi entry/tuple, entry number too long",
245 { /* hdr */ 0x3, 0x21,
246 /* mpc */ 0x0, 0x1, 0x0, 0x1,
248 /* tuples */ 0x40, 0x3,
251 /* mpc */ 0x0, 0x2, 0x0, 0x1,
253 /* tuples */ 0x40, 0x3,
256 /* mpc */ 0x0, 0x2, 0x0, 0x2,
258 /* tuples */ 0x40, 0x3,
262 35, SHOULD_PARSE, /* parses, but last few tuples should be gibberish */
266 "ORF, multi entry/tuple, entry number too short",
267 { /* hdr */ 0x3, 0x21,
268 /* mpc */ 0x0, 0x1, 0x0, 0x1,
270 /* tuples */ 0x40, 0x3,
273 /* mpc */ 0x0, 0x2, 0x0, 0x1,
275 /* tuples */ 0x40, 0x3,
278 /* mpc */ 0x0, 0x2, 0x0, 0x2,
280 /* tuples */ 0x40, 0x3,
284 35, SHOULD_PARSE, /* Parses, but should get gibberish afi/safis */
288 "ORF, multi entry/tuple, padded to align",
289 { /* hdr */ 0x3, 0x22,
290 /* mpc */ 0x0, 0x1, 0x0, 0x1,
292 /* tuples */ 0x40, 0x3,
295 /* mpc */ 0x0, 0x2, 0x0, 0x1,
297 /* tuples */ 0x40, 0x3,
300 /* mpc */ 0x0, 0x2, 0x0, 0x2,
302 /* tuples */ 0x40, 0x3,
312 { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12 }, /* AS: 2882400018 */
313 6, SHOULD_PARSE, 2882400018,
316 "AS4 capability: short",
317 { 0x41, 0x4, 0xab, 0xcd, 0xef }, /* AS: 2882400018 */
321 "AS4 capability: long",
322 { 0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12 },
323 7, SHOULD_ERR, 2882400018,
327 { /* hdr */ CAPABILITY_CODE_RESTART, 0xe,
328 /* R-bit, time */ 0xf1, 0x12,
342 "GR capability, but header length too short",
343 { /* hdr */ 0x40, 0xa,
344 /* R-bit, time */ 0xf1, 0x12,
355 15 /* array is 16 though */, SHOULD_ERR,
358 "GR capability, but header length too long",
359 { /* hdr */ 0x40, 0xf,
360 /* R-bit, time */ 0xf1, 0x12,
374 "GR capability, but truncated",
375 { /* hdr */ 0x40, 0xf,
376 /* R-bit, time */ 0xf1, 0x12,
390 "GR capability, but empty.",
391 { /* hdr */ 0x40, 0x0,
396 "MP capability, but empty.",
397 { /* hdr */ 0x1, 0x0,
402 "ORF capability, but empty.",
403 { /* hdr */ 0x3, 0x0,
408 "AS4 capability, but empty.",
409 { /* hdr */ 0x41, 0x0,
414 "Dynamic capability, but empty.",
415 { /* hdr */ 0x42, 0x0,
420 "Dynamic capability (deprecated version)",
421 { CAPABILITY_CODE_DYNAMIC, 0x0 },
424 { NULL, NULL, {0}, 0, 0}
427 /* DYNAMIC message */
428 struct test_segment dynamic_cap_msgs[] =
431 "Dynamic Capability Message, IP/Multicast",
432 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
433 7, SHOULD_PARSE, /* horrible alignment, just as with ORF */
436 "Dynamic Capability Message, IP/Multicast, truncated",
437 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2 },
441 "Dynamic Capability Message, IP/Multicast, padded",
442 { 0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0 },
443 8, SHOULD_ERR, /* No way to tell padding from data.. */
446 "Dynamic Capability Message, IP/Multicast, cap data padded",
447 { 0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0 },
448 8, SHOULD_PARSE, /* You can though add padding to the capability data */
450 { "DynCapMPCoverflow",
451 "Dynamic Capability Message, IP/Multicast, cap data != length",
452 { 0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0 },
455 { NULL, NULL, {0}, 0, 0}
458 /* Entire Optional-Parameters block */
459 struct test_segment opt_params[] =
462 "One capability per Optional-Param",
463 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
464 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
465 0x02, 0x02, 0x80, 0x00, /* RR (old) */
466 0x02, 0x02, 0x02, 0x00, /* RR */
471 "Series of capability, one Optional-Param",
473 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
474 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
475 0x80, 0x00, /* RR (old) */
481 "AS4 capability after other caps (singlets)",
482 { 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
483 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
484 0x02, 0x02, 0x80, 0x00, /* RR (old) */
485 0x02, 0x02, 0x02, 0x00, /* RR */
486 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
488 32, SHOULD_PARSE, 196614,
491 "AS4 capability, in series of capabilities",
493 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
494 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
495 0x80, 0x00, /* RR (old) */
497 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
499 24, SHOULD_PARSE, 196614,
502 "AS4 capability, in series of capabilities",
504 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
505 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
506 0x02, 0x02, 0x80, 0x00, /* RR old */
507 0x02, 0x02, 0x02, 0x00, /* RR */
508 0x02, 0x06, 0x41, 0x04, 0x00, 0x03, 0x00, 0x06, /* AS4 */
510 32, SHOULD_PARSE, 196614,
513 "AS4 capability, in series of capabilities",
515 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01,
516 0x02, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01,
517 0x02, 0x02, 0x80, 0x00,
518 0x02, 0x02, 0x02, 0x00,
519 0x02, 0x06, 0x41, 0x04, 0x00, 0x00, 0xfc, 0x03,
520 0x02, 0x09, 0x82, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03,
521 0x02, 0x09, 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
522 0x02, 0x02, 0x42, 0x00,
524 58, SHOULD_PARSE, 64515,
527 { NULL, NULL, {0}, 0, 0}
530 /* basic parsing test */
532 parse_test (struct peer *peer, struct test_segment *t, int type)
537 int oldfailed = failed;
539 #define RANDOM_FUZZ 35
541 stream_reset (peer->ibuf);
542 stream_put (peer->ibuf, NULL, RANDOM_FUZZ);
543 stream_set_getp (peer->ibuf, RANDOM_FUZZ);
548 stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP);
549 stream_putc (peer->ibuf, t->len);
552 /* for (i = 0; i < BGP_MARKER_SIZE; i++)
553 stream_putc (peer->, 0xff);
555 stream_putc (s, BGP_MSG_CAPABILITY);*/
558 stream_write (peer->ibuf, t->data, t->len);
560 printf ("%s: %s\n", t->name, t->desc);
565 len += 2; /* to cover the OPT-Param header */
567 printf ("len: %u\n", len);
568 /* peek_for_as4 wants getp at capibility*/
569 as4 = peek_for_as4_capability (peer, len);
570 printf ("peek_for_as4: as4 is %u\n", as4);
571 /* and it should leave getp as it found it */
572 assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ);
574 ret = bgp_open_option_parse (peer, len, &capability);
577 ret = bgp_capability_receive (peer, t->len);
580 printf ("unknown type %u\n", type);
584 if (!ret && t->validate_afi)
586 safi_t safi = t->safi;
588 if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid)
591 printf ("MP: %u/%u (%u): recv %u, nego %u\n",
592 t->afi, t->safi, safi,
593 peer->afc_recv[t->afi][safi],
594 peer->afc_nego[t->afi][safi]);
596 if (t->afi_valid == VALID_AFI)
599 if (!peer->afc_recv[t->afi][safi])
601 if (!peer->afc_nego[t->afi][safi])
606 if (as4 != t->peek_for)
608 printf ("as4 %u != %u\n", as4, t->peek_for);
612 printf ("parsed?: %s\n", ret ? "no" : "yes");
614 if (ret != t->parses)
618 printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET
619 : VT100_GREEN "OK" VT100_RESET);
621 printf ("%s", (failed > oldfailed) ? "failed!" : "OK" );
624 printf (" (%u)", failed);
629 static struct bgp *bgp;
630 static as_t asn = 100;
638 conf_bgp_debug_fsm = -1UL;
639 conf_bgp_debug_events = -1UL;
640 conf_bgp_debug_packet = -1UL;
641 conf_bgp_debug_normal = -1UL;
642 conf_bgp_debug_as4 = -1UL;
643 term_bgp_debug_fsm = -1UL;
644 term_bgp_debug_events = -1UL;
645 term_bgp_debug_packet = -1UL;
646 term_bgp_debug_normal = -1UL;
647 term_bgp_debug_as4 = -1UL;
649 master = thread_master_create ();
651 bgp_option_set (BGP_OPT_NO_LISTEN);
653 if (fileno (stdout) >= 0)
654 tty = isatty (fileno (stdout));
656 if (bgp_get (&bgp, &asn, NULL))
659 peer = peer_create_accept (bgp);
660 peer->host = (char *) "foo";
662 for (i = AFI_IP; i < AFI_MAX; i++)
663 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
666 peer->afc_adv[i][j] = 1;
670 while (mp_segments[i].name)
671 parse_test (peer, &mp_segments[i++], CAPABILITY);
673 /* These tests assume mp_segments tests set at least
674 * one of the afc_nego's
677 while (test_segments[i].name)
678 parse_test (peer, &test_segments[i++], CAPABILITY);
681 while (misc_segments[i].name)
682 parse_test (peer, &misc_segments[i++], CAPABILITY);
685 while (opt_params[i].name)
686 parse_test (peer, &opt_params[i++], OPT_PARAM);
688 SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
689 peer->status = Established;
692 while (dynamic_cap_msgs[i].name)
693 parse_test (peer, &dynamic_cap_msgs[i++], DYNCAP);
695 printf ("failures: %d\n", failed);