1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
4 #include "../../../../include/linux/kernel.h"
7 static union tcp_addr tcp_md5_client
;
9 #define FILTER_TEST_NKEYS 16
11 static int test_port
= 7788;
12 static void make_listen(int sk
)
16 tcp_addr_to_sockaddr_in(&addr
, &this_ip_addr
, htons(test_port
++));
17 if (bind(sk
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)
20 test_error("listen()");
23 static void test_vefify_ao_info(int sk
, struct tcp_ao_info_opt
*info
,
26 struct tcp_ao_info_opt tmp
= {};
27 socklen_t len
= sizeof(tmp
);
29 if (getsockopt(sk
, IPPROTO_TCP
, TCP_AO_INFO
, &tmp
, &len
))
30 test_error("getsockopt(TCP_AO_INFO) failed");
32 #define __cmp_ao(member) \
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); \
40 if (info
->set_current
)
41 __cmp_ao(current_key
);
44 if (info
->set_counters
) {
47 __cmp_ao(pkt_key_not_found
);
48 __cmp_ao(pkt_ao_required
);
49 __cmp_ao(pkt_dropped_icmp
);
51 __cmp_ao(ao_required
);
52 __cmp_ao(accept_icmps
);
54 test_ok("AO info get: %s", tst
);
58 static void __setsockopt_checked(int sk
, int optname
, bool get
,
59 void *optval
, socklen_t
*len
,
60 int err
, const char *tst
, const char *tst2
)
71 ret
= getsockopt(sk
, IPPROTO_TCP
, optname
, optval
, len
);
73 ret
= setsockopt(sk
, IPPROTO_TCP
, optname
, optval
, *len
);
76 test_ok("%s%s", tst
?: "", tst2
?: "");
78 test_fail("%s%s: %setsockopt() failed",
79 tst
, tst2
, get
? "g" : "s");
85 test_fail("%s%s: %setsockopt() was expected to fail with %d",
86 tst
, tst2
, get
? "g" : "s", err
);
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",
102 static void setsockopt_checked(int sk
, int optname
, void *optval
,
103 int err
, const char *tst
)
105 const char *cmd
= NULL
;
111 len
= sizeof(struct tcp_ao_add
);
115 len
= sizeof(struct tcp_ao_del
);
118 cmd
= "AO info set: ";
119 len
= sizeof(struct tcp_ao_info_opt
);
125 __setsockopt_checked(sk
, optname
, false, optval
, &len
, err
, cmd
, tst
);
128 static int prepare_defs(int cmd
, void *optval
)
130 int sk
= socket(test_family
, SOCK_STREAM
, IPPROTO_TCP
);
133 test_error("socket()");
136 case TCP_AO_ADD_KEY
: {
137 struct tcp_ao_add
*add
= optval
;
139 if (test_prepare_def_key(add
, DEFAULT_TEST_PASSWORD
, 0, this_ip_dest
,
141 test_error("prepare default tcp_ao_add");
144 case TCP_AO_DEL_KEY
: {
145 struct tcp_ao_del
*del
= optval
;
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
));
153 del
->prefix
= DEFAULT_TEST_PREFIX
;
154 tcp_addr_to_sockaddr_in(&del
->addr
, &this_ip_dest
, 0);
158 struct tcp_ao_info_opt
*info
= optval
;
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
));
166 case TCP_AO_GET_KEYS
: {
167 struct tcp_ao_getsockopt
*get
= optval
;
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
));
178 test_error("unknown cmd");
184 static void test_extend(int cmd
, bool get
, const char *tst
, socklen_t under_size
)
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
;
195 socklen_t extended_size
= sizeof(tmp_opt
);
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");
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");
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");
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");
221 static void extend_tests(void)
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);
233 static void test_optmem_limit(void)
235 size_t i
, keys_limit
, current_optmem
= test_get_optmem();
236 struct tcp_ao_add ao
;
237 union tcp_addr net
= {};
240 if (inet_pton(TEST_FAMILY
, TEST_NETWORK
, &net
) != 1)
241 test_error("Can't convert ip address %s", TEST_NETWORK
);
243 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
244 keys_limit
= current_optmem
/ KERNEL_TCP_AO_KEY_SZ_ROUND_UP
;
246 union tcp_addr key_peer
;
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
,
255 * TCP_AO_ADD_KEY should be the same order as the real
256 * sizeof(struct tcp_ao_key) in kernel.
258 if (i
<= keys_limit
* 10)
260 test_fail("optmem limit test failed: added %zu key", i
);
263 if (i
< keys_limit
) {
264 test_fail("optmem limit test failed: couldn't add %zu key", i
);
267 test_ok("optmem limit was hit on adding %zu key", i
);
273 static void test_einval_add_key(void)
275 struct tcp_ao_add ao
;
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");
282 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
284 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "using reserved padding");
286 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
288 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "using reserved2 padding");
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");
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)");
300 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
302 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "no prefix, addr");
304 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
306 memcpy(&ao
.addr
, &SOCKADDR_ANY
, sizeof(SOCKADDR_ANY
));
307 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, 0, "no prefix, any addr");
309 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
311 memcpy(&ao
.addr
, &SOCKADDR_ANY
, sizeof(SOCKADDR_ANY
));
312 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "prefix, any addr");
314 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
316 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "too big prefix");
318 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
320 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "too short prefix");
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");
326 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
329 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "add current key on a listen socket");
331 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
334 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "add rnext key on a listen socket");
336 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
340 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "add current+rnext key on a listen socket");
342 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
344 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, 0, "add key and set as current");
346 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
348 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, 0, "add key and set as rnext");
350 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
353 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, 0, "add key and set as current+rnext");
355 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
357 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
,
358 "ifindex without TCP_AO_KEYF_IFNINDEX");
360 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
361 ao
.keyflags
|= TCP_AO_KEYF_IFINDEX
;
363 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EINVAL
, "non-existent VRF");
365 * tcp_md5_do_lookup{,_any_l3index}() are checked in unsigned-md5
366 * see client_vrf_tests().
371 /* tcp_ao_parse_crypto() */
372 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
374 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EMSGSIZE
, "maclen bigger than TCP hdr");
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");
381 static void test_einval_del_key(void)
383 struct tcp_ao_del del
;
386 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
388 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "using reserved padding");
390 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
392 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "using reserved2 padding");
394 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
396 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, this_ip_dest
, DEFAULT_TEST_PREFIX
, 0, 0))
397 test_error("add key");
399 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "del and set current key on a listen socket");
401 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
403 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, this_ip_dest
, DEFAULT_TEST_PREFIX
, 0, 0))
404 test_error("add key");
406 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "del and set rnext key on a listen socket");
408 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
410 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, this_ip_dest
, DEFAULT_TEST_PREFIX
, 0, 0))
411 test_error("add key");
414 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "del and set current+rnext key on a listen socket");
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");
420 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
422 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
,
423 "ifindex without TCP_AO_KEYF_IFNINDEX");
425 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
426 del
.keyflags
|= TCP_AO_KEYF_IFINDEX
;
428 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "non-existent VRF");
430 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
432 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set non-existing current key");
434 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
436 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set non-existing rnext key");
438 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
441 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set non-existing current+rnext key");
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");
447 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, 0, "set current key");
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");
453 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, 0, "set rnext key");
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");
460 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, 0, "set current+rnext key");
462 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
464 del
.current_key
= 100;
465 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set as current key to be removed");
467 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
470 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set as rnext key to be removed");
472 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
474 del
.current_key
= 100;
477 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "set as current+rnext key to be removed");
479 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
481 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, EINVAL
, "async on non-listen");
483 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
485 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "non-existing sndid");
487 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
489 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, ENOENT
, "non-existing rcvid");
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");
495 sk
= prepare_defs(TCP_AO_DEL_KEY
, &del
);
496 setsockopt_checked(sk
, TCP_AO_DEL_KEY
, &del
, 0, "correct key delete");
499 static void test_einval_ao_info(void)
501 struct tcp_ao_info_opt info
;
504 sk
= prepare_defs(TCP_AO_INFO
, &info
);
506 info
.set_current
= 1;
507 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EINVAL
, "set current key on a listen socket");
509 sk
= prepare_defs(TCP_AO_INFO
, &info
);
512 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EINVAL
, "set rnext key on a listen socket");
514 sk
= prepare_defs(TCP_AO_INFO
, &info
);
516 info
.set_current
= 1;
518 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EINVAL
, "set current+rnext key on a listen socket");
520 sk
= prepare_defs(TCP_AO_INFO
, &info
);
522 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EINVAL
, "using reserved padding");
524 sk
= prepare_defs(TCP_AO_INFO
, &info
);
526 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EINVAL
, "using reserved2 padding");
528 sk
= prepare_defs(TCP_AO_INFO
, &info
);
529 info
.accept_icmps
= 1;
530 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, 0, "accept_icmps");
532 sk
= prepare_defs(TCP_AO_INFO
, &info
);
533 info
.ao_required
= 1;
534 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, 0, "ao required");
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)");
544 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, EKEYREJECTED
,
545 "ao required with MD5 key");
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");
553 sk
= prepare_defs(TCP_AO_INFO
, &info
);
555 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, ENOENT
, "set non-existing rnext key");
557 sk
= prepare_defs(TCP_AO_INFO
, &info
);
558 info
.set_current
= 1;
560 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, ENOENT
, "set non-existing current+rnext key");
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");
567 sk
= prepare_defs(TCP_AO_INFO
, &info
);
570 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, 0, "set rnext key");
572 sk
= prepare_defs(TCP_AO_INFO
, &info
);
573 info
.set_current
= 1;
575 info
.current_key
= 100;
577 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, 0, "set current+rnext key");
579 sk
= prepare_defs(TCP_AO_INFO
, &info
);
580 info
.set_counters
= 1;
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");
588 sk
= prepare_defs(TCP_AO_INFO
, &info
);
589 setsockopt_checked(sk
, TCP_AO_INFO
, &info
, 0, "no-op");
592 static void getsockopt_checked(int sk
, struct tcp_ao_getsockopt
*optval
,
593 int err
, const char *tst
)
595 socklen_t len
= sizeof(struct tcp_ao_getsockopt
);
597 __setsockopt_checked(sk
, TCP_AO_GET_KEYS
, true, optval
, &len
, err
,
601 static void test_einval_get_keys(void)
603 struct tcp_ao_getsockopt out
;
606 sk
= socket(test_family
, SOCK_STREAM
, IPPROTO_TCP
);
608 test_error("socket()");
609 getsockopt_checked(sk
, &out
, ENOENT
, "no ao_info");
611 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
612 getsockopt_checked(sk
, &out
, 0, "proper tcp_ao_get_mkts()");
614 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
616 getsockopt_checked(sk
, &out
, EINVAL
, "set out-only pkt_good counter");
618 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
620 getsockopt_checked(sk
, &out
, EINVAL
, "set out-only pkt_bad counter");
622 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
623 out
.keyflags
= (uint8_t)(-1);
624 getsockopt_checked(sk
, &out
, EINVAL
, "bad keyflags");
626 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
628 getsockopt_checked(sk
, &out
, EINVAL
,
629 "ifindex without TCP_AO_KEYF_IFNINDEX");
631 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
633 getsockopt_checked(sk
, &out
, EINVAL
, "using reserved field");
635 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
638 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
639 getsockopt_checked(sk
, &out
, EINVAL
, "no prefix, addr");
641 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
644 memcpy(&out
.addr
, &SOCKADDR_ANY
, sizeof(SOCKADDR_ANY
));
645 getsockopt_checked(sk
, &out
, 0, "no prefix, any addr");
647 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
650 memcpy(&out
.addr
, &SOCKADDR_ANY
, sizeof(SOCKADDR_ANY
));
651 getsockopt_checked(sk
, &out
, EINVAL
, "prefix, any addr");
653 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
656 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
657 getsockopt_checked(sk
, &out
, EINVAL
, "too big prefix");
659 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
662 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
663 getsockopt_checked(sk
, &out
, EINVAL
, "too short prefix");
665 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
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");
671 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
673 out
.prefix
= DEFAULT_TEST_PREFIX
;
674 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + prefix");
676 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
678 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
679 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + addr");
681 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
684 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + sndid");
686 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
689 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + rcvid");
691 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
694 out
.prefix
= DEFAULT_TEST_PREFIX
;
695 getsockopt_checked(sk
, &out
, EINVAL
, "current + prefix");
697 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
700 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
701 getsockopt_checked(sk
, &out
, EINVAL
, "current + addr");
703 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
707 getsockopt_checked(sk
, &out
, EINVAL
, "current + sndid");
709 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
713 getsockopt_checked(sk
, &out
, EINVAL
, "current + rcvid");
715 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
718 out
.prefix
= DEFAULT_TEST_PREFIX
;
719 getsockopt_checked(sk
, &out
, EINVAL
, "rnext + prefix");
721 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
724 tcp_addr_to_sockaddr_in(&out
.addr
, &this_ip_dest
, 0);
725 getsockopt_checked(sk
, &out
, EINVAL
, "rnext + addr");
727 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
731 getsockopt_checked(sk
, &out
, EINVAL
, "rnext + sndid");
733 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
737 getsockopt_checked(sk
, &out
, EINVAL
, "rnext + rcvid");
739 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
742 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + current");
744 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
747 getsockopt_checked(sk
, &out
, EINVAL
, "get_all + rnext");
749 sk
= prepare_defs(TCP_AO_GET_KEYS
, &out
);
753 getsockopt_checked(sk
, &out
, 0, "current + rnext");
756 static void einval_tests(void)
758 test_einval_add_key();
759 test_einval_del_key();
760 test_einval_ao_info();
761 test_einval_get_keys();
764 static void duplicate_tests(void)
766 union tcp_addr network_dup
;
767 struct tcp_ao_add ao
, ao2
;
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");
775 sk
= prepare_defs(TCP_AO_ADD_KEY
, &ao
);
777 memcpy(&ao2
.addr
, &SOCKADDR_ANY
, sizeof(SOCKADDR_ANY
));
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");
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
));
788 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EEXIST
, "duplicate: add any addr key");
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
,
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");
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");
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()");
809 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EEXIST
, "duplicate: RecvID differs");
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()");
815 setsockopt_checked(sk
, TCP_AO_ADD_KEY
, &ao
, EEXIST
, "duplicate: SendID differs");
818 static void fetch_all_keys(int sk
, struct tcp_ao_getsockopt
*keys
)
820 socklen_t optlen
= sizeof(struct tcp_ao_getsockopt
);
822 memset(keys
, 0, sizeof(struct tcp_ao_getsockopt
) * FILTER_TEST_NKEYS
);
824 keys
[0].nkeys
= FILTER_TEST_NKEYS
;
825 if (getsockopt(sk
, IPPROTO_TCP
, TCP_AO_GET_KEYS
, &keys
[0], &optlen
))
826 test_error("getsockopt");
829 static int prepare_test_keys(struct tcp_ao_getsockopt
*keys
)
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;
837 sk
= socket(test_family
, SOCK_STREAM
, IPPROTO_TCP
);
839 test_error("socket()");
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
);
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;
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
);
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
));
866 fetch_all_keys(sk
, keys
);
871 /* Assumes passwords are unique */
872 static int compare_mkts(struct tcp_ao_getsockopt
*expected
, int nexpected
,
873 struct tcp_ao_getsockopt
*actual
, int nactual
)
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)
884 return nexpected
- matches
;
887 static void filter_keys_checked(int sk
, struct tcp_ao_getsockopt
*filter
,
888 struct tcp_ao_getsockopt
*expected
,
889 unsigned int nexpected
, const char *tst
)
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
);
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
);
905 if (compare_mkts(expected
, nexpected
, filtered_keys
,
906 filtered_keys
[0].nkeys
)) {
907 test_fail("got wrong keys back");
910 test_ok("filter keys: %s", tst
);
914 memset(filter
, 0, sizeof(struct tcp_ao_getsockopt
));
917 static void filter_tests(void)
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
= {};
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");
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
) {
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");
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
) {
957 test_error("No rnext key after adding one");
959 filter_keys_checked(sk
, &filter
, &original_keys
[f
], 1, "by is_rnext");
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) {
967 memcpy(&expected_keys
[nmatches
], &original_keys
[i
],
968 sizeof(struct tcp_ao_getsockopt
));
973 test_error("No key for sndid 100");
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
,
982 sk
= prepare_test_keys(original_keys
);
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");
991 test_fail("filter keys: wrong nkeys, expected %u got %u",
992 FILTER_TEST_NKEYS
, filter
.nkeys
);
995 static void *client_fn(void *arg
)
997 if (inet_pton(TEST_FAMILY
, __TEST_CLIENT_IP(2), &tcp_md5_client
) != 1)
998 test_error("Can't convert ip address");
1007 int main(int argc
, char *argv
[])
1009 test_init(126, client_fn
, NULL
);