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