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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "frr_pthread.h"
32 #include "bgpd/bgpd.c"
33 #include "bgpd/bgp_open.h"
34 #include "bgpd/bgp_debug.h"
35 #include "bgpd/bgp_packet.h"
37 #define VT100_RESET "\x1b[0m"
38 #define VT100_RED "\x1b[31m"
39 #define VT100_GREEN "\x1b[32m"
40 #define VT100_YELLOW "\x1b[33m"
46 /* need these to link in libbgp */
47 struct zebra_privs_t
*bgpd_privs
= NULL
;
48 struct thread_master
*master
= NULL
;
50 static int failed
= 0;
53 /* test segments to parse and validate, and use for other tests */
54 static struct test_segment
{
57 const uint8_t data
[1024];
59 #define SHOULD_PARSE 0
61 int parses
; /* whether it should parse or not */
62 as_t peek_for
; /* what peek_for_as4_capability should say */
64 /* AFI/SAFI validation */
75 "capability header, and no more",
76 {CAPABILITY_CODE_REFRESH
, 0x0},
83 "header, no data but length says there is",
91 "valid, with padding",
92 {CAPABILITY_CODE_REFRESH
, 0x2, 0x0, 0x0},
99 "violates minsize requirement",
100 {CAPABILITY_CODE_ORF
, 0x2, 0x0, 0x0},
104 {NULL
, NULL
, {0}, 0, 0},
107 static struct test_segment mp_segments
[] = {
111 {0x1, 0x4, 0x0, 0x1, 0x0, 0x1},
123 {0x1, 0x4, 0x0, 0x2, 0x0, 0x1},
136 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x2},
148 "MP IP6/MPLS-labeled VPN",
149 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x80},
162 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x4},
174 "MP IP4/MPLS-labeled VPN",
175 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x80},
187 "MP unknown AFI/SAFI",
188 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0xa, 0x0, 0x81},
195 INVALID_AFI
, /* parses, but unknown */
200 "MP IP4/Unicast, length too short (< minimum)",
201 {CAPABILITY_CODE_MP
, 0x2, 0x0, 0x1, 0x0, 0x1},
208 "MP IP4/Unicast, length too long",
209 {CAPABILITY_CODE_MP
, 0x6, 0x0, 0x1, 0x0, 0x1},
218 {NULL
, NULL
, {0}, 0, 0}};
220 static struct test_segment misc_segments
[] =
225 "ORF, simple, single entry, single tuple",
226 {/* hdr */ CAPABILITY_CODE_ORF
, 0x7,
227 /* mpc */ 0x0, 0x1, 0x0, 0x1,
229 /* tuples */ 0x40, 0x3},
236 "ORF, multi entry/tuple",
238 /* hdr */ CAPABILITY_CODE_ORF
,
280 "ORF, multi entry/tuple, hdr length too short",
282 /* hdr */ CAPABILITY_CODE_ORF
,
319 SHOULD_ERR
, /* It should error on invalid
324 "ORF, multi entry/tuple, length too long",
367 "ORF, multi entry/tuple, entry number too long",
406 SHOULD_PARSE
, /* parses, but last few tuples should be
412 "ORF, multi entry/tuple, entry number too short",
451 SHOULD_PARSE
, /* Parses, but should get gibberish
457 "ORF, multi entry/tuple, padded to align",
503 {0x41, 0x4, 0xab, 0xcd, 0xef,
504 0x12}, /* AS: 2882400018 */
511 "AS4 capability: short",
512 {0x41, 0x4, 0xab, 0xcd, 0xef}, /* AS: 2882400018 */
518 "AS4 capability: long",
519 {0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12},
528 /* hdr */ CAPABILITY_CODE_RESTART
, 0xe,
529 /* R-bit, time */ 0xf1, 0x12,
545 "GR capability, but header length too short",
548 /* R-bit, time */ 0xf1, 0x12,
559 15 /* array is 16 though */,
564 "GR capability, but header length too long",
567 /* R-bit, time */ 0xf1, 0x12,
583 "GR capability, but truncated",
586 /* R-bit, time */ 0xf1, 0x12,
602 "GR capability, but empty.",
611 "MP capability, but empty.",
620 "ORF capability, but empty.",
629 "AS4 capability, but empty.",
638 "Dynamic capability, but empty.",
647 "Dynamic capability (deprecated version)",
648 {CAPABILITY_CODE_DYNAMIC
, 0x0},
652 {NULL
, NULL
, {0}, 0, 0}};
654 /* DYNAMIC message */
655 struct test_segment dynamic_cap_msgs
[] = {
658 "Dynamic Capability Message, IP/Multicast",
659 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2},
661 SHOULD_PARSE
, /* horrible alignment, just as with ORF */
665 "Dynamic Capability Message, IP/Multicast, truncated",
666 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2},
672 "Dynamic Capability Message, IP/Multicast, padded",
673 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0},
675 SHOULD_ERR
, /* No way to tell padding from data.. */
679 "Dynamic Capability Message, IP/Multicast, cap data padded",
680 {0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0},
682 SHOULD_PARSE
, /* You can though add padding to the capability
687 "Dynamic Capability Message, IP/Multicast, cap data != length",
688 {0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0},
692 {NULL
, NULL
, {0}, 0, 0}};
694 /* Entire Optional-Parameters block */
695 struct test_segment opt_params
[] = {
698 "One capability per Optional-Param",
700 0x02, 0x06, 0x01, 0x04,
701 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
702 0x02, 0x06, 0x01, 0x04,
703 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
704 0x02, 0x02, 0x80, 0x00, /* RR (old) */
705 0x02, 0x02, 0x02, 0x00, /* RR */
712 "Series of capability, one Optional-Param",
714 0x02, 0x10, 0x01, 0x04, 0x00, 0x01, 0x00,
715 0x01, /* MP IPv4/Uni */
716 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
717 0x80, 0x00, /* RR (old) */
725 "AS4 capability after other caps (singlets)",
727 0x02, 0x06, 0x01, 0x04,
728 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
729 0x02, 0x06, 0x01, 0x04,
730 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
731 0x02, 0x02, 0x80, 0x00, /* RR (old) */
732 0x02, 0x02, 0x02, 0x00, /* RR */
733 0x02, 0x06, 0x41, 0x04,
734 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
742 "AS4 capability, in series of capabilities",
744 0x02, 0x16, 0x01, 0x04, 0x00, 0x01,
745 0x00, 0x01, /* MP IPv4/Uni */
746 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
747 0x80, 0x00, /* RR (old) */
749 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
757 "AS4 capability, in series of capabilities",
759 0x02, 0x06, 0x01, 0x04,
760 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
761 0x02, 0x06, 0x01, 0x04,
762 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
763 0x02, 0x02, 0x80, 0x00, /* RR old */
764 0x02, 0x02, 0x02, 0x00, /* RR */
765 0x02, 0x06, 0x41, 0x04,
766 0x00, 0x03, 0x00, 0x06, /* AS4 */
774 "AS4 capability, in series of capabilities",
776 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x02,
777 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x02, 0x02,
778 0x80, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x06, 0x41,
779 0x04, 0x00, 0x00, 0xfc, 0x03, 0x02, 0x09, 0x82, 0x07,
780 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, 0x02, 0x09,
781 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
782 0x02, 0x02, 0x42, 0x00,
789 {NULL
, NULL
, {0}, 0, 0}};
791 /* basic parsing test */
792 static void parse_test(struct peer
*peer
, struct test_segment
*t
, int type
)
797 int oldfailed
= failed
;
799 #define RANDOM_FUZZ 35
801 stream_reset(peer
->curr
);
802 stream_put(peer
->curr
, NULL
, RANDOM_FUZZ
);
803 stream_set_getp(peer
->curr
, RANDOM_FUZZ
);
807 stream_putc(peer
->curr
, BGP_OPEN_OPT_CAP
);
808 stream_putc(peer
->curr
, t
->len
);
811 /* for (i = 0; i < BGP_MARKER_SIZE; i++)
812 stream_putc (peer->, 0xff);
814 stream_putc (s, BGP_MSG_CAPABILITY);*/
817 stream_write(peer
->curr
, t
->data
, t
->len
);
819 printf("%s: %s\n", t
->name
, t
->desc
);
823 len
+= 2; /* to cover the OPT-Param header */
825 printf("len: %u\n", len
);
826 /* peek_for_as4 wants getp at capibility*/
827 as4
= peek_for_as4_capability(peer
, len
);
828 printf("peek_for_as4: as4 is %u\n", as4
);
829 /* and it should leave getp as it found it */
830 assert(stream_get_getp(peer
->curr
) == RANDOM_FUZZ
);
832 ret
= bgp_open_option_parse(peer
, len
, &capability
);
835 ret
= bgp_capability_receive(peer
, t
->len
);
838 printf("unknown type %u\n", type
);
842 if (ret
!= BGP_Stop
&& t
->validate_afi
) {
846 /* Convert AFI, SAFI to internal values, check. */
847 if (bgp_map_afi_safi_iana2int(t
->afi
, t
->safi
, &afi
, &safi
)) {
848 if (t
->afi_valid
== VALID_AFI
)
851 printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", t
->afi
, afi
,
852 t
->safi
, safi
, peer
->afc_recv
[afi
][safi
],
853 peer
->afc_nego
[afi
][safi
]);
855 if (t
->afi_valid
== VALID_AFI
) {
857 if (!peer
->afc_recv
[afi
][safi
])
859 if (!peer
->afc_nego
[afi
][safi
])
864 if (as4
!= t
->peek_for
) {
865 printf("as4 %u != %u\n", as4
, t
->peek_for
);
870 * Some of the functions used return BGP_Stop on error and some return
871 * -1. If we have -1, keep it; if we have BGP_Stop, transform it to the
872 * correct pass/fail code
875 ret
= (ret
== BGP_Stop
) ? -1 : 0;
877 printf("parsed?: %s\n", ret
? "no" : "yes");
879 if (ret
!= t
->parses
) {
880 printf("t->parses: %d\nret: %d\n", t
->parses
, ret
);
886 (failed
> oldfailed
) ? VT100_RED
"failed!" VT100_RESET
887 : VT100_GREEN
"OK" VT100_RESET
);
889 printf("%s", (failed
> oldfailed
) ? "failed!" : "OK");
892 printf(" (%u)", failed
);
897 static struct bgp
*bgp
;
898 static as_t asn
= 100;
905 conf_bgp_debug_neighbor_events
= -1UL;
906 conf_bgp_debug_packet
= -1UL;
907 conf_bgp_debug_as4
= -1UL;
908 term_bgp_debug_neighbor_events
= -1UL;
909 term_bgp_debug_packet
= -1UL;
910 term_bgp_debug_as4
= -1UL;
913 master
= thread_master_create(NULL
);
914 bgp_master_init(master
);
915 vrf_init(NULL
, NULL
, NULL
, NULL
);
916 bgp_option_set(BGP_OPT_NO_LISTEN
);
919 frr_pthread_get(PTHREAD_KEEPALIVES
)->running
= true;
921 if (fileno(stdout
) >= 0)
922 tty
= isatty(fileno(stdout
));
924 if (bgp_get(&bgp
, &asn
, NULL
, BGP_INSTANCE_TYPE_DEFAULT
))
927 peer
= peer_create_accept(bgp
);
928 peer
->host
= (char *)"foo";
930 for (i
= AFI_IP
; i
< AFI_MAX
; i
++)
931 for (j
= SAFI_UNICAST
; j
< SAFI_MAX
; j
++) {
933 peer
->afc_adv
[i
][j
] = 1;
936 peer
->curr
= stream_new(BGP_MAX_PACKET_SIZE
);
939 while (mp_segments
[i
].name
)
940 parse_test(peer
, &mp_segments
[i
++], CAPABILITY
);
942 /* These tests assume mp_segments tests set at least
943 * one of the afc_nego's
946 while (test_segments
[i
].name
)
947 parse_test(peer
, &test_segments
[i
++], CAPABILITY
);
950 while (misc_segments
[i
].name
)
951 parse_test(peer
, &misc_segments
[i
++], CAPABILITY
);
954 while (opt_params
[i
].name
)
955 parse_test(peer
, &opt_params
[i
++], OPT_PARAM
);
957 SET_FLAG(peer
->cap
, PEER_CAP_DYNAMIC_ADV
);
958 peer
->status
= Established
;
961 while (dynamic_cap_msgs
[i
].name
)
962 parse_test(peer
, &dynamic_cap_msgs
[i
++], DYNCAP
);
964 printf("failures: %d\n", failed
);