1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2007 Sun Microsystems, Inc.
15 #include "frr_pthread.h"
17 #include "bgpd/bgpd.c"
18 #include "bgpd/bgp_open.h"
19 #include "bgpd/bgp_debug.h"
20 #include "bgpd/bgp_packet.h"
22 #define VT100_RESET "\x1b[0m"
23 #define VT100_RED "\x1b[31m"
24 #define VT100_GREEN "\x1b[32m"
25 #define VT100_YELLOW "\x1b[33m"
31 /* need these to link in libbgp */
32 struct zebra_privs_t bgpd_privs
= {};
33 struct thread_master
*master
= NULL
;
35 static int failed
= 0;
38 /* test segments to parse and validate, and use for other tests */
39 static struct test_segment
{
42 const uint8_t data
[1024];
44 #define SHOULD_PARSE 0
46 int parses
; /* whether it should parse or not */
47 as_t peek_for
; /* what peek_for_as4_capability should say */
49 /* AFI/SAFI validation */
60 "capability header, and no more",
61 {CAPABILITY_CODE_REFRESH
, 0x0},
68 "header, no data but length says there is",
76 "valid, with padding",
77 {CAPABILITY_CODE_REFRESH
, 0x2, 0x0, 0x0},
84 "violates minsize requirement",
85 {CAPABILITY_CODE_ORF
, 0x2, 0x0, 0x0},
89 {NULL
, NULL
, {0}, 0, 0},
92 static struct test_segment mp_segments
[] = {
96 {0x1, 0x4, 0x0, 0x1, 0x0, 0x1},
108 {0x1, 0x4, 0x0, 0x2, 0x0, 0x1},
121 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x2},
133 "MP IP6/MPLS-labeled VPN",
134 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x80},
147 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x2, 0x0, 0x4},
159 "MP IP4/MPLS-labeled VPN",
160 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0x1, 0x0, 0x80},
172 "MP unknown AFI/SAFI",
173 {CAPABILITY_CODE_MP
, 0x4, 0x0, 0xa, 0x0, 0x81},
180 INVALID_AFI
, /* parses, but unknown */
185 "MP IP4/Unicast, length too short (< minimum)",
186 {CAPABILITY_CODE_MP
, 0x2, 0x0, 0x1, 0x0, 0x1},
193 "MP IP4/Unicast, length too long",
194 {CAPABILITY_CODE_MP
, 0x6, 0x0, 0x1, 0x0, 0x1},
203 {NULL
, NULL
, {0}, 0, 0}};
205 static struct test_segment misc_segments
[] =
210 "ORF, simple, single entry, single tuple",
211 {/* hdr */ CAPABILITY_CODE_ORF
, 0x7,
212 /* mpc */ 0x0, 0x1, 0x0, 0x1,
214 /* tuples */ 0x40, 0x3},
221 "ORF, multi entry/tuple",
223 /* hdr */ CAPABILITY_CODE_ORF
,
265 "ORF, multi entry/tuple, hdr length too short",
267 /* hdr */ CAPABILITY_CODE_ORF
,
304 SHOULD_ERR
, /* It should error on invalid
309 "ORF, multi entry/tuple, length too long",
352 "ORF, multi entry/tuple, entry number too long",
391 SHOULD_PARSE
, /* parses, but last few tuples should be
397 "ORF, multi entry/tuple, entry number too short",
436 SHOULD_PARSE
, /* Parses, but should get gibberish
442 "ORF, multi entry/tuple, padded to align",
488 {0x41, 0x4, 0xab, 0xcd, 0xef,
489 0x12}, /* AS: 2882400018 */
496 "AS4 capability: short",
497 {0x41, 0x4, 0xab, 0xcd, 0xef}, /* AS: 2882400018 */
503 "AS4 capability: long",
504 {0x41, 0x4, 0xab, 0xcd, 0xef, 0x12, 0x12},
513 /* hdr */ CAPABILITY_CODE_RESTART
, 0xe,
514 /* R-bit, time */ 0xf1, 0x12,
530 "GR capability, but header length too short",
533 /* R-bit, time */ 0xf1, 0x12,
544 15 /* array is 16 though */,
549 "GR capability, but header length too long",
552 /* R-bit, time */ 0xf1, 0x12,
568 "GR capability, but truncated",
571 /* R-bit, time */ 0xf1, 0x12,
587 "GR capability, but empty.",
596 "MP capability, but empty.",
605 "ORF capability, but empty.",
614 "AS4 capability, but empty.",
623 "Dynamic capability, but empty.",
632 "Dynamic capability (deprecated version)",
633 {CAPABILITY_CODE_DYNAMIC
, 0x0},
649 "Role capability, but too long",
659 "Role capability, but empty.",
666 {NULL
, NULL
, {0}, 0, 0}};
668 /* DYNAMIC message */
669 struct test_segment dynamic_cap_msgs
[] = {
672 "Dynamic Capability Message, IP/Multicast",
673 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2},
675 SHOULD_PARSE
, /* horrible alignment, just as with ORF */
679 "Dynamic Capability Message, IP/Multicast, truncated",
680 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2},
686 "Dynamic Capability Message, IP/Multicast, padded",
687 {0x0, 0x1, 0x4, 0x0, 0x1, 0x0, 0x2, 0x0},
689 SHOULD_ERR
, /* No way to tell padding from data.. */
693 "Dynamic Capability Message, IP/Multicast, cap data padded",
694 {0x0, 0x1, 0x5, 0x0, 0x1, 0x0, 0x2, 0x0},
696 SHOULD_PARSE
, /* You can though add padding to the capability
701 "Dynamic Capability Message, IP/Multicast, cap data != length",
702 {0x0, 0x1, 0x3, 0x0, 0x1, 0x0, 0x2, 0x0},
706 {NULL
, NULL
, {0}, 0, 0}};
708 /* Entire Optional-Parameters block */
709 struct test_segment opt_params
[] = {
712 "One capability per Optional-Param",
714 0x02, 0x06, 0x01, 0x04,
715 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
716 0x02, 0x06, 0x01, 0x04,
717 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
718 0x02, 0x02, 0x80, 0x00, /* RR (old) */
719 0x02, 0x02, 0x02, 0x00, /* RR */
726 "Series of capability, one Optional-Param",
728 0x02, 0x10, 0x01, 0x04, 0x00, 0x01, 0x00,
729 0x01, /* MP IPv4/Uni */
730 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
731 0x80, 0x00, /* RR (old) */
739 "AS4 capability after other caps (singlets)",
741 0x02, 0x06, 0x01, 0x04,
742 0x00, 0x01, 0x00, 0x01, /* MP IPv4/Uni */
743 0x02, 0x06, 0x01, 0x04,
744 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
745 0x02, 0x02, 0x80, 0x00, /* RR (old) */
746 0x02, 0x02, 0x02, 0x00, /* RR */
747 0x02, 0x06, 0x41, 0x04,
748 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
756 "AS4 capability, in series of capabilities",
758 0x02, 0x16, 0x01, 0x04, 0x00, 0x01,
759 0x00, 0x01, /* MP IPv4/Uni */
760 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, /* MP IPv6/Uni */
761 0x80, 0x00, /* RR (old) */
763 0x41, 0x04, 0x00, 0x03, 0x00, 0x06 /* AS4: 1996614 */
771 "AS4 capability, in series of capabilities",
773 0x02, 0x06, 0x01, 0x04,
774 0x00, 0x01, 0x00, 0x01, /* MP IPv4/uni */
775 0x02, 0x06, 0x01, 0x04,
776 0x00, 0x02, 0x00, 0x01, /* MP IPv6/uni */
777 0x02, 0x02, 0x80, 0x00, /* RR old */
778 0x02, 0x02, 0x02, 0x00, /* RR */
779 0x02, 0x06, 0x41, 0x04,
780 0x00, 0x03, 0x00, 0x06, /* AS4 */
788 "AS4 capability, in series of capabilities",
790 0x02, 0x06, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x02,
791 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x01, 0x02, 0x02,
792 0x80, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x06, 0x41,
793 0x04, 0x00, 0x00, 0xfc, 0x03, 0x02, 0x09, 0x82, 0x07,
794 0x00, 0x01, 0x00, 0x01, 0x01, 0x80, 0x03, 0x02, 0x09,
795 0x03, 0x07, 0x00, 0x01, 0x00, 0x01, 0x01, 0x40, 0x03,
796 0x02, 0x02, 0x42, 0x00,
803 {NULL
, NULL
, {0}, 0, 0}};
805 /* basic parsing test */
806 static void parse_test(struct peer
*peer
, struct test_segment
*t
, int type
)
811 int oldfailed
= failed
;
813 #define RANDOM_FUZZ 35
815 stream_reset(peer
->curr
);
816 stream_put(peer
->curr
, NULL
, RANDOM_FUZZ
);
817 stream_set_getp(peer
->curr
, RANDOM_FUZZ
);
821 stream_putc(peer
->curr
, BGP_OPEN_OPT_CAP
);
822 stream_putc(peer
->curr
, t
->len
);
825 /* for (i = 0; i < BGP_MARKER_SIZE; i++)
826 stream_putc (peer->, 0xff);
828 stream_putc (s, BGP_MSG_CAPABILITY);*/
831 stream_write(peer
->curr
, t
->data
, t
->len
);
833 printf("%s: %s\n", t
->name
, t
->desc
);
837 len
+= 2; /* to cover the OPT-Param header */
840 printf("len: %u\n", len
);
841 /* peek_for_as4 wants getp at capibility*/
842 as4
= peek_for_as4_capability(peer
, len
);
843 printf("peek_for_as4: as4 is %u\n", as4
);
844 /* and it should leave getp as it found it */
845 assert(stream_get_getp(peer
->curr
) == RANDOM_FUZZ
);
847 ret
= bgp_open_option_parse(peer
, len
, &capability
);
850 ret
= bgp_capability_receive(peer
, t
->len
);
853 printf("unknown type %u\n", type
);
857 if (ret
!= BGP_Stop
&& t
->validate_afi
) {
861 /* Convert AFI, SAFI to internal values, check. */
862 if (bgp_map_afi_safi_iana2int(t
->afi
, t
->safi
, &afi
, &safi
)) {
863 if (t
->afi_valid
== VALID_AFI
)
866 printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", t
->afi
, afi
,
867 t
->safi
, safi
, peer
->afc_recv
[afi
][safi
],
868 peer
->afc_nego
[afi
][safi
]);
870 if (t
->afi_valid
== VALID_AFI
) {
872 if (!peer
->afc_recv
[afi
][safi
])
874 if (!peer
->afc_nego
[afi
][safi
])
879 if (as4
!= t
->peek_for
) {
880 printf("as4 %u != %u\n", as4
, t
->peek_for
);
885 * Some of the functions used return BGP_Stop on error and some return
886 * -1. If we have -1, keep it; if we have BGP_Stop, transform it to the
887 * correct pass/fail code
890 ret
= (ret
== BGP_Stop
) ? -1 : 0;
892 printf("parsed?: %s\n", ret
? "no" : "yes");
894 if (ret
!= t
->parses
) {
895 printf("t->parses: %d\nret: %d\n", t
->parses
, ret
);
901 (failed
> oldfailed
) ? VT100_RED
"failed!" VT100_RESET
902 : VT100_GREEN
"OK" VT100_RESET
);
904 printf("%s", (failed
> oldfailed
) ? "failed!" : "OK");
907 printf(" (%u)", failed
);
912 static struct bgp
*bgp
;
913 static as_t asn
= 100;
920 conf_bgp_debug_neighbor_events
= -1UL;
921 conf_bgp_debug_packet
= -1UL;
922 conf_bgp_debug_as4
= -1UL;
923 term_bgp_debug_neighbor_events
= -1UL;
924 term_bgp_debug_packet
= -1UL;
925 term_bgp_debug_as4
= -1UL;
928 master
= thread_master_create(NULL
);
929 bgp_master_init(master
, BGP_SOCKET_SNDBUF_SIZE
, list_new());
930 vrf_init(NULL
, NULL
, NULL
, NULL
);
931 bgp_option_set(BGP_OPT_NO_LISTEN
);
935 bgp_pth_ka
->running
= true;
937 if (fileno(stdout
) >= 0)
938 tty
= isatty(fileno(stdout
));
940 if (bgp_get(&bgp
, &asn
, NULL
, BGP_INSTANCE_TYPE_DEFAULT
, NULL
,
941 ASNOTATION_PLAIN
) < 0)
944 peer
= peer_create_accept(bgp
);
945 peer
->host
= (char *)"foo";
947 for (i
= AFI_IP
; i
< AFI_MAX
; i
++)
948 for (j
= SAFI_UNICAST
; j
< SAFI_MAX
; j
++) {
950 peer
->afc_adv
[i
][j
] = 1;
953 peer
->curr
= stream_new(BGP_MAX_PACKET_SIZE
);
956 while (mp_segments
[i
].name
)
957 parse_test(peer
, &mp_segments
[i
++], CAPABILITY
);
959 /* These tests assume mp_segments tests set at least
960 * one of the afc_nego's
963 while (test_segments
[i
].name
)
964 parse_test(peer
, &test_segments
[i
++], CAPABILITY
);
967 while (misc_segments
[i
].name
)
968 parse_test(peer
, &misc_segments
[i
++], CAPABILITY
);
971 while (opt_params
[i
].name
)
972 parse_test(peer
, &opt_params
[i
++], OPT_PARAM
);
974 SET_FLAG(peer
->cap
, PEER_CAP_DYNAMIC_ADV
);
975 peer
->status
= Established
;
978 while (dynamic_cap_msgs
[i
].name
)
979 parse_test(peer
, &dynamic_cap_msgs
[i
++], DYNCAP
);
981 printf("failures: %d\n", failed
);