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
7 static union tcp_addr tcp_md5_client;
8
9 static int test_port = 7788;
make_listen(int sk)10 static 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
test_vefify_ao_info(int sk,struct tcp_ao_info_opt * info,const char * tst)21 static 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) \
31 do { \
32 if (info->member != tmp.member) { \
33 test_fail("%s: getsockopt(): " __stringify(member) " %zu != %zu", \
34 tst, (size_t)info->member, (size_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_ao
54 }
55
__setsockopt_checked(int sk,int optname,bool get,void * optval,socklen_t * len,int err,const char * tst,const char * tst2)56 static 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 else
71 ret = setsockopt(sk, IPPROTO_TCP, optname, optval, *len);
72 if (ret == -1) {
73 if (errno == err)
74 test_ok("%s%s", tst ?: "", tst2 ?: "");
75 else
76 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
setsockopt_checked(int sk,int optname,void * optval,int err,const char * tst)100 static 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
prepare_defs(int cmd,void * optval)126 static 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
test_extend(int cmd,bool get,const char * tst,socklen_t under_size)182 static 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
extend_tests(void)219 static 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
test_optmem_limit(void)231 static 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 real
254 * 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
test_einval_add_key(void)271 static 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-md5
364 * 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
test_einval_del_key(void)379 static 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
test_einval_ao_info(void)497 static 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
getsockopt_checked(int sk,struct tcp_ao_getsockopt * optval,int err,const char * tst)590 static 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
test_einval_get_keys(void)599 static 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
einval_tests(void)754 static 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
duplicate_tests(void)762 static 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
client_fn(void * arg)816 static 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 filters
825 * returning proper nr & keys;
826 */
827
828 return NULL;
829 }
830
main(int argc,char * argv[])831 int main(int argc, char *argv[])
832 {
833 test_init(120, client_fn, NULL);
834 return 0;
835 }
836