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 */
826 printf("len: %u\n", len
);
827 /* peek_for_as4 wants getp at capibility*/
828 as4
= peek_for_as4_capability(peer
, len
);
829 printf("peek_for_as4: as4 is %u\n", as4
);
830 /* and it should leave getp as it found it */
831 assert(stream_get_getp(peer
->curr
) == RANDOM_FUZZ
);
833 ret
= bgp_open_option_parse(peer
, len
, &capability
);
836 ret
= bgp_capability_receive(peer
, t
->len
);
839 printf("unknown type %u\n", type
);
843 if (ret
!= BGP_Stop
&& t
->validate_afi
) {
847 /* Convert AFI, SAFI to internal values, check. */
848 if (bgp_map_afi_safi_iana2int(t
->afi
, t
->safi
, &afi
, &safi
)) {
849 if (t
->afi_valid
== VALID_AFI
)
852 printf("MP: %u(%u)/%u(%u): recv %u, nego %u\n", t
->afi
, afi
,
853 t
->safi
, safi
, peer
->afc_recv
[afi
][safi
],
854 peer
->afc_nego
[afi
][safi
]);
856 if (t
->afi_valid
== VALID_AFI
) {
858 if (!peer
->afc_recv
[afi
][safi
])
860 if (!peer
->afc_nego
[afi
][safi
])
865 if (as4
!= t
->peek_for
) {
866 printf("as4 %u != %u\n", as4
, t
->peek_for
);
871 * Some of the functions used return BGP_Stop on error and some return
872 * -1. If we have -1, keep it; if we have BGP_Stop, transform it to the
873 * correct pass/fail code
876 ret
= (ret
== BGP_Stop
) ? -1 : 0;
878 printf("parsed?: %s\n", ret
? "no" : "yes");
880 if (ret
!= t
->parses
) {
881 printf("t->parses: %d\nret: %d\n", t
->parses
, ret
);
887 (failed
> oldfailed
) ? VT100_RED
"failed!" VT100_RESET
888 : VT100_GREEN
"OK" VT100_RESET
);
890 printf("%s", (failed
> oldfailed
) ? "failed!" : "OK");
893 printf(" (%u)", failed
);
898 static struct bgp
*bgp
;
899 static as_t asn
= 100;
906 conf_bgp_debug_neighbor_events
= -1UL;
907 conf_bgp_debug_packet
= -1UL;
908 conf_bgp_debug_as4
= -1UL;
909 term_bgp_debug_neighbor_events
= -1UL;
910 term_bgp_debug_packet
= -1UL;
911 term_bgp_debug_as4
= -1UL;
914 master
= thread_master_create(NULL
);
915 bgp_master_init(master
, BGP_SOCKET_SNDBUF_SIZE
, list_new());
916 vrf_init(NULL
, NULL
, NULL
, NULL
, NULL
);
917 bgp_option_set(BGP_OPT_NO_LISTEN
);
921 bgp_pth_ka
->running
= true;
923 if (fileno(stdout
) >= 0)
924 tty
= isatty(fileno(stdout
));
926 if (bgp_get(&bgp
, &asn
, NULL
, BGP_INSTANCE_TYPE_DEFAULT
) < 0)
929 peer
= peer_create_accept(bgp
);
930 peer
->host
= (char *)"foo";
932 for (i
= AFI_IP
; i
< AFI_MAX
; i
++)
933 for (j
= SAFI_UNICAST
; j
< SAFI_MAX
; j
++) {
935 peer
->afc_adv
[i
][j
] = 1;
938 peer
->curr
= stream_new(BGP_MAX_PACKET_SIZE
);
941 while (mp_segments
[i
].name
)
942 parse_test(peer
, &mp_segments
[i
++], CAPABILITY
);
944 /* These tests assume mp_segments tests set at least
945 * one of the afc_nego's
948 while (test_segments
[i
].name
)
949 parse_test(peer
, &test_segments
[i
++], CAPABILITY
);
952 while (misc_segments
[i
].name
)
953 parse_test(peer
, &misc_segments
[i
++], CAPABILITY
);
956 while (opt_params
[i
].name
)
957 parse_test(peer
, &opt_params
[i
++], OPT_PARAM
);
959 SET_FLAG(peer
->cap
, PEER_CAP_DYNAMIC_ADV
);
960 peer
->status
= Established
;
963 while (dynamic_cap_msgs
[i
].name
)
964 parse_test(peer
, &dynamic_cap_msgs
[i
++], DYNCAP
);
966 printf("failures: %d\n", failed
);