File Index
Files and directories
Sign in
FILE

setsockopt-closed.c

File preview with syntax highlighting.

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