1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
3 #include <inttypes.h>
4 #include "aolib.h"
5 
6 #define fault(type)	(inj == FAULT_ ## type)
7 static const char *md5_password = "Some evil genius, enemy to mankind, must have been the first contriver.";
8 static const char *ao_password = DEFAULT_TEST_PASSWORD;
9 
10 static union tcp_addr client2;
11 static union tcp_addr client3;
12 
13 static const int test_vrf_ifindex = 200;
14 static const uint8_t test_vrf_tabid = 42;
setup_vrfs(void)15 static void setup_vrfs(void)
16 {
17 	int err;
18 
19 	if (!kernel_config_has(KCONFIG_NET_VRF))
20 		return;
21 
22 	err = add_vrf("ksft-vrf", test_vrf_tabid, test_vrf_ifindex, -1);
23 	if (err)
24 		test_error("Failed to add a VRF: %d", err);
25 
26 	err = link_set_up("ksft-vrf");
27 	if (err)
28 		test_error("Failed to bring up a VRF");
29 
30 	err = ip_route_add_vrf(veth_name, TEST_FAMILY,
31 			       this_ip_addr, this_ip_dest, test_vrf_tabid);
32 	if (err)
33 		test_error("Failed to add a route to VRF: %d", err);
34 }
35 
try_accept(const char * tst_name,unsigned int port,union tcp_addr * md5_addr,uint8_t md5_prefix,union tcp_addr * ao_addr,uint8_t ao_prefix,bool set_ao_required,uint8_t sndid,uint8_t rcvid,uint8_t vrf,const char * cnt_name,test_cnt cnt_expected,int needs_tcp_md5,fault_t inj)36 static void try_accept(const char *tst_name, unsigned int port,
37 		       union tcp_addr *md5_addr, uint8_t md5_prefix,
38 		       union tcp_addr *ao_addr, uint8_t ao_prefix,
39 		       bool set_ao_required,
40 		       uint8_t sndid, uint8_t rcvid, uint8_t vrf,
41 		       const char *cnt_name, test_cnt cnt_expected,
42 		       int needs_tcp_md5, fault_t inj)
43 {
44 	struct tcp_ao_counters ao_cnt1, ao_cnt2;
45 	uint64_t before_cnt = 0, after_cnt = 0; /* silence GCC */
46 	int lsk, err, sk = 0;
47 	time_t timeout;
48 
49 	if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
50 		return;
51 
52 	lsk = test_listen_socket(this_ip_addr, port, 1);
53 
54 	if (md5_addr && test_set_md5(lsk, *md5_addr, md5_prefix, -1, md5_password))
55 		test_error("setsockopt(TCP_MD5SIG_EXT)");
56 
57 	if (ao_addr && test_add_key(lsk, ao_password,
58 				    *ao_addr, ao_prefix, sndid, rcvid))
59 		test_error("setsockopt(TCP_AO_ADD_KEY)");
60 
61 	if (set_ao_required && test_set_ao_flags(lsk, true, false))
62 		test_error("setsockopt(TCP_AO_INFO)");
63 
64 	if (cnt_name)
65 		before_cnt = netstat_get_one(cnt_name, NULL);
66 	if (ao_addr && test_get_tcp_ao_counters(lsk, &ao_cnt1))
67 		test_error("test_get_tcp_ao_counters()");
68 
69 	synchronize_threads(); /* preparations done */
70 
71 	timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
72 	err = test_wait_fd(lsk, timeout, 0);
73 	synchronize_threads(); /* connect()/accept() timeouts */
74 	if (err == -ETIMEDOUT) {
75 		if (!fault(TIMEOUT))
76 			test_fail("timed out for accept()");
77 	} else if (err < 0) {
78 		test_error("test_wait_fd()");
79 	} else {
80 		if (fault(TIMEOUT))
81 			test_fail("ready to accept");
82 
83 		sk = accept(lsk, NULL, NULL);
84 		if (sk < 0) {
85 			test_error("accept()");
86 		} else {
87 			if (fault(TIMEOUT))
88 				test_fail("%s: accepted", tst_name);
89 		}
90 	}
91 
92 	if (ao_addr && test_get_tcp_ao_counters(lsk, &ao_cnt2))
93 		test_error("test_get_tcp_ao_counters()");
94 	close(lsk);
95 
96 	if (!cnt_name) {
97 		test_ok("%s: no counter checks", tst_name);
98 		goto out;
99 	}
100 
101 	after_cnt = netstat_get_one(cnt_name, NULL);
102 
103 	if (after_cnt <= before_cnt) {
104 		test_fail("%s: %s counter did not increase: %" PRIu64 " <= %" PRIu64,
105 				tst_name, cnt_name, after_cnt, before_cnt);
106 	} else {
107 		test_ok("%s: counter %s increased %" PRIu64 " => %" PRIu64,
108 			tst_name, cnt_name, before_cnt, after_cnt);
109 	}
110 	if (ao_addr)
111 		test_tcp_ao_counters_cmp(tst_name, &ao_cnt1, &ao_cnt2, cnt_expected);
112 
113 out:
114 	synchronize_threads(); /* test_kill_sk() */
115 	if (sk > 0)
116 		test_kill_sk(sk);
117 }
118 
server_add_routes(void)119 static void server_add_routes(void)
120 {
121 	int family = TEST_FAMILY;
122 
123 	synchronize_threads(); /* client_add_ips() */
124 
125 	if (ip_route_add(veth_name, family, this_ip_addr, client2))
126 		test_error("Failed to add route");
127 	if (ip_route_add(veth_name, family, this_ip_addr, client3))
128 		test_error("Failed to add route");
129 }
130 
server_add_fail_tests(unsigned int * port)131 static void server_add_fail_tests(unsigned int *port)
132 {
133 	union tcp_addr addr_any = {};
134 
135 	try_accept("TCP-AO established: add TCP-MD5 key", (*port)++, NULL, 0,
136 		   &addr_any, 0, 0, 100, 100, 0, "TCPAOGood", TEST_CNT_GOOD,
137 		   1, 0);
138 	try_accept("TCP-MD5 established: add TCP-AO key", (*port)++, &addr_any,
139 		   0, NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
140 	try_accept("non-signed established: add TCP-AO key", (*port)++, NULL, 0,
141 		   NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
142 }
143 
server_vrf_tests(unsigned int * port)144 static void server_vrf_tests(unsigned int *port)
145 {
146 	setup_vrfs();
147 }
148 
server_fn(void * arg)149 static void *server_fn(void *arg)
150 {
151 	unsigned int port = test_server_port;
152 	union tcp_addr addr_any = {};
153 
154 	server_add_routes();
155 
156 	try_accept("AO server (INADDR_ANY): AO client", port++, NULL, 0,
157 		   &addr_any, 0, 0, 100, 100, 0, "TCPAOGood",
158 		   TEST_CNT_GOOD, 0, 0);
159 	try_accept("AO server (INADDR_ANY): MD5 client", port++, NULL, 0,
160 		   &addr_any, 0, 0, 100, 100, 0, "TCPMD5Unexpected",
161 		   0, 1, FAULT_TIMEOUT);
162 	try_accept("AO server (INADDR_ANY): no sign client", port++, NULL, 0,
163 		   &addr_any, 0, 0, 100, 100, 0, "TCPAORequired",
164 		   TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
165 	try_accept("AO server (AO_REQUIRED): AO client", port++, NULL, 0,
166 		   &this_ip_dest, TEST_PREFIX, true,
167 		   100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 0, 0);
168 	try_accept("AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
169 		   &this_ip_dest, TEST_PREFIX, true,
170 		   100, 100, 0, "TCPAORequired",
171 		   TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
172 
173 	try_accept("MD5 server (INADDR_ANY): AO client", port++, &addr_any, 0,
174 		   NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
175 		   0, 1, FAULT_TIMEOUT);
176 	try_accept("MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
177 		   NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
178 	try_accept("MD5 server (INADDR_ANY): no sign client", port++, &addr_any,
179 		   0, NULL, 0, 0, 0, 0, 0, "TCPMD5NotFound",
180 		   0, 1, FAULT_TIMEOUT);
181 
182 	try_accept("no sign server: AO client", port++, NULL, 0,
183 		   NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
184 		   TEST_CNT_AO_KEY_NOT_FOUND, 0, FAULT_TIMEOUT);
185 	try_accept("no sign server: MD5 client", port++, NULL, 0,
186 		   NULL, 0, 0, 0, 0, 0, "TCPMD5Unexpected",
187 		   0, 1, FAULT_TIMEOUT);
188 	try_accept("no sign server: no sign client", port++, NULL, 0,
189 		   NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
190 
191 	try_accept("AO+MD5 server: AO client (matching)", port++,
192 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
193 		   100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 1, 0);
194 	try_accept("AO+MD5 server: AO client (misconfig, matching MD5)", port++,
195 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
196 		   100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
197 		   1, FAULT_TIMEOUT);
198 	try_accept("AO+MD5 server: AO client (misconfig, non-matching)", port++,
199 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
200 		   100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
201 		   1, FAULT_TIMEOUT);
202 	try_accept("AO+MD5 server: MD5 client (matching)", port++,
203 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
204 		   100, 100, 0, NULL, 0, 1, 0);
205 	try_accept("AO+MD5 server: MD5 client (misconfig, matching AO)", port++,
206 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
207 		   100, 100, 0, "TCPMD5Unexpected", 0, 1, FAULT_TIMEOUT);
208 	try_accept("AO+MD5 server: MD5 client (misconfig, non-matching)", port++,
209 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
210 		   100, 100, 0, "TCPMD5Unexpected", 0, 1, FAULT_TIMEOUT);
211 	try_accept("AO+MD5 server: no sign client (unmatched)", port++,
212 		   &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
213 		   100, 100, 0, "CurrEstab", 0, 1, 0);
214 	try_accept("AO+MD5 server: no sign client (misconfig, matching AO)",
215 		   port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
216 		   100, 100, 0, "TCPAORequired",
217 		   TEST_CNT_AO_REQUIRED, 1, FAULT_TIMEOUT);
218 	try_accept("AO+MD5 server: no sign client (misconfig, matching MD5)",
219 		   port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
220 		   100, 100, 0, "TCPMD5NotFound", 0, 1, FAULT_TIMEOUT);
221 
222 	try_accept("AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
223 		   port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
224 		   100, 100, 0, NULL, 0, 1, FAULT_TIMEOUT);
225 	try_accept("AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
226 		   port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
227 		   100, 100, 0, NULL, 0, 1, FAULT_TIMEOUT);
228 
229 	server_add_fail_tests(&port);
230 
231 	server_vrf_tests(&port);
232 
233 	/* client exits */
234 	synchronize_threads();
235 	return NULL;
236 }
237 
client_bind(int sk,union tcp_addr bind_addr)238 static int client_bind(int sk, union tcp_addr bind_addr)
239 {
240 #ifdef IPV6_TEST
241 	struct sockaddr_in6 addr = {
242 		.sin6_family	= AF_INET6,
243 		.sin6_port	= 0,
244 		.sin6_addr	= bind_addr.a6,
245 	};
246 #else
247 	struct sockaddr_in addr = {
248 		.sin_family	= AF_INET,
249 		.sin_port	= 0,
250 		.sin_addr	= bind_addr.a4,
251 	};
252 #endif
253 	return bind(sk, &addr, sizeof(addr));
254 }
255 
try_connect(const char * tst_name,unsigned int port,union tcp_addr * md5_addr,uint8_t md5_prefix,union tcp_addr * ao_addr,uint8_t ao_prefix,uint8_t sndid,uint8_t rcvid,uint8_t vrf,fault_t inj,int needs_tcp_md5,union tcp_addr * bind_addr)256 static void try_connect(const char *tst_name, unsigned int port,
257 		       union tcp_addr *md5_addr, uint8_t md5_prefix,
258 		       union tcp_addr *ao_addr, uint8_t ao_prefix,
259 		       uint8_t sndid, uint8_t rcvid, uint8_t vrf,
260 		       fault_t inj, int needs_tcp_md5, union tcp_addr *bind_addr)
261 {
262 	time_t timeout;
263 	int sk, ret;
264 
265 	if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
266 		return;
267 
268 	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
269 	if (sk < 0)
270 		test_error("socket()");
271 
272 	if (bind_addr && client_bind(sk, *bind_addr))
273 		test_error("bind()");
274 
275 	if (md5_addr && test_set_md5(sk, *md5_addr, md5_prefix, -1, md5_password))
276 		test_error("setsockopt(TCP_MD5SIG_EXT)");
277 
278 	if (ao_addr && test_add_key(sk, ao_password, *ao_addr,
279 				    ao_prefix, sndid, rcvid))
280 		test_error("setsockopt(TCP_AO_ADD_KEY)");
281 
282 	synchronize_threads(); /* preparations done */
283 
284 	timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
285 	ret = _test_connect_socket(sk, this_ip_dest, port, timeout);
286 
287 	synchronize_threads(); /* connect()/accept() timeouts */
288 	if (ret < 0) {
289 		if (fault(KEYREJECT) && ret == -EKEYREJECTED)
290 			test_ok("%s: connect() was prevented", tst_name);
291 		else if (ret == -ETIMEDOUT && fault(TIMEOUT))
292 			test_ok("%s", tst_name);
293 		else if (ret == -ECONNREFUSED &&
294 				(fault(TIMEOUT) || fault(KEYREJECT)))
295 			test_ok("%s: refused to connect", tst_name);
296 		else
297 			test_error("%s: connect() returned %d", tst_name, ret);
298 		goto out;
299 	}
300 
301 	if (fault(TIMEOUT) || fault(KEYREJECT))
302 		test_fail("%s: connected", tst_name);
303 	else
304 		test_ok("%s: connected", tst_name);
305 
306 out:
307 	synchronize_threads(); /* test_kill_sk() */
308 	/* _test_connect_socket() cleans up on failure */
309 	if (ret > 0)
310 		test_kill_sk(sk);
311 }
312 
313 #define PREINSTALL_MD5_FIRST	BIT(0)
314 #define PREINSTALL_AO		BIT(1)
315 #define POSTINSTALL_AO		BIT(2)
316 #define PREINSTALL_MD5		BIT(3)
317 #define POSTINSTALL_MD5		BIT(4)
318 
try_add_key_vrf(int sk,union tcp_addr in_addr,uint8_t prefix,int vrf,uint8_t sndid,uint8_t rcvid,bool set_ao_required)319 static int try_add_key_vrf(int sk, union tcp_addr in_addr, uint8_t prefix,
320 			   int vrf, uint8_t sndid, uint8_t rcvid,
321 			   bool set_ao_required)
322 {
323 	uint8_t keyflags = 0;
324 
325 	if (vrf >= 0)
326 		keyflags |= TCP_AO_KEYF_IFINDEX;
327 	else
328 		vrf = 0;
329 	if (set_ao_required) {
330 		int err = test_set_ao_flags(sk, true, 0);
331 
332 		if (err)
333 			return err;
334 	}
335 	return test_add_key_vrf(sk, ao_password, keyflags, in_addr, prefix,
336 				(uint8_t)vrf, sndid, rcvid);
337 }
338 
test_continue(const char * tst_name,int err,fault_t inj,bool added_ao)339 static bool test_continue(const char *tst_name, int err,
340 			  fault_t inj, bool added_ao)
341 {
342 	bool expected_to_fail;
343 
344 	expected_to_fail = fault(PREINSTALL_AO) && added_ao;
345 	expected_to_fail |= fault(PREINSTALL_MD5) && !added_ao;
346 
347 	if (!err) {
348 		if (!expected_to_fail)
349 			return true;
350 		test_fail("%s: setsockopt()s were expected to fail", tst_name);
351 		return false;
352 	}
353 	if (err != -EKEYREJECTED || !expected_to_fail) {
354 		test_error("%s: setsockopt(%s) = %d", tst_name,
355 			   added_ao ? "TCP_AO_ADD_KEY" : "TCP_MD5SIG_EXT", err);
356 		return false;
357 	}
358 	test_ok("%s: prefailed as expected: %m", tst_name);
359 	return false;
360 }
361 
open_add(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,bool set_ao_required,uint8_t sndid,uint8_t rcvid,fault_t inj)362 static int open_add(const char *tst_name, unsigned int port,
363 		    unsigned int strategy,
364 		    union tcp_addr md5_addr, uint8_t md5_prefix, int md5_vrf,
365 		    union tcp_addr ao_addr, uint8_t ao_prefix,
366 		    int ao_vrf, bool set_ao_required,
367 		    uint8_t sndid, uint8_t rcvid,
368 		    fault_t inj)
369 {
370 	int sk;
371 
372 	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
373 	if (sk < 0)
374 		test_error("socket()");
375 
376 	if (client_bind(sk, this_ip_addr))
377 		test_error("bind()");
378 
379 	if (strategy & PREINSTALL_MD5_FIRST) {
380 		if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password))
381 			test_error("setsockopt(TCP_MD5SIG_EXT)");
382 	}
383 
384 	if (strategy & PREINSTALL_AO) {
385 		int err = try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
386 					  sndid, rcvid, set_ao_required);
387 
388 		if (!test_continue(tst_name, err, inj, true)) {
389 			close(sk);
390 			return -1;
391 		}
392 	}
393 
394 	if (strategy & PREINSTALL_MD5) {
395 		errno = 0;
396 		test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password);
397 		if (!test_continue(tst_name, -errno, inj, false)) {
398 			close(sk);
399 			return -1;
400 		}
401 	}
402 
403 	return sk;
404 }
405 
try_to_preadd(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,bool set_ao_required,uint8_t sndid,uint8_t rcvid,int needs_tcp_md5,int needs_vrf,fault_t inj)406 static void try_to_preadd(const char *tst_name, unsigned int port,
407 			  unsigned int strategy,
408 			  union tcp_addr md5_addr, uint8_t md5_prefix,
409 			  int md5_vrf,
410 			  union tcp_addr ao_addr, uint8_t ao_prefix,
411 			  int ao_vrf, bool set_ao_required,
412 			  uint8_t sndid, uint8_t rcvid,
413 			  int needs_tcp_md5, int needs_vrf, fault_t inj)
414 {
415 	int sk;
416 
417 	if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
418 		return;
419 	if (needs_vrf && should_skip_test(tst_name, KCONFIG_NET_VRF))
420 		return;
421 
422 	sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
423 		      ao_addr, ao_prefix, ao_vrf, set_ao_required,
424 		      sndid, rcvid, inj);
425 	if (sk < 0)
426 		return;
427 
428 	test_ok("%s", tst_name);
429 	close(sk);
430 }
431 
try_to_add(const char * tst_name,unsigned int port,unsigned int strategy,union tcp_addr md5_addr,uint8_t md5_prefix,int md5_vrf,union tcp_addr ao_addr,uint8_t ao_prefix,int ao_vrf,uint8_t sndid,uint8_t rcvid,int needs_tcp_md5,fault_t inj)432 static void try_to_add(const char *tst_name, unsigned int port,
433 		       unsigned int strategy,
434 		       union tcp_addr md5_addr, uint8_t md5_prefix,
435 		       int md5_vrf,
436 		       union tcp_addr ao_addr, uint8_t ao_prefix,
437 		       int ao_vrf, uint8_t sndid, uint8_t rcvid,
438 		       int needs_tcp_md5, fault_t inj)
439 {
440 	time_t timeout;
441 	int sk, ret;
442 
443 	if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
444 		return;
445 
446 	sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
447 		      ao_addr, ao_prefix, ao_vrf, 0, sndid, rcvid, inj);
448 	if (sk < 0)
449 		return;
450 
451 	synchronize_threads(); /* preparations done */
452 
453 	timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
454 	ret = _test_connect_socket(sk, this_ip_dest, port, timeout);
455 
456 	synchronize_threads(); /* connect()/accept() timeouts */
457 	if (ret <= 0) {
458 		test_error("%s: connect() returned %d", tst_name, ret);
459 		goto out;
460 	}
461 
462 	if (strategy & POSTINSTALL_MD5) {
463 		if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password)) {
464 			if (fault(POSTINSTALL)) {
465 				test_ok("%s: postfailed as expected", tst_name);
466 				goto out;
467 			} else {
468 				test_error("setsockopt(TCP_MD5SIG_EXT)");
469 			}
470 		} else if (fault(POSTINSTALL)) {
471 			test_fail("%s: post setsockopt() was expected to fail", tst_name);
472 			goto out;
473 		}
474 	}
475 
476 	if (strategy & POSTINSTALL_AO) {
477 		if (try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
478 				   sndid, rcvid, 0)) {
479 			if (fault(POSTINSTALL)) {
480 				test_ok("%s: postfailed as expected", tst_name);
481 				goto out;
482 			} else {
483 				test_error("setsockopt(TCP_AO_ADD_KEY)");
484 			}
485 		} else if (fault(POSTINSTALL)) {
486 			test_fail("%s: post setsockopt() was expected to fail", tst_name);
487 			goto out;
488 		}
489 	}
490 
491 out:
492 	synchronize_threads(); /* test_kill_sk() */
493 	/* _test_connect_socket() cleans up on failure */
494 	if (ret > 0)
495 		test_kill_sk(sk);
496 }
497 
client_add_ip(union tcp_addr * client,const char * ip)498 static void client_add_ip(union tcp_addr *client, const char *ip)
499 {
500 	int err, family = TEST_FAMILY;
501 
502 	if (inet_pton(family, ip, client) != 1)
503 		test_error("Can't convert ip address %s", ip);
504 
505 	err = ip_addr_add(veth_name, family, *client, TEST_PREFIX);
506 	if (err)
507 		test_error("Failed to add ip address: %d", err);
508 }
509 
client_add_ips(void)510 static void client_add_ips(void)
511 {
512 	client_add_ip(&client2, __TEST_CLIENT_IP(2));
513 	client_add_ip(&client3, __TEST_CLIENT_IP(3));
514 	synchronize_threads(); /* server_add_routes() */
515 }
516 
client_add_fail_tests(unsigned int * port)517 static void client_add_fail_tests(unsigned int *port)
518 {
519 	try_to_add("TCP-AO established: add TCP-MD5 key",
520 		   (*port)++, POSTINSTALL_MD5 | PREINSTALL_AO,
521 		   this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
522 		   100, 100, 1, FAULT_POSTINSTALL);
523 	try_to_add("TCP-MD5 established: add TCP-AO key",
524 		   (*port)++, PREINSTALL_MD5 | POSTINSTALL_AO,
525 		   this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
526 		   100, 100, 1, FAULT_POSTINSTALL);
527 	try_to_add("non-signed established: add TCP-AO key",
528 		   (*port)++, POSTINSTALL_AO,
529 		   this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
530 		   100, 100, 0, FAULT_POSTINSTALL);
531 
532 	try_to_add("TCP-AO key intersects with existing TCP-MD5 key",
533 		   (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
534 		   this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
535 		   100, 100, 1, FAULT_PREINSTALL_AO);
536 	try_to_add("TCP-MD5 key intersects with existing TCP-AO key",
537 		   (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
538 		   this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
539 		   100, 100, 1, FAULT_PREINSTALL_MD5);
540 
541 	try_to_preadd("TCP-MD5 key + TCP-AO required",
542 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
543 		      this_ip_addr, TEST_PREFIX, -1,
544 		      this_ip_addr, TEST_PREFIX, -1, true,
545 		      100, 100, 1, 0, FAULT_PREINSTALL_AO);
546 	try_to_preadd("TCP-AO required on socket + TCP-MD5 key",
547 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
548 		      this_ip_addr, TEST_PREFIX, -1,
549 		      this_ip_addr, TEST_PREFIX, -1, true,
550 		      100, 100, 1, 0, FAULT_PREINSTALL_MD5);
551 }
552 
client_vrf_tests(unsigned int * port)553 static void client_vrf_tests(unsigned int *port)
554 {
555 	setup_vrfs();
556 
557 	/* The following restrictions for setsockopt()s are expected:
558 	 *
559 	 * |--------------|-----------------|-------------|-------------|
560 	 * |              | MD5 key without |   MD5 key   |   MD5 key   |
561 	 * |              |     l3index     |  l3index=0  |  l3index=N  |
562 	 * |--------------|-----------------|-------------|-------------|
563 	 * |  TCP-AO key  |                 |             |             |
564 	 * |  without     |     reject      |    reject   |    reject   |
565 	 * |  l3index     |                 |             |             |
566 	 * |--------------|-----------------|-------------|-------------|
567 	 * |  TCP-AO key  |                 |             |             |
568 	 * |  l3index=0   |     reject      |    reject   |    allow    |
569 	 * |--------------|-----------------|-------------|-------------|
570 	 * |  TCP-AO key  |                 |             |             |
571 	 * |  l3index=N   |     reject      |    allow    |    reject   |
572 	 * |--------------|-----------------|-------------|-------------|
573 	 */
574 	try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (no l3index)",
575 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
576 		      this_ip_addr, TEST_PREFIX, -1,
577 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
578 		      1, 1, FAULT_PREINSTALL_MD5);
579 	try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (no l3index)",
580 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
581 		      this_ip_addr, TEST_PREFIX, -1,
582 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
583 		      1, 1, FAULT_PREINSTALL_AO);
584 	try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=0)",
585 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
586 		      this_ip_addr, TEST_PREFIX, 0,
587 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
588 		      1, 1, FAULT_PREINSTALL_MD5);
589 	try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (no l3index)",
590 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
591 		      this_ip_addr, TEST_PREFIX, 0,
592 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
593 		      1, 1, FAULT_PREINSTALL_AO);
594 	try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=N)",
595 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
596 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
597 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
598 		      1, 1, FAULT_PREINSTALL_MD5);
599 	try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (no l3index)",
600 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
601 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
602 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
603 		      1, 1, FAULT_PREINSTALL_AO);
604 
605 	try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (no l3index)",
606 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
607 		      this_ip_addr, TEST_PREFIX, -1,
608 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
609 		      1, 1, FAULT_PREINSTALL_MD5);
610 	try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=0)",
611 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
612 		      this_ip_addr, TEST_PREFIX, -1,
613 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
614 		      1, 1, FAULT_PREINSTALL_AO);
615 	try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=0)",
616 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
617 		      this_ip_addr, TEST_PREFIX, 0,
618 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
619 		      1, 1, FAULT_PREINSTALL_MD5);
620 	try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=0)",
621 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
622 		      this_ip_addr, TEST_PREFIX, 0,
623 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
624 		      1, 1, FAULT_PREINSTALL_AO);
625 	try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=N)",
626 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
627 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
628 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
629 		      1, 1, 0);
630 	try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=0)",
631 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
632 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
633 		      this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
634 		      1, 1, 0);
635 
636 	try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (no l3index)",
637 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
638 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
639 		      this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
640 		      1, 1, FAULT_PREINSTALL_MD5);
641 	try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=N)",
642 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
643 		      this_ip_addr, TEST_PREFIX, -1,
644 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
645 		      1, 1, FAULT_PREINSTALL_AO);
646 	try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=0)",
647 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
648 		      this_ip_addr, TEST_PREFIX, 0,
649 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
650 		      1, 1, 0);
651 	try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=N)",
652 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
653 		      this_ip_addr, TEST_PREFIX, 0,
654 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
655 		      1, 1, 0);
656 	try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=N)",
657 		      (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
658 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
659 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
660 		      1, 1, FAULT_PREINSTALL_MD5);
661 	try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=N)",
662 		      (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
663 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
664 		      this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
665 		      1, 1, FAULT_PREINSTALL_AO);
666 }
667 
client_fn(void * arg)668 static void *client_fn(void *arg)
669 {
670 	unsigned int port = test_server_port;
671 	union tcp_addr addr_any = {};
672 
673 	client_add_ips();
674 
675 	try_connect("AO server (INADDR_ANY): AO client", port++, NULL, 0,
676 		    &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
677 	trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, this_ip_addr,
678 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
679 	try_connect("AO server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
680 		    NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
681 	trace_hash_event_expect(TCP_HASH_AO_REQUIRED, this_ip_addr,
682 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
683 	try_connect("AO server (INADDR_ANY): unsigned client", port++, NULL, 0,
684 		    NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
685 	try_connect("AO server (AO_REQUIRED): AO client", port++, NULL, 0,
686 		    &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
687 	trace_hash_event_expect(TCP_HASH_AO_REQUIRED, client2,
688 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
689 	try_connect("AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
690 		    NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &client2);
691 
692 	trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
693 			      -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
694 	try_connect("MD5 server (INADDR_ANY): AO client", port++, NULL, 0,
695 		   &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
696 	try_connect("MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
697 		   NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
698 	trace_hash_event_expect(TCP_HASH_MD5_REQUIRED, this_ip_addr,
699 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
700 	try_connect("MD5 server (INADDR_ANY): no sign client", port++, NULL, 0,
701 		   NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
702 
703 	trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
704 			      -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
705 	try_connect("no sign server: AO client", port++, NULL, 0,
706 		   &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
707 	trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, this_ip_addr,
708 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
709 	try_connect("no sign server: MD5 client", port++, &addr_any, 0,
710 		   NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
711 	try_connect("no sign server: no sign client", port++, NULL, 0,
712 		   NULL, 0, 100, 100, 0, 0, 0, &this_ip_addr);
713 
714 	try_connect("AO+MD5 server: AO client (matching)", port++, NULL, 0,
715 		   &addr_any, 0, 100, 100, 0, 0, 1, &client2);
716 	trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, this_ip_addr, this_ip_dest,
717 			      -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
718 	try_connect("AO+MD5 server: AO client (misconfig, matching MD5)",
719 		   port++, NULL, 0, &addr_any, 0, 100, 100, 0,
720 		   FAULT_TIMEOUT, 1, &this_ip_addr);
721 	trace_ao_event_expect(TCP_AO_KEY_NOT_FOUND, client3, this_ip_dest,
722 			      -1, port, 0, 0, 1, 0, 0, 0, 100, 100, -1);
723 	try_connect("AO+MD5 server: AO client (misconfig, non-matching)",
724 		   port++, NULL, 0, &addr_any, 0, 100, 100, 0,
725 		   FAULT_TIMEOUT, 1, &client3);
726 	try_connect("AO+MD5 server: MD5 client (matching)", port++, &addr_any, 0,
727 		   NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
728 	trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, client2,
729 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
730 	try_connect("AO+MD5 server: MD5 client (misconfig, matching AO)",
731 		   port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
732 		   1, &client2);
733 	trace_hash_event_expect(TCP_HASH_MD5_UNEXPECTED, client3,
734 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
735 	try_connect("AO+MD5 server: MD5 client (misconfig, non-matching)",
736 		   port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
737 		   1, &client3);
738 	try_connect("AO+MD5 server: no sign client (unmatched)",
739 		   port++, NULL, 0, NULL, 0, 100, 100, 0, 0, 1, &client3);
740 	trace_hash_event_expect(TCP_HASH_AO_REQUIRED, client2,
741 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
742 	try_connect("AO+MD5 server: no sign client (misconfig, matching AO)",
743 		   port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
744 		   1, &client2);
745 	trace_hash_event_expect(TCP_HASH_MD5_REQUIRED, this_ip_addr,
746 				this_ip_dest, -1, port, 0, 0, 1, 0, 0, 0);
747 	try_connect("AO+MD5 server: no sign client (misconfig, matching MD5)",
748 		   port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
749 		   1, &this_ip_addr);
750 
751 	try_connect("AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
752 		   port++, &this_ip_addr, TEST_PREFIX,
753 		   &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
754 		   1, &this_ip_addr);
755 	try_connect("AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
756 		   port++, &this_ip_addr, TEST_PREFIX,
757 		   &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
758 		   1, &client2);
759 
760 	client_add_fail_tests(&port);
761 	client_vrf_tests(&port);
762 
763 	return NULL;
764 }
765 
main(int argc,char * argv[])766 int main(int argc, char *argv[])
767 {
768 	test_init(73, server_fn, client_fn);
769 	return 0;
770 }
771