xref: /openbsd-src/regress/usr.sbin/bgpd/unittests/rde_flowspec_test.c (revision 9a21c8c8e850f6f4111294ab1cc69f27f82ab3af)
1 /*	$OpenBSD: rde_flowspec_test.c,v 1.2 2023/04/18 06:41:00 claudio Exp $ */
2 
3 /*
4  * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <err.h>
20 #include <stdio.h>
21 
22 #include "bgpd.h"
23 #include "rde.h"
24 
25 const uint8_t ordered0[] = { 0x01, 0x00, 0x02, 0x00, 0x03, 0x80, 0x00 };
26 const uint8_t ordered1[] = { 0x02, 0x00, 0x01, 0x00, 0x03, 0x80, 0x00 };
27 const uint8_t ordered2[] = { 0x02, 0x00, 0x03, 0x80, 0x00, 0x01, 0x00 };
28 const uint8_t ordered3[] = { 0x01, 0x00, 0x01, 0x00, 0x03, 0x80, 0x00 };
29 
30 const uint8_t minmax0[] = { 0x00, 0x00 };
31 const uint8_t minmax1[] = { 0x0e, 0x00 };
32 const uint8_t minmax2[] = { 0xfe, 0x00 };
33 
34 const uint8_t flow[] = { 0x0d, 0x80, 0x00 };
35 
36 const uint8_t badand[] = { 0x04, 0xc0, 0x00 };
37 const uint8_t goodand[] = { 0x04, 0x00, 0x00, 0xc0, 0x00 };
38 
39 const uint8_t overflow0[] = { 0x04 };
40 const uint8_t overflow1[] = { 0x04, 0x80 };
41 const uint8_t overflow2[] = { 0x04, 0x90, 0x00 };
42 const uint8_t overflow3[] = { 0x04, 0xc0, 0x00, 0x00, 0x00 };
43 const uint8_t overflow4[] = { 0x04, 0x00, 0x00 };
44 const uint8_t overflow5[] = { 0x04, 0x00, 0x00, 0x80 };
45 const uint8_t overflow6[] = { 0x04, 0x10, 0x00, 0x80 };
46 const uint8_t prefix0[] = { 0x01 };
47 const uint8_t prefix1[] = { 0x01, 0x07 };
48 const uint8_t prefix2[] = { 0x01, 0x0a, 0xef };
49 const uint8_t prefix3[] = { 0x01, 0x11, 0xef, 0x00 };
50 const uint8_t prefix4[] = { 0x01, 0x21, 0xef, 0x00, 0x00, 0x01, 0x00 };
51 const uint8_t prefix60[] = { 0x01 };
52 const uint8_t prefix61[] = { 0x01, 0x07 };
53 const uint8_t prefix62[] = { 0x01, 0x10, 0x1 };
54 const uint8_t prefix63[] = { 0x01, 0x10, 0x01, 0x20 };
55 const uint8_t prefix64[] = { 0x01, 0x81, 0x73, 0x20, 0x01 };
56 const uint8_t prefix65[] = { 0x01, 0x80, 0x83, 0x20, 0x01 };
57 const uint8_t prefix66[] = { 0x01, 0x40, 0x40, 0x20, 0x01 };
58 
59 static void
test_flowspec_valid(void)60 test_flowspec_valid(void)
61 {
62 	/* empty NLRI is invalid */
63 	if (flowspec_valid(NULL, 0, 0) != -1)
64 		errx(1, "empty NLRI is not invalid");
65 
66 	/* ensure that type range is checked */
67 	if (flowspec_valid(minmax0, sizeof(minmax0), 0) != -1 ||
68 	    flowspec_valid(minmax1, sizeof(minmax1), 0) != -1 ||
69 	    flowspec_valid(minmax2, sizeof(minmax2), 0) != -1)
70 		errx(1, "out of range type is not invalid");
71 
72 	/* ensure that types are ordered */
73 	if (flowspec_valid(ordered0, sizeof(ordered0), 0) != 0)
74 		errx(1, "in order NLRI is not valid");
75 	if (flowspec_valid(ordered1, sizeof(ordered1), 0) != -1 ||
76 	    flowspec_valid(ordered2, sizeof(ordered2), 0) != -1 ||
77 	    flowspec_valid(ordered3, sizeof(ordered3), 0) != -1)
78 		errx(1, "out of order types are not invalid");
79 
80 	/* flow is only valid in the IPv6 case */
81 	if (flowspec_valid(flow, sizeof(flow), 0) != -1)
82 		errx(1, "FLOW type for IPv4 is not invalid");
83 	if (flowspec_valid(flow, sizeof(flow), 1) != 0)
84 		errx(1, "FLOW type for IPv4 is not valid");
85 
86 	/* first component cannot have and flag set */
87 	if (flowspec_valid(badand, sizeof(badand), 0) != -1)
88 		errx(1, "AND in first element is not invalid");
89 	if (flowspec_valid(goodand, sizeof(goodand), 0) != 0)
90 		errx(1, "AND in other element is not valid");
91 
92 	/* various overflows */
93 	if (flowspec_valid(overflow0, sizeof(overflow0), 0) != -1 ||
94 	    flowspec_valid(overflow1, sizeof(overflow1), 0) != -1 ||
95 	    flowspec_valid(overflow2, sizeof(overflow2), 0) != -1 ||
96 	    flowspec_valid(overflow3, sizeof(overflow3), 0) != -1 ||
97 	    flowspec_valid(overflow4, sizeof(overflow4), 0) != -1 ||
98 	    flowspec_valid(overflow5, sizeof(overflow5), 0) != -1 ||
99 	    flowspec_valid(overflow6, sizeof(overflow6), 0) != -1)
100 		errx(1, "overflow not detected");
101 
102 	if (flowspec_valid(prefix0, sizeof(prefix0), 0) != -1 ||
103 	    flowspec_valid(prefix1, sizeof(prefix1), 0) != -1 ||
104 	    flowspec_valid(prefix2, sizeof(prefix2), 0) != -1 ||
105 	    flowspec_valid(prefix3, sizeof(prefix3), 0) != -1 ||
106 	    flowspec_valid(prefix4, sizeof(prefix4), 0) != -1)
107 		errx(1, "bad prefix encoding is not invalid");
108 
109 	if (flowspec_valid(prefix60, sizeof(prefix60), 1) != -1 ||
110 	    flowspec_valid(prefix61, sizeof(prefix61), 1) != -1 ||
111 	    flowspec_valid(prefix62, sizeof(prefix62), 1) != -1 ||
112 	    flowspec_valid(prefix63, sizeof(prefix63), 1) != -1 ||
113 	    flowspec_valid(prefix64, sizeof(prefix64), 1) != -1 ||
114 	    flowspec_valid(prefix65, sizeof(prefix65), 1) != -1 ||
115 	    flowspec_valid(prefix66, sizeof(prefix66), 1) != -1)
116 		errx(1, "bad IPv6 prefix encoding is not invalid");
117 }
118 
119 static int
do_cmp(const uint8_t * a,int alen,const uint8_t * b,int blen,int is_v6)120 do_cmp(const uint8_t *a, int alen, const uint8_t *b, int blen, int is_v6)
121 {
122 	if (flowspec_cmp(a, alen, b, blen, is_v6) != -1 ||
123 	    flowspec_cmp(b, blen, a, alen, is_v6) != 1)
124 		return -1;
125 	return 0;
126 }
127 
128 const uint8_t cmp1[] = { 0x01, 0x00 };
129 const uint8_t cmp2[] = { 0x02, 0x00 };
130 const uint8_t cmp3[] = { 0x01, 0x00, 0x2, 0x00 };
131 const uint8_t cmp4[] = { 0x04, 0x80, 0x2 };
132 const uint8_t cmp5[] = { 0x04, 0x80, 0x3 };
133 const uint8_t cmp6[] = { 0x04, 0x00, 0x3, 0x80, 0x02 };
134 
135 const uint8_t cmp41[] = { 0x01, 24, 192, 168, 16 };
136 const uint8_t cmp42[] = { 0x01, 24, 192, 168, 32 };
137 const uint8_t cmp43[] = { 0x01, 24, 192, 168, 42 };
138 const uint8_t cmp44[] = { 0x01, 20, 192, 168, 32 };
139 
140 const uint8_t cmp61[] = { 0x01, 48, 0, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0xfe };
141 const uint8_t cmp62[] = { 0x01, 48, 8, 0x01, 0x0d, 0xb8, 0xc0, 0xfe };
142 const uint8_t cmp63[] = { 0x01, 40, 0, 0x20, 0x01, 0x0d, 0xb8, 0xc0 };
143 const uint8_t cmp64[] = { 0x01, 40, 0, 0x20, 0x01, 0x0d, 0xb8, 0xd0 };
144 
145 static void
test_flowspec_cmp(void)146 test_flowspec_cmp(void)
147 {
148 	if (do_cmp(cmp1, sizeof(cmp1), cmp2, sizeof(cmp2), 0) != 0)
149 		errx(1, "cmp on type failed");
150 	if (do_cmp(cmp3, sizeof(cmp3), cmp1, sizeof(cmp1), 0) != 0)
151 		errx(1, "cmp on more components failed");
152 	if (do_cmp(cmp4, sizeof(cmp4), cmp5, sizeof(cmp5), 0) != 0)
153 		errx(1, "cmp on lowest common component failed");
154 	if (do_cmp(cmp6, sizeof(cmp6), cmp5, sizeof(cmp5), 0) != 0)
155 		errx(1, "cmp on lowest common component failed");
156 	if (do_cmp(cmp6, sizeof(cmp6), cmp4, sizeof(cmp4), 0) != 0)
157 		errx(1, "cmp on lowest common component failed");
158 
159 	if (do_cmp(cmp41, sizeof(cmp41), cmp42, sizeof(cmp42), 0) != 0)
160 		errx(1, "cmp 1 on prefix component failed");
161 	if (do_cmp(cmp41, sizeof(cmp41), cmp43, sizeof(cmp43), 0) != 0)
162 		errx(1, "cmp 2 on prefix component failed");
163 	if (do_cmp(cmp41, sizeof(cmp41), cmp44, sizeof(cmp44), 0) != 0)
164 		errx(1, "cmp 3 on prefix component failed");
165 	if (do_cmp(cmp42, sizeof(cmp42), cmp43, sizeof(cmp43), 0) != 0)
166 		errx(1, "cmp 4 on prefix component failed");
167 	if (do_cmp(cmp42, sizeof(cmp42), cmp44, sizeof(cmp44), 0) != 0)
168 		errx(1, "cmp 5 on prefix component failed");
169 	if (do_cmp(cmp43, sizeof(cmp43), cmp44, sizeof(cmp44), 0) != 0)
170 		errx(1, "cmp 6 on prefix component failed");
171 
172 	if (do_cmp(cmp61, sizeof(cmp61), cmp62, sizeof(cmp62), 1) != 0)
173 		errx(1, "cmp 1 on inet6 prefix component failed");
174 	if (do_cmp(cmp61, sizeof(cmp61), cmp63, sizeof(cmp63), 1) != 0)
175 		errx(1, "cmp 1 on inet6 prefix component failed");
176 	if (do_cmp(cmp61, sizeof(cmp61), cmp64, sizeof(cmp64), 1) != 0)
177 		errx(1, "cmp 1 on inet6 prefix component failed");
178 	if (do_cmp(cmp63, sizeof(cmp63), cmp64, sizeof(cmp64), 1) != 0)
179 		errx(1, "cmp 1 on inet6 prefix component failed");
180 }
181 
182 int
main(int argc,char ** argv)183 main(int argc, char **argv)
184 {
185 	test_flowspec_valid();
186 	test_flowspec_cmp();
187 	printf("OK\n");
188 	return 0;
189 }
190 
191 __dead void
fatalx(const char * emsg,...)192 fatalx(const char *emsg, ...)
193 {
194 	va_list ap;
195 	va_start(ap, emsg);
196 	verrx(2, emsg, ap);
197 }
198 
199