brintos

brintos / linux-shallow public Read only

0
0
Text · 24.6 KiB · 084db4e Raw
836 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Author: Dmitry Safonov <dima@arista.com> */3#include <inttypes.h>4#include "../../../../include/linux/kernel.h"5#include "aolib.h"6 7static union tcp_addr tcp_md5_client;8 9static int test_port = 7788;10static void make_listen(int sk)11{12	sockaddr_af addr;13 14	tcp_addr_to_sockaddr_in(&addr, &this_ip_addr, htons(test_port++));15	if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0)16		test_error("bind()");17	if (listen(sk, 1))18		test_error("listen()");19}20 21static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,22				const char *tst)23{24	struct tcp_ao_info_opt tmp = {};25	socklen_t len = sizeof(tmp);26 27	if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))28		test_error("getsockopt(TCP_AO_INFO) failed");29 30#define __cmp_ao(member)							\31do {										\32	if (info->member != tmp.member) {					\33		test_fail("%s: getsockopt(): " __stringify(member) " %" PRIu64 " != %" PRIu64,	\34			  tst, (uint64_t)info->member, (uint64_t)tmp.member);	\35		return;								\36	}									\37} while(0)38	if (info->set_current)39		__cmp_ao(current_key);40	if (info->set_rnext)41		__cmp_ao(rnext);42	if (info->set_counters) {43		__cmp_ao(pkt_good);44		__cmp_ao(pkt_bad);45		__cmp_ao(pkt_key_not_found);46		__cmp_ao(pkt_ao_required);47		__cmp_ao(pkt_dropped_icmp);48	}49	__cmp_ao(ao_required);50	__cmp_ao(accept_icmps);51 52	test_ok("AO info get: %s", tst);53#undef __cmp_ao54}55 56static void __setsockopt_checked(int sk, int optname, bool get,57				 void *optval, socklen_t *len,58				 int err, const char *tst, const char *tst2)59{60	int ret;61 62	if (!tst)63		tst = "";64	if (!tst2)65		tst2 = "";66 67	errno = 0;68	if (get)69		ret = getsockopt(sk, IPPROTO_TCP, optname, optval, len);70	else71		ret = setsockopt(sk, IPPROTO_TCP, optname, optval, *len);72	if (ret == -1) {73		if (errno == err)74			test_ok("%s%s", tst ?: "", tst2 ?: "");75		else76			test_fail("%s%s: %setsockopt() failed",77				  tst, tst2, get ? "g" : "s");78		close(sk);79		return;80	}81 82	if (err) {83		test_fail("%s%s: %setsockopt() was expected to fail with %d",84			  tst, tst2, get ? "g" : "s", err);85	} else {86		test_ok("%s%s", tst ?: "", tst2 ?: "");87		if (optname == TCP_AO_ADD_KEY) {88			test_verify_socket_key(sk, optval);89		} else if (optname == TCP_AO_INFO && !get) {90			test_vefify_ao_info(sk, optval, tst2);91		} else if (optname == TCP_AO_GET_KEYS) {92			if (*len != sizeof(struct tcp_ao_getsockopt))93				test_fail("%s%s: get keys returned wrong tcp_ao_getsockopt size",94					  tst, tst2);95		}96	}97	close(sk);98}99 100static void setsockopt_checked(int sk, int optname, void *optval,101			       int err, const char *tst)102{103	const char *cmd = NULL;104	socklen_t len;105 106	switch (optname) {107	case TCP_AO_ADD_KEY:108		cmd = "key add: ";109		len = sizeof(struct tcp_ao_add);110		break;111	case TCP_AO_DEL_KEY:112		cmd = "key del: ";113		len = sizeof(struct tcp_ao_del);114		break;115	case TCP_AO_INFO:116		cmd = "AO info set: ";117		len = sizeof(struct tcp_ao_info_opt);118		break;119	default:120		break;121	}122 123	__setsockopt_checked(sk, optname, false, optval, &len, err, cmd, tst);124}125 126static int prepare_defs(int cmd, void *optval)127{128	int sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);129 130	if (sk < 0)131		test_error("socket()");132 133	switch (cmd) {134	case TCP_AO_ADD_KEY: {135		struct tcp_ao_add *add = optval;136 137		if (test_prepare_def_key(add, DEFAULT_TEST_PASSWORD, 0, this_ip_dest,138					-1, 0, 100, 100))139			test_error("prepare default tcp_ao_add");140		break;141		}142	case TCP_AO_DEL_KEY: {143		struct tcp_ao_del *del = optval;144 145		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,146				 DEFAULT_TEST_PREFIX, 100, 100))147			test_error("add default key");148		memset(del, 0, sizeof(struct tcp_ao_del));149		del->sndid = 100;150		del->rcvid = 100;151		del->prefix = DEFAULT_TEST_PREFIX;152		tcp_addr_to_sockaddr_in(&del->addr, &this_ip_dest, 0);153		break;154		}155	case TCP_AO_INFO: {156		struct tcp_ao_info_opt *info = optval;157 158		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,159				 DEFAULT_TEST_PREFIX, 100, 100))160			test_error("add default key");161		memset(info, 0, sizeof(struct tcp_ao_info_opt));162		break;163		}164	case TCP_AO_GET_KEYS: {165		struct tcp_ao_getsockopt *get = optval;166 167		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest,168				 DEFAULT_TEST_PREFIX, 100, 100))169			test_error("add default key");170		memset(get, 0, sizeof(struct tcp_ao_getsockopt));171		get->nkeys = 1;172		get->get_all = 1;173		break;174		}175	default:176		test_error("unknown cmd");177	}178 179	return sk;180}181 182static void test_extend(int cmd, bool get, const char *tst, socklen_t under_size)183{184	struct {185		union {186			struct tcp_ao_add add;187			struct tcp_ao_del del;188			struct tcp_ao_getsockopt get;189			struct tcp_ao_info_opt info;190		};191		char *extend[100];192	} tmp_opt;193	socklen_t extended_size = sizeof(tmp_opt);194	int sk;195 196	memset(&tmp_opt, 0, sizeof(tmp_opt));197	sk = prepare_defs(cmd, &tmp_opt);198	__setsockopt_checked(sk, cmd, get, &tmp_opt, &under_size,199			     EINVAL, tst, ": minimum size");200 201	memset(&tmp_opt, 0, sizeof(tmp_opt));202	sk = prepare_defs(cmd, &tmp_opt);203	__setsockopt_checked(sk, cmd, get, &tmp_opt, &extended_size,204			     0, tst, ": extended size");205 206	memset(&tmp_opt, 0, sizeof(tmp_opt));207	sk = prepare_defs(cmd, &tmp_opt);208	__setsockopt_checked(sk, cmd, get, NULL, &extended_size,209			     EFAULT, tst, ": null optval");210 211	if (get) {212		memset(&tmp_opt, 0, sizeof(tmp_opt));213		sk = prepare_defs(cmd, &tmp_opt);214		__setsockopt_checked(sk, cmd, get, &tmp_opt, NULL,215				     EFAULT, tst, ": null optlen");216	}217}218 219static void extend_tests(void)220{221	test_extend(TCP_AO_ADD_KEY, false, "AO add",222		    offsetof(struct tcp_ao_add, key));223	test_extend(TCP_AO_DEL_KEY, false, "AO del",224		    offsetof(struct tcp_ao_del, keyflags));225	test_extend(TCP_AO_INFO, false, "AO set info",226		    offsetof(struct tcp_ao_info_opt, pkt_dropped_icmp));227	test_extend(TCP_AO_INFO, true, "AO get info", -1);228	test_extend(TCP_AO_GET_KEYS, true, "AO get keys", -1);229}230 231static void test_optmem_limit(void)232{233	size_t i, keys_limit, current_optmem = test_get_optmem();234	struct tcp_ao_add ao;235	union tcp_addr net = {};236	int sk;237 238	if (inet_pton(TEST_FAMILY, TEST_NETWORK, &net) != 1)239		test_error("Can't convert ip address %s", TEST_NETWORK);240 241	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);242	keys_limit = current_optmem / KERNEL_TCP_AO_KEY_SZ_ROUND_UP;243	for (i = 0;; i++) {244		union tcp_addr key_peer;245		int err;246 247		key_peer = gen_tcp_addr(net, i + 1);248		tcp_addr_to_sockaddr_in(&ao.addr, &key_peer, 0);249		err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY,250				 &ao, sizeof(ao));251		if (!err) {252			/*253			 * TCP_AO_ADD_KEY should be the same order as the real254			 * sizeof(struct tcp_ao_key) in kernel.255			 */256			if (i <= keys_limit * 10)257				continue;258			test_fail("optmem limit test failed: added %zu key", i);259			break;260		}261		if (i < keys_limit) {262			test_fail("optmem limit test failed: couldn't add %zu key", i);263			break;264		}265		test_ok("optmem limit was hit on adding %zu key", i);266		break;267	}268	close(sk);269}270 271static void test_einval_add_key(void)272{273	struct tcp_ao_add ao;274	int sk;275 276	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);277	ao.keylen = TCP_AO_MAXKEYLEN + 1;278	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too big keylen");279 280	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);281	ao.reserved = 1;282	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "using reserved padding");283 284	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);285	ao.reserved2 = 1;286	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "using reserved2 padding");287 288	/* tcp_ao_verify_ipv{4,6}() checks */289	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);290	ao.addr.ss_family = AF_UNIX;291	memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));292	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "wrong address family");293 294	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);295	tcp_addr_to_sockaddr_in(&ao.addr, &this_ip_dest, 1234);296	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "port (unsupported)");297 298	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);299	ao.prefix = 0;300	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "no prefix, addr");301 302	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);303	ao.prefix = 0;304	memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));305	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "no prefix, any addr");306 307	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);308	ao.prefix = 32;309	memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));310	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "prefix, any addr");311 312	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);313	ao.prefix = 129;314	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too big prefix");315 316	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);317	ao.prefix = 2;318	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "too short prefix");319 320	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);321	ao.keyflags = (uint8_t)(-1);322	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "bad key flags");323 324	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);325	make_listen(sk);326	ao.set_current = 1;327	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current key on a listen socket");328 329	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);330	make_listen(sk);331	ao.set_rnext = 1;332	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add rnext key on a listen socket");333 334	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);335	make_listen(sk);336	ao.set_current = 1;337	ao.set_rnext = 1;338	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "add current+rnext key on a listen socket");339 340	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);341	ao.set_current = 1;342	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current");343 344	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);345	ao.set_rnext = 1;346	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as rnext");347 348	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);349	ao.set_current = 1;350	ao.set_rnext = 1;351	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, 0, "add key and set as current+rnext");352 353	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);354	ao.ifindex = 42;355	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL,356			   "ifindex without TCP_AO_KEYF_IFNINDEX");357 358	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);359	ao.keyflags |= TCP_AO_KEYF_IFINDEX;360	ao.ifindex = 42;361	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EINVAL, "non-existent VRF");362	/*363	 * tcp_md5_do_lookup{,_any_l3index}() are checked in unsigned-md5364	 * see client_vrf_tests().365	 */366 367	test_optmem_limit();368 369	/* tcp_ao_parse_crypto() */370	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);371	ao.maclen = 100;372	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EMSGSIZE, "maclen bigger than TCP hdr");373 374	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);375	strcpy(ao.alg_name, "imaginary hash algo");376	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, ENOENT, "bad algo");377}378 379static void test_einval_del_key(void)380{381	struct tcp_ao_del del;382	int sk;383 384	sk = prepare_defs(TCP_AO_DEL_KEY, &del);385	del.reserved = 1;386	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "using reserved padding");387 388	sk = prepare_defs(TCP_AO_DEL_KEY, &del);389	del.reserved2 = 1;390	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "using reserved2 padding");391 392	sk = prepare_defs(TCP_AO_DEL_KEY, &del);393	make_listen(sk);394	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))395		test_error("add key");396	del.set_current = 1;397	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current key on a listen socket");398 399	sk = prepare_defs(TCP_AO_DEL_KEY, &del);400	make_listen(sk);401	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))402		test_error("add key");403	del.set_rnext = 1;404	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set rnext key on a listen socket");405 406	sk = prepare_defs(TCP_AO_DEL_KEY, &del);407	make_listen(sk);408	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))409		test_error("add key");410	del.set_current = 1;411	del.set_rnext = 1;412	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "del and set current+rnext key on a listen socket");413 414	sk = prepare_defs(TCP_AO_DEL_KEY, &del);415	del.keyflags = (uint8_t)(-1);416	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "bad key flags");417 418	sk = prepare_defs(TCP_AO_DEL_KEY, &del);419	del.ifindex = 42;420	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL,421			   "ifindex without TCP_AO_KEYF_IFNINDEX");422 423	sk = prepare_defs(TCP_AO_DEL_KEY, &del);424	del.keyflags |= TCP_AO_KEYF_IFINDEX;425	del.ifindex = 42;426	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existent VRF");427 428	sk = prepare_defs(TCP_AO_DEL_KEY, &del);429	del.set_current = 1;430	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing current key");431 432	sk = prepare_defs(TCP_AO_DEL_KEY, &del);433	del.set_rnext = 1;434	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing rnext key");435 436	sk = prepare_defs(TCP_AO_DEL_KEY, &del);437	del.set_current = 1;438	del.set_rnext = 1;439	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set non-existing current+rnext key");440 441	sk = prepare_defs(TCP_AO_DEL_KEY, &del);442	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))443		test_error("add key");444	del.set_current = 1;445	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set current key");446 447	sk = prepare_defs(TCP_AO_DEL_KEY, &del);448	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))449		test_error("add key");450	del.set_rnext = 1;451	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set rnext key");452 453	sk = prepare_defs(TCP_AO_DEL_KEY, &del);454	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, DEFAULT_TEST_PREFIX, 0, 0))455		test_error("add key");456	del.set_current = 1;457	del.set_rnext = 1;458	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "set current+rnext key");459 460	sk = prepare_defs(TCP_AO_DEL_KEY, &del);461	del.set_current = 1;462	del.current_key = 100;463	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current key to be removed");464 465	sk = prepare_defs(TCP_AO_DEL_KEY, &del);466	del.set_rnext = 1;467	del.rnext = 100;468	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as rnext key to be removed");469 470	sk = prepare_defs(TCP_AO_DEL_KEY, &del);471	del.set_current = 1;472	del.current_key = 100;473	del.set_rnext = 1;474	del.rnext = 100;475	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "set as current+rnext key to be removed");476 477	sk = prepare_defs(TCP_AO_DEL_KEY, &del);478	del.del_async = 1;479	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, EINVAL, "async on non-listen");480 481	sk = prepare_defs(TCP_AO_DEL_KEY, &del);482	del.sndid = 101;483	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existing sndid");484 485	sk = prepare_defs(TCP_AO_DEL_KEY, &del);486	del.rcvid = 101;487	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "non-existing rcvid");488 489	sk = prepare_defs(TCP_AO_DEL_KEY, &del);490	tcp_addr_to_sockaddr_in(&del.addr, &this_ip_addr, 0);491	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, ENOENT, "incorrect addr");492 493	sk = prepare_defs(TCP_AO_DEL_KEY, &del);494	setsockopt_checked(sk, TCP_AO_DEL_KEY, &del, 0, "correct key delete");495}496 497static void test_einval_ao_info(void)498{499	struct tcp_ao_info_opt info;500	int sk;501 502	sk = prepare_defs(TCP_AO_INFO, &info);503	make_listen(sk);504	info.set_current = 1;505	setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current key on a listen socket");506 507	sk = prepare_defs(TCP_AO_INFO, &info);508	make_listen(sk);509	info.set_rnext = 1;510	setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set rnext key on a listen socket");511 512	sk = prepare_defs(TCP_AO_INFO, &info);513	make_listen(sk);514	info.set_current = 1;515	info.set_rnext = 1;516	setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "set current+rnext key on a listen socket");517 518	sk = prepare_defs(TCP_AO_INFO, &info);519	info.reserved = 1;520	setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "using reserved padding");521 522	sk = prepare_defs(TCP_AO_INFO, &info);523	info.reserved2 = 1;524	setsockopt_checked(sk, TCP_AO_INFO, &info, EINVAL, "using reserved2 padding");525 526	sk = prepare_defs(TCP_AO_INFO, &info);527	info.accept_icmps = 1;528	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "accept_icmps");529 530	sk = prepare_defs(TCP_AO_INFO, &info);531	info.ao_required = 1;532	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "ao required");533 534	if (!should_skip_test("ao required with MD5 key", KCONFIG_TCP_MD5)) {535		sk = prepare_defs(TCP_AO_INFO, &info);536		info.ao_required = 1;537		if (test_set_md5(sk, tcp_md5_client, TEST_PREFIX, -1,538				 "long long secret")) {539			test_error("setsockopt(TCP_MD5SIG_EXT)");540			close(sk);541		} else {542			setsockopt_checked(sk, TCP_AO_INFO, &info, EKEYREJECTED,543					   "ao required with MD5 key");544		}545	}546 547	sk = prepare_defs(TCP_AO_INFO, &info);548	info.set_current = 1;549	setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing current key");550 551	sk = prepare_defs(TCP_AO_INFO, &info);552	info.set_rnext = 1;553	setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing rnext key");554 555	sk = prepare_defs(TCP_AO_INFO, &info);556	info.set_current = 1;557	info.set_rnext = 1;558	setsockopt_checked(sk, TCP_AO_INFO, &info, ENOENT, "set non-existing current+rnext key");559 560	sk = prepare_defs(TCP_AO_INFO, &info);561	info.set_current = 1;562	info.current_key = 100;563	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set current key");564 565	sk = prepare_defs(TCP_AO_INFO, &info);566	info.set_rnext = 1;567	info.rnext = 100;568	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set rnext key");569 570	sk = prepare_defs(TCP_AO_INFO, &info);571	info.set_current = 1;572	info.set_rnext = 1;573	info.current_key = 100;574	info.rnext = 100;575	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set current+rnext key");576 577	sk = prepare_defs(TCP_AO_INFO, &info);578	info.set_counters = 1;579	info.pkt_good = 321;580	info.pkt_bad = 888;581	info.pkt_key_not_found = 654;582	info.pkt_ao_required = 987654;583	info.pkt_dropped_icmp = 10000;584	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "set counters");585 586	sk = prepare_defs(TCP_AO_INFO, &info);587	setsockopt_checked(sk, TCP_AO_INFO, &info, 0, "no-op");588}589 590static void getsockopt_checked(int sk, struct tcp_ao_getsockopt *optval,591			       int err, const char *tst)592{593	socklen_t len = sizeof(struct tcp_ao_getsockopt);594 595	__setsockopt_checked(sk, TCP_AO_GET_KEYS, true, optval, &len, err,596			     "get keys: ", tst);597}598 599static void test_einval_get_keys(void)600{601	struct tcp_ao_getsockopt out;602	int sk;603 604	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);605	if (sk < 0)606		test_error("socket()");607	getsockopt_checked(sk, &out, ENOENT, "no ao_info");608 609	sk = prepare_defs(TCP_AO_GET_KEYS, &out);610	getsockopt_checked(sk, &out, 0, "proper tcp_ao_get_mkts()");611 612	sk = prepare_defs(TCP_AO_GET_KEYS, &out);613	out.pkt_good = 643;614	getsockopt_checked(sk, &out, EINVAL, "set out-only pkt_good counter");615 616	sk = prepare_defs(TCP_AO_GET_KEYS, &out);617	out.pkt_bad = 94;618	getsockopt_checked(sk, &out, EINVAL, "set out-only pkt_bad counter");619 620	sk = prepare_defs(TCP_AO_GET_KEYS, &out);621	out.keyflags = (uint8_t)(-1);622	getsockopt_checked(sk, &out, EINVAL, "bad keyflags");623 624	sk = prepare_defs(TCP_AO_GET_KEYS, &out);625	out.ifindex = 42;626	getsockopt_checked(sk, &out, EINVAL,627			   "ifindex without TCP_AO_KEYF_IFNINDEX");628 629	sk = prepare_defs(TCP_AO_GET_KEYS, &out);630	out.reserved = 1;631	getsockopt_checked(sk, &out, EINVAL, "using reserved field");632 633	sk = prepare_defs(TCP_AO_GET_KEYS, &out);634	out.get_all = 0;635	out.prefix = 0;636	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);637	getsockopt_checked(sk, &out, EINVAL, "no prefix, addr");638 639	sk = prepare_defs(TCP_AO_GET_KEYS, &out);640	out.get_all = 0;641	out.prefix = 0;642	memcpy(&out.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));643	getsockopt_checked(sk, &out, 0, "no prefix, any addr");644 645	sk = prepare_defs(TCP_AO_GET_KEYS, &out);646	out.get_all = 0;647	out.prefix = 32;648	memcpy(&out.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));649	getsockopt_checked(sk, &out, EINVAL, "prefix, any addr");650 651	sk = prepare_defs(TCP_AO_GET_KEYS, &out);652	out.get_all = 0;653	out.prefix = 129;654	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);655	getsockopt_checked(sk, &out, EINVAL, "too big prefix");656 657	sk = prepare_defs(TCP_AO_GET_KEYS, &out);658	out.get_all = 0;659	out.prefix = 2;660	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);661	getsockopt_checked(sk, &out, EINVAL, "too short prefix");662 663	sk = prepare_defs(TCP_AO_GET_KEYS, &out);664	out.get_all = 0;665	out.prefix = DEFAULT_TEST_PREFIX;666	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);667	getsockopt_checked(sk, &out, 0, "prefix + addr");668 669	sk = prepare_defs(TCP_AO_GET_KEYS, &out);670	out.get_all = 1;671	out.prefix = DEFAULT_TEST_PREFIX;672	getsockopt_checked(sk, &out, EINVAL, "get_all + prefix");673 674	sk = prepare_defs(TCP_AO_GET_KEYS, &out);675	out.get_all = 1;676	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);677	getsockopt_checked(sk, &out, EINVAL, "get_all + addr");678 679	sk = prepare_defs(TCP_AO_GET_KEYS, &out);680	out.get_all = 1;681	out.sndid = 1;682	getsockopt_checked(sk, &out, EINVAL, "get_all + sndid");683 684	sk = prepare_defs(TCP_AO_GET_KEYS, &out);685	out.get_all = 1;686	out.rcvid = 1;687	getsockopt_checked(sk, &out, EINVAL, "get_all + rcvid");688 689	sk = prepare_defs(TCP_AO_GET_KEYS, &out);690	out.get_all = 0;691	out.is_current = 1;692	out.prefix = DEFAULT_TEST_PREFIX;693	getsockopt_checked(sk, &out, EINVAL, "current + prefix");694 695	sk = prepare_defs(TCP_AO_GET_KEYS, &out);696	out.get_all = 0;697	out.is_current = 1;698	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);699	getsockopt_checked(sk, &out, EINVAL, "current + addr");700 701	sk = prepare_defs(TCP_AO_GET_KEYS, &out);702	out.get_all = 0;703	out.is_current = 1;704	out.sndid = 1;705	getsockopt_checked(sk, &out, EINVAL, "current + sndid");706 707	sk = prepare_defs(TCP_AO_GET_KEYS, &out);708	out.get_all = 0;709	out.is_current = 1;710	out.rcvid = 1;711	getsockopt_checked(sk, &out, EINVAL, "current + rcvid");712 713	sk = prepare_defs(TCP_AO_GET_KEYS, &out);714	out.get_all = 0;715	out.is_rnext = 1;716	out.prefix = DEFAULT_TEST_PREFIX;717	getsockopt_checked(sk, &out, EINVAL, "rnext + prefix");718 719	sk = prepare_defs(TCP_AO_GET_KEYS, &out);720	out.get_all = 0;721	out.is_rnext = 1;722	tcp_addr_to_sockaddr_in(&out.addr, &this_ip_dest, 0);723	getsockopt_checked(sk, &out, EINVAL, "rnext + addr");724 725	sk = prepare_defs(TCP_AO_GET_KEYS, &out);726	out.get_all = 0;727	out.is_rnext = 1;728	out.sndid = 1;729	getsockopt_checked(sk, &out, EINVAL, "rnext + sndid");730 731	sk = prepare_defs(TCP_AO_GET_KEYS, &out);732	out.get_all = 0;733	out.is_rnext = 1;734	out.rcvid = 1;735	getsockopt_checked(sk, &out, EINVAL, "rnext + rcvid");736 737	sk = prepare_defs(TCP_AO_GET_KEYS, &out);738	out.get_all = 1;739	out.is_current = 1;740	getsockopt_checked(sk, &out, EINVAL, "get_all + current");741 742	sk = prepare_defs(TCP_AO_GET_KEYS, &out);743	out.get_all = 1;744	out.is_rnext = 1;745	getsockopt_checked(sk, &out, EINVAL, "get_all + rnext");746 747	sk = prepare_defs(TCP_AO_GET_KEYS, &out);748	out.get_all = 0;749	out.is_current = 1;750	out.is_rnext = 1;751	getsockopt_checked(sk, &out, 0, "current + rnext");752}753 754static void einval_tests(void)755{756	test_einval_add_key();757	test_einval_del_key();758	test_einval_ao_info();759	test_einval_get_keys();760}761 762static void duplicate_tests(void)763{764	union tcp_addr network_dup;765	struct tcp_ao_add ao, ao2;766	int sk;767 768	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);769	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))770		test_error("setsockopt()");771	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy");772 773	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);774	ao2 = ao;775	memcpy(&ao2.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));776	ao2.prefix = 0;777	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao2, sizeof(ao)))778		test_error("setsockopt()");779	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: any addr key on the socket");780 781	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);782	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))783		test_error("setsockopt()");784	memcpy(&ao.addr, &SOCKADDR_ANY, sizeof(SOCKADDR_ANY));785	ao.prefix = 0;786	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr key");787 788	if (inet_pton(TEST_FAMILY, TEST_NETWORK, &network_dup) != 1)789		test_error("Can't convert ip address %s", TEST_NETWORK);790	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);791	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))792		test_error("setsockopt()");793	if (test_prepare_def_key(&ao, "password", 0, network_dup,794				 16, 0, 100, 100))795		test_error("prepare default tcp_ao_add");796	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: add any addr for the same subnet");797 798	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);799	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))800		test_error("setsockopt()");801	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: full copy of a key");802 803	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);804	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))805		test_error("setsockopt()");806	ao.rcvid = 101;807	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: RecvID differs");808 809	sk = prepare_defs(TCP_AO_ADD_KEY, &ao);810	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &ao, sizeof(ao)))811		test_error("setsockopt()");812	ao.sndid = 101;813	setsockopt_checked(sk, TCP_AO_ADD_KEY, &ao, EEXIST, "duplicate: SendID differs");814}815 816static void *client_fn(void *arg)817{818	if (inet_pton(TEST_FAMILY, __TEST_CLIENT_IP(2), &tcp_md5_client) != 1)819		test_error("Can't convert ip address");820	extend_tests();821	einval_tests();822	duplicate_tests();823	/*824	 * TODO: check getsockopt(TCP_AO_GET_KEYS) with different filters825	 * returning proper nr & keys;826	 */827 828	return NULL;829}830 831int main(int argc, char *argv[])832{833	test_init(121, client_fn, NULL);834	return 0;835}836