Merge tag 'rust-6.9' of https://github.com/Rust-for-Linux/linux
[sfrench/cifs-2.6.git] / tools / testing / selftests / net / tcp_ao / unsigned-md5.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
3 #include <inttypes.h>
4 #include "aolib.h"
5
6 #define fault(type)     (inj == FAULT_ ## type)
7 static const char *md5_password = "Some evil genius, enemy to mankind, must have been the first contriver.";
8 static const char *ao_password = DEFAULT_TEST_PASSWORD;
9
10 static union tcp_addr client2;
11 static union tcp_addr client3;
12
13 static const int test_vrf_ifindex = 200;
14 static const uint8_t test_vrf_tabid = 42;
15 static void setup_vrfs(void)
16 {
17         int err;
18
19         if (!kernel_config_has(KCONFIG_NET_VRF))
20                 return;
21
22         err = add_vrf("ksft-vrf", test_vrf_tabid, test_vrf_ifindex, -1);
23         if (err)
24                 test_error("Failed to add a VRF: %d", err);
25
26         err = link_set_up("ksft-vrf");
27         if (err)
28                 test_error("Failed to bring up a VRF");
29
30         err = ip_route_add_vrf(veth_name, TEST_FAMILY,
31                                this_ip_addr, this_ip_dest, test_vrf_tabid);
32         if (err)
33                 test_error("Failed to add a route to VRF: %d", err);
34 }
35
36 static void try_accept(const char *tst_name, unsigned int port,
37                        union tcp_addr *md5_addr, uint8_t md5_prefix,
38                        union tcp_addr *ao_addr, uint8_t ao_prefix,
39                        bool set_ao_required,
40                        uint8_t sndid, uint8_t rcvid, uint8_t vrf,
41                        const char *cnt_name, test_cnt cnt_expected,
42                        int needs_tcp_md5, fault_t inj)
43 {
44         struct tcp_ao_counters ao_cnt1, ao_cnt2;
45         uint64_t before_cnt = 0, after_cnt = 0; /* silence GCC */
46         int lsk, err, sk = 0;
47         time_t timeout;
48
49         if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
50                 return;
51
52         lsk = test_listen_socket(this_ip_addr, port, 1);
53
54         if (md5_addr && test_set_md5(lsk, *md5_addr, md5_prefix, -1, md5_password))
55                 test_error("setsockopt(TCP_MD5SIG_EXT)");
56
57         if (ao_addr && test_add_key(lsk, ao_password,
58                                     *ao_addr, ao_prefix, sndid, rcvid))
59                 test_error("setsockopt(TCP_AO_ADD_KEY)");
60
61         if (set_ao_required && test_set_ao_flags(lsk, true, false))
62                 test_error("setsockopt(TCP_AO_INFO)");
63
64         if (cnt_name)
65                 before_cnt = netstat_get_one(cnt_name, NULL);
66         if (ao_addr && test_get_tcp_ao_counters(lsk, &ao_cnt1))
67                 test_error("test_get_tcp_ao_counters()");
68
69         synchronize_threads(); /* preparations done */
70
71         timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
72         err = test_wait_fd(lsk, timeout, 0);
73         if (err == -ETIMEDOUT) {
74                 if (!fault(TIMEOUT))
75                         test_fail("timed out for accept()");
76         } else if (err < 0) {
77                 test_error("test_wait_fd()");
78         } else {
79                 if (fault(TIMEOUT))
80                         test_fail("ready to accept");
81
82                 sk = accept(lsk, NULL, NULL);
83                 if (sk < 0) {
84                         test_error("accept()");
85                 } else {
86                         if (fault(TIMEOUT))
87                                 test_fail("%s: accepted", tst_name);
88                 }
89         }
90
91         if (ao_addr && test_get_tcp_ao_counters(lsk, &ao_cnt2))
92                 test_error("test_get_tcp_ao_counters()");
93         close(lsk);
94
95         if (!cnt_name) {
96                 test_ok("%s: no counter checks", tst_name);
97                 goto out;
98         }
99
100         after_cnt = netstat_get_one(cnt_name, NULL);
101
102         if (after_cnt <= before_cnt) {
103                 test_fail("%s: %s counter did not increase: %zu <= %zu",
104                                 tst_name, cnt_name, after_cnt, before_cnt);
105         } else {
106                 test_ok("%s: counter %s increased %zu => %zu",
107                         tst_name, cnt_name, before_cnt, after_cnt);
108         }
109         if (ao_addr)
110                 test_tcp_ao_counters_cmp(tst_name, &ao_cnt1, &ao_cnt2, cnt_expected);
111
112 out:
113         synchronize_threads(); /* test_kill_sk() */
114         if (sk > 0)
115                 test_kill_sk(sk);
116 }
117
118 static void server_add_routes(void)
119 {
120         int family = TEST_FAMILY;
121
122         synchronize_threads(); /* client_add_ips() */
123
124         if (ip_route_add(veth_name, family, this_ip_addr, client2))
125                 test_error("Failed to add route");
126         if (ip_route_add(veth_name, family, this_ip_addr, client3))
127                 test_error("Failed to add route");
128 }
129
130 static void server_add_fail_tests(unsigned int *port)
131 {
132         union tcp_addr addr_any = {};
133
134         try_accept("TCP-AO established: add TCP-MD5 key", (*port)++, NULL, 0,
135                    &addr_any, 0, 0, 100, 100, 0, "TCPAOGood", TEST_CNT_GOOD,
136                    1, 0);
137         try_accept("TCP-MD5 established: add TCP-AO key", (*port)++, &addr_any,
138                    0, NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
139         try_accept("non-signed established: add TCP-AO key", (*port)++, NULL, 0,
140                    NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
141 }
142
143 static void server_vrf_tests(unsigned int *port)
144 {
145         setup_vrfs();
146 }
147
148 static void *server_fn(void *arg)
149 {
150         unsigned int port = test_server_port;
151         union tcp_addr addr_any = {};
152
153         server_add_routes();
154
155         try_accept("AO server (INADDR_ANY): AO client", port++, NULL, 0,
156                    &addr_any, 0, 0, 100, 100, 0, "TCPAOGood",
157                    TEST_CNT_GOOD, 0, 0);
158         try_accept("AO server (INADDR_ANY): MD5 client", port++, NULL, 0,
159                    &addr_any, 0, 0, 100, 100, 0, "TCPMD5Unexpected",
160                    0, 1, FAULT_TIMEOUT);
161         try_accept("AO server (INADDR_ANY): no sign client", port++, NULL, 0,
162                    &addr_any, 0, 0, 100, 100, 0, "TCPAORequired",
163                    TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
164         try_accept("AO server (AO_REQUIRED): AO client", port++, NULL, 0,
165                    &this_ip_dest, TEST_PREFIX, true,
166                    100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 0, 0);
167         try_accept("AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
168                    &this_ip_dest, TEST_PREFIX, true,
169                    100, 100, 0, "TCPAORequired",
170                    TEST_CNT_AO_REQUIRED, 0, FAULT_TIMEOUT);
171
172         try_accept("MD5 server (INADDR_ANY): AO client", port++, &addr_any, 0,
173                    NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
174                    0, 1, FAULT_TIMEOUT);
175         try_accept("MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
176                    NULL, 0, 0, 0, 0, 0, NULL, 0, 1, 0);
177         try_accept("MD5 server (INADDR_ANY): no sign client", port++, &addr_any,
178                    0, NULL, 0, 0, 0, 0, 0, "TCPMD5NotFound",
179                    0, 1, FAULT_TIMEOUT);
180
181         try_accept("no sign server: AO client", port++, NULL, 0,
182                    NULL, 0, 0, 0, 0, 0, "TCPAOKeyNotFound",
183                    TEST_CNT_AO_KEY_NOT_FOUND, 0, FAULT_TIMEOUT);
184         try_accept("no sign server: MD5 client", port++, NULL, 0,
185                    NULL, 0, 0, 0, 0, 0, "TCPMD5Unexpected",
186                    0, 1, FAULT_TIMEOUT);
187         try_accept("no sign server: no sign client", port++, NULL, 0,
188                    NULL, 0, 0, 0, 0, 0, "CurrEstab", 0, 0, 0);
189
190         try_accept("AO+MD5 server: AO client (matching)", port++,
191                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
192                    100, 100, 0, "TCPAOGood", TEST_CNT_GOOD, 1, 0);
193         try_accept("AO+MD5 server: AO client (misconfig, matching MD5)", port++,
194                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
195                    100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
196                    1, FAULT_TIMEOUT);
197         try_accept("AO+MD5 server: AO client (misconfig, non-matching)", port++,
198                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
199                    100, 100, 0, "TCPAOKeyNotFound", TEST_CNT_AO_KEY_NOT_FOUND,
200                    1, FAULT_TIMEOUT);
201         try_accept("AO+MD5 server: MD5 client (matching)", port++,
202                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
203                    100, 100, 0, NULL, 0, 1, 0);
204         try_accept("AO+MD5 server: MD5 client (misconfig, matching AO)", port++,
205                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
206                    100, 100, 0, "TCPMD5Unexpected", 0, 1, FAULT_TIMEOUT);
207         try_accept("AO+MD5 server: MD5 client (misconfig, non-matching)", port++,
208                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
209                    100, 100, 0, "TCPMD5Unexpected", 0, 1, FAULT_TIMEOUT);
210         try_accept("AO+MD5 server: no sign client (unmatched)", port++,
211                    &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
212                    100, 100, 0, "CurrEstab", 0, 1, 0);
213         try_accept("AO+MD5 server: no sign client (misconfig, matching AO)",
214                    port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
215                    100, 100, 0, "TCPAORequired",
216                    TEST_CNT_AO_REQUIRED, 1, FAULT_TIMEOUT);
217         try_accept("AO+MD5 server: no sign client (misconfig, matching MD5)",
218                    port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
219                    100, 100, 0, "TCPMD5NotFound", 0, 1, FAULT_TIMEOUT);
220
221         try_accept("AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
222                    port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
223                    100, 100, 0, NULL, 0, 1, FAULT_TIMEOUT);
224         try_accept("AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
225                    port++, &this_ip_dest, TEST_PREFIX, &client2, TEST_PREFIX, 0,
226                    100, 100, 0, NULL, 0, 1, FAULT_TIMEOUT);
227
228         server_add_fail_tests(&port);
229
230         server_vrf_tests(&port);
231
232         /* client exits */
233         synchronize_threads();
234         return NULL;
235 }
236
237 static int client_bind(int sk, union tcp_addr bind_addr)
238 {
239 #ifdef IPV6_TEST
240         struct sockaddr_in6 addr = {
241                 .sin6_family    = AF_INET6,
242                 .sin6_port      = 0,
243                 .sin6_addr      = bind_addr.a6,
244         };
245 #else
246         struct sockaddr_in addr = {
247                 .sin_family     = AF_INET,
248                 .sin_port       = 0,
249                 .sin_addr       = bind_addr.a4,
250         };
251 #endif
252         return bind(sk, &addr, sizeof(addr));
253 }
254
255 static void try_connect(const char *tst_name, unsigned int port,
256                        union tcp_addr *md5_addr, uint8_t md5_prefix,
257                        union tcp_addr *ao_addr, uint8_t ao_prefix,
258                        uint8_t sndid, uint8_t rcvid, uint8_t vrf,
259                        fault_t inj, int needs_tcp_md5, union tcp_addr *bind_addr)
260 {
261         time_t timeout;
262         int sk, ret;
263
264         if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
265                 return;
266
267         sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
268         if (sk < 0)
269                 test_error("socket()");
270
271         if (bind_addr && client_bind(sk, *bind_addr))
272                 test_error("bind()");
273
274         if (md5_addr && test_set_md5(sk, *md5_addr, md5_prefix, -1, md5_password))
275                 test_error("setsockopt(TCP_MD5SIG_EXT)");
276
277         if (ao_addr && test_add_key(sk, ao_password, *ao_addr,
278                                     ao_prefix, sndid, rcvid))
279                 test_error("setsockopt(TCP_AO_ADD_KEY)");
280
281         synchronize_threads(); /* preparations done */
282
283         timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
284         ret = _test_connect_socket(sk, this_ip_dest, port, timeout);
285
286         if (ret < 0) {
287                 if (fault(KEYREJECT) && ret == -EKEYREJECTED)
288                         test_ok("%s: connect() was prevented", tst_name);
289                 else if (ret == -ETIMEDOUT && fault(TIMEOUT))
290                         test_ok("%s", tst_name);
291                 else if (ret == -ECONNREFUSED &&
292                                 (fault(TIMEOUT) || fault(KEYREJECT)))
293                         test_ok("%s: refused to connect", tst_name);
294                 else
295                         test_error("%s: connect() returned %d", tst_name, ret);
296                 goto out;
297         }
298
299         if (fault(TIMEOUT) || fault(KEYREJECT))
300                 test_fail("%s: connected", tst_name);
301         else
302                 test_ok("%s: connected", tst_name);
303
304 out:
305         synchronize_threads(); /* test_kill_sk() */
306         /* _test_connect_socket() cleans up on failure */
307         if (ret > 0)
308                 test_kill_sk(sk);
309 }
310
311 #define PREINSTALL_MD5_FIRST    BIT(0)
312 #define PREINSTALL_AO           BIT(1)
313 #define POSTINSTALL_AO          BIT(2)
314 #define PREINSTALL_MD5          BIT(3)
315 #define POSTINSTALL_MD5         BIT(4)
316
317 static int try_add_key_vrf(int sk, union tcp_addr in_addr, uint8_t prefix,
318                            int vrf, uint8_t sndid, uint8_t rcvid,
319                            bool set_ao_required)
320 {
321         uint8_t keyflags = 0;
322
323         if (vrf >= 0)
324                 keyflags |= TCP_AO_KEYF_IFINDEX;
325         else
326                 vrf = 0;
327         if (set_ao_required) {
328                 int err = test_set_ao_flags(sk, true, 0);
329
330                 if (err)
331                         return err;
332         }
333         return test_add_key_vrf(sk, ao_password, keyflags, in_addr, prefix,
334                                 (uint8_t)vrf, sndid, rcvid);
335 }
336
337 static bool test_continue(const char *tst_name, int err,
338                           fault_t inj, bool added_ao)
339 {
340         bool expected_to_fail;
341
342         expected_to_fail = fault(PREINSTALL_AO) && added_ao;
343         expected_to_fail |= fault(PREINSTALL_MD5) && !added_ao;
344
345         if (!err) {
346                 if (!expected_to_fail)
347                         return true;
348                 test_fail("%s: setsockopt()s were expected to fail", tst_name);
349                 return false;
350         }
351         if (err != -EKEYREJECTED || !expected_to_fail) {
352                 test_error("%s: setsockopt(%s) = %d", tst_name,
353                            added_ao ? "TCP_AO_ADD_KEY" : "TCP_MD5SIG_EXT", err);
354                 return false;
355         }
356         test_ok("%s: prefailed as expected: %m", tst_name);
357         return false;
358 }
359
360 static int open_add(const char *tst_name, unsigned int port,
361                     unsigned int strategy,
362                     union tcp_addr md5_addr, uint8_t md5_prefix, int md5_vrf,
363                     union tcp_addr ao_addr, uint8_t ao_prefix,
364                     int ao_vrf, bool set_ao_required,
365                     uint8_t sndid, uint8_t rcvid,
366                     fault_t inj)
367 {
368         int sk;
369
370         sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
371         if (sk < 0)
372                 test_error("socket()");
373
374         if (client_bind(sk, this_ip_addr))
375                 test_error("bind()");
376
377         if (strategy & PREINSTALL_MD5_FIRST) {
378                 if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password))
379                         test_error("setsockopt(TCP_MD5SIG_EXT)");
380         }
381
382         if (strategy & PREINSTALL_AO) {
383                 int err = try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
384                                           sndid, rcvid, set_ao_required);
385
386                 if (!test_continue(tst_name, err, inj, true)) {
387                         close(sk);
388                         return -1;
389                 }
390         }
391
392         if (strategy & PREINSTALL_MD5) {
393                 errno = 0;
394                 test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password);
395                 if (!test_continue(tst_name, -errno, inj, false)) {
396                         close(sk);
397                         return -1;
398                 }
399         }
400
401         return sk;
402 }
403
404 static void try_to_preadd(const char *tst_name, unsigned int port,
405                           unsigned int strategy,
406                           union tcp_addr md5_addr, uint8_t md5_prefix,
407                           int md5_vrf,
408                           union tcp_addr ao_addr, uint8_t ao_prefix,
409                           int ao_vrf, bool set_ao_required,
410                           uint8_t sndid, uint8_t rcvid,
411                           int needs_tcp_md5, int needs_vrf, fault_t inj)
412 {
413         int sk;
414
415         if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
416                 return;
417         if (needs_vrf && should_skip_test(tst_name, KCONFIG_NET_VRF))
418                 return;
419
420         sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
421                       ao_addr, ao_prefix, ao_vrf, set_ao_required,
422                       sndid, rcvid, inj);
423         if (sk < 0)
424                 return;
425
426         test_ok("%s", tst_name);
427         close(sk);
428 }
429
430 static void try_to_add(const char *tst_name, unsigned int port,
431                        unsigned int strategy,
432                        union tcp_addr md5_addr, uint8_t md5_prefix,
433                        int md5_vrf,
434                        union tcp_addr ao_addr, uint8_t ao_prefix,
435                        int ao_vrf, uint8_t sndid, uint8_t rcvid,
436                        int needs_tcp_md5, fault_t inj)
437 {
438         time_t timeout;
439         int sk, ret;
440
441         if (needs_tcp_md5 && should_skip_test(tst_name, KCONFIG_TCP_MD5))
442                 return;
443
444         sk = open_add(tst_name, port, strategy, md5_addr, md5_prefix, md5_vrf,
445                       ao_addr, ao_prefix, ao_vrf, 0, sndid, rcvid, inj);
446         if (sk < 0)
447                 return;
448
449         synchronize_threads(); /* preparations done */
450
451         timeout = fault(TIMEOUT) ? TEST_RETRANSMIT_SEC : TEST_TIMEOUT_SEC;
452         ret = _test_connect_socket(sk, this_ip_dest, port, timeout);
453
454         if (ret <= 0) {
455                 test_error("%s: connect() returned %d", tst_name, ret);
456                 goto out;
457         }
458
459         if (strategy & POSTINSTALL_MD5) {
460                 if (test_set_md5(sk, md5_addr, md5_prefix, md5_vrf, md5_password)) {
461                         if (fault(POSTINSTALL)) {
462                                 test_ok("%s: postfailed as expected", tst_name);
463                                 goto out;
464                         } else {
465                                 test_error("setsockopt(TCP_MD5SIG_EXT)");
466                         }
467                 } else if (fault(POSTINSTALL)) {
468                         test_fail("%s: post setsockopt() was expected to fail", tst_name);
469                         goto out;
470                 }
471         }
472
473         if (strategy & POSTINSTALL_AO) {
474                 if (try_add_key_vrf(sk, ao_addr, ao_prefix, ao_vrf,
475                                    sndid, rcvid, 0)) {
476                         if (fault(POSTINSTALL)) {
477                                 test_ok("%s: postfailed as expected", tst_name);
478                                 goto out;
479                         } else {
480                                 test_error("setsockopt(TCP_AO_ADD_KEY)");
481                         }
482                 } else if (fault(POSTINSTALL)) {
483                         test_fail("%s: post setsockopt() was expected to fail", tst_name);
484                         goto out;
485                 }
486         }
487
488 out:
489         synchronize_threads(); /* test_kill_sk() */
490         /* _test_connect_socket() cleans up on failure */
491         if (ret > 0)
492                 test_kill_sk(sk);
493 }
494
495 static void client_add_ip(union tcp_addr *client, const char *ip)
496 {
497         int err, family = TEST_FAMILY;
498
499         if (inet_pton(family, ip, client) != 1)
500                 test_error("Can't convert ip address %s", ip);
501
502         err = ip_addr_add(veth_name, family, *client, TEST_PREFIX);
503         if (err)
504                 test_error("Failed to add ip address: %d", err);
505 }
506
507 static void client_add_ips(void)
508 {
509         client_add_ip(&client2, __TEST_CLIENT_IP(2));
510         client_add_ip(&client3, __TEST_CLIENT_IP(3));
511         synchronize_threads(); /* server_add_routes() */
512 }
513
514 static void client_add_fail_tests(unsigned int *port)
515 {
516         try_to_add("TCP-AO established: add TCP-MD5 key",
517                    (*port)++, POSTINSTALL_MD5 | PREINSTALL_AO,
518                    this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
519                    100, 100, 1, FAULT_POSTINSTALL);
520         try_to_add("TCP-MD5 established: add TCP-AO key",
521                    (*port)++, PREINSTALL_MD5 | POSTINSTALL_AO,
522                    this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
523                    100, 100, 1, FAULT_POSTINSTALL);
524         try_to_add("non-signed established: add TCP-AO key",
525                    (*port)++, POSTINSTALL_AO,
526                    this_ip_dest, TEST_PREFIX, -1, this_ip_dest, TEST_PREFIX, 0,
527                    100, 100, 0, FAULT_POSTINSTALL);
528
529         try_to_add("TCP-AO key intersects with existing TCP-MD5 key",
530                    (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
531                    this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
532                    100, 100, 1, FAULT_PREINSTALL_AO);
533         try_to_add("TCP-MD5 key intersects with existing TCP-AO key",
534                    (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
535                    this_ip_addr, TEST_PREFIX, -1, this_ip_addr, TEST_PREFIX, -1,
536                    100, 100, 1, FAULT_PREINSTALL_MD5);
537
538         try_to_preadd("TCP-MD5 key + TCP-AO required",
539                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
540                       this_ip_addr, TEST_PREFIX, -1,
541                       this_ip_addr, TEST_PREFIX, -1, true,
542                       100, 100, 1, 0, FAULT_PREINSTALL_AO);
543         try_to_preadd("TCP-AO required on socket + TCP-MD5 key",
544                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
545                       this_ip_addr, TEST_PREFIX, -1,
546                       this_ip_addr, TEST_PREFIX, -1, true,
547                       100, 100, 1, 0, FAULT_PREINSTALL_MD5);
548 }
549
550 static void client_vrf_tests(unsigned int *port)
551 {
552         setup_vrfs();
553
554         /* The following restrictions for setsockopt()s are expected:
555          *
556          * |--------------|-----------------|-------------|-------------|
557          * |              | MD5 key without |   MD5 key   |   MD5 key   |
558          * |              |     l3index     |  l3index=0  |  l3index=N  |
559          * |--------------|-----------------|-------------|-------------|
560          * |  TCP-AO key  |                 |             |             |
561          * |  without     |     reject      |    reject   |    reject   |
562          * |  l3index     |                 |             |             |
563          * |--------------|-----------------|-------------|-------------|
564          * |  TCP-AO key  |                 |             |             |
565          * |  l3index=0   |     reject      |    reject   |    allow    |
566          * |--------------|-----------------|-------------|-------------|
567          * |  TCP-AO key  |                 |             |             |
568          * |  l3index=N   |     reject      |    allow    |    reject   |
569          * |--------------|-----------------|-------------|-------------|
570          */
571         try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (no l3index)",
572                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
573                       this_ip_addr, TEST_PREFIX, -1,
574                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
575                       1, 1, FAULT_PREINSTALL_MD5);
576         try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (no l3index)",
577                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
578                       this_ip_addr, TEST_PREFIX, -1,
579                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
580                       1, 1, FAULT_PREINSTALL_AO);
581         try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=0)",
582                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
583                       this_ip_addr, TEST_PREFIX, 0,
584                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
585                       1, 1, FAULT_PREINSTALL_MD5);
586         try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (no l3index)",
587                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
588                       this_ip_addr, TEST_PREFIX, 0,
589                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
590                       1, 1, FAULT_PREINSTALL_AO);
591         try_to_preadd("VRF: TCP-AO key (no l3index) + TCP-MD5 key (l3index=N)",
592                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
593                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
594                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
595                       1, 1, FAULT_PREINSTALL_MD5);
596         try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (no l3index)",
597                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
598                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
599                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
600                       1, 1, FAULT_PREINSTALL_AO);
601
602         try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (no l3index)",
603                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
604                       this_ip_addr, TEST_PREFIX, -1,
605                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
606                       1, 1, FAULT_PREINSTALL_MD5);
607         try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=0)",
608                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
609                       this_ip_addr, TEST_PREFIX, -1,
610                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
611                       1, 1, FAULT_PREINSTALL_AO);
612         try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=0)",
613                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
614                       this_ip_addr, TEST_PREFIX, 0,
615                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
616                       1, 1, FAULT_PREINSTALL_MD5);
617         try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=0)",
618                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
619                       this_ip_addr, TEST_PREFIX, 0,
620                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
621                       1, 1, FAULT_PREINSTALL_AO);
622         try_to_preadd("VRF: TCP-AO key (l3index=0) + TCP-MD5 key (l3index=N)",
623                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
624                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
625                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
626                       1, 1, 0);
627         try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=0)",
628                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
629                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
630                       this_ip_addr, TEST_PREFIX, 0, 0, 100, 100,
631                       1, 1, 0);
632
633         try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (no l3index)",
634                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
635                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
636                       this_ip_addr, TEST_PREFIX, -1, 0, 100, 100,
637                       1, 1, FAULT_PREINSTALL_MD5);
638         try_to_preadd("VRF: TCP-MD5 key (no l3index) + TCP-AO key (l3index=N)",
639                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
640                       this_ip_addr, TEST_PREFIX, -1,
641                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
642                       1, 1, FAULT_PREINSTALL_AO);
643         try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=0)",
644                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
645                       this_ip_addr, TEST_PREFIX, 0,
646                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
647                       1, 1, 0);
648         try_to_preadd("VRF: TCP-MD5 key (l3index=0) + TCP-AO key (l3index=N)",
649                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
650                       this_ip_addr, TEST_PREFIX, 0,
651                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
652                       1, 1, 0);
653         try_to_preadd("VRF: TCP-AO key (l3index=N) + TCP-MD5 key (l3index=N)",
654                       (*port)++, PREINSTALL_MD5 | PREINSTALL_AO,
655                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
656                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
657                       1, 1, FAULT_PREINSTALL_MD5);
658         try_to_preadd("VRF: TCP-MD5 key (l3index=N) + TCP-AO key (l3index=N)",
659                       (*port)++, PREINSTALL_MD5_FIRST | PREINSTALL_AO,
660                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex,
661                       this_ip_addr, TEST_PREFIX, test_vrf_ifindex, 0, 100, 100,
662                       1, 1, FAULT_PREINSTALL_AO);
663 }
664
665 static void *client_fn(void *arg)
666 {
667         unsigned int port = test_server_port;
668         union tcp_addr addr_any = {};
669
670         client_add_ips();
671
672         try_connect("AO server (INADDR_ANY): AO client", port++, NULL, 0,
673                     &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
674         try_connect("AO server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
675                     NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
676         try_connect("AO server (INADDR_ANY): unsigned client", port++, NULL, 0,
677                     NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
678         try_connect("AO server (AO_REQUIRED): AO client", port++, NULL, 0,
679                     &addr_any, 0, 100, 100, 0, 0, 0, &this_ip_addr);
680         try_connect("AO server (AO_REQUIRED): unsigned client", port++, NULL, 0,
681                     NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &client2);
682
683         try_connect("MD5 server (INADDR_ANY): AO client", port++, NULL, 0,
684                    &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
685         try_connect("MD5 server (INADDR_ANY): MD5 client", port++, &addr_any, 0,
686                    NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
687         try_connect("MD5 server (INADDR_ANY): no sign client", port++, NULL, 0,
688                    NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
689
690         try_connect("no sign server: AO client", port++, NULL, 0,
691                    &addr_any, 0, 100, 100, 0, FAULT_TIMEOUT, 0, &this_ip_addr);
692         try_connect("no sign server: MD5 client", port++, &addr_any, 0,
693                    NULL, 0, 100, 100, 0, FAULT_TIMEOUT, 1, &this_ip_addr);
694         try_connect("no sign server: no sign client", port++, NULL, 0,
695                    NULL, 0, 100, 100, 0, 0, 0, &this_ip_addr);
696
697         try_connect("AO+MD5 server: AO client (matching)", port++, NULL, 0,
698                    &addr_any, 0, 100, 100, 0, 0, 1, &client2);
699         try_connect("AO+MD5 server: AO client (misconfig, matching MD5)",
700                    port++, NULL, 0, &addr_any, 0, 100, 100, 0,
701                    FAULT_TIMEOUT, 1, &this_ip_addr);
702         try_connect("AO+MD5 server: AO client (misconfig, non-matching)",
703                    port++, NULL, 0, &addr_any, 0, 100, 100, 0,
704                    FAULT_TIMEOUT, 1, &client3);
705         try_connect("AO+MD5 server: MD5 client (matching)", port++, &addr_any, 0,
706                    NULL, 0, 100, 100, 0, 0, 1, &this_ip_addr);
707         try_connect("AO+MD5 server: MD5 client (misconfig, matching AO)",
708                    port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
709                    1, &client2);
710         try_connect("AO+MD5 server: MD5 client (misconfig, non-matching)",
711                    port++, &addr_any, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
712                    1, &client3);
713         try_connect("AO+MD5 server: no sign client (unmatched)",
714                    port++, NULL, 0, NULL, 0, 100, 100, 0, 0, 1, &client3);
715         try_connect("AO+MD5 server: no sign client (misconfig, matching AO)",
716                    port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
717                    1, &client2);
718         try_connect("AO+MD5 server: no sign client (misconfig, matching MD5)",
719                    port++, NULL, 0, NULL, 0, 100, 100, 0, FAULT_TIMEOUT,
720                    1, &this_ip_addr);
721
722         try_connect("AO+MD5 server: client with both [TCP-MD5] and TCP-AO keys",
723                    port++, &this_ip_addr, TEST_PREFIX,
724                    &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
725                    1, &this_ip_addr);
726         try_connect("AO+MD5 server: client with both TCP-MD5 and [TCP-AO] keys",
727                    port++, &this_ip_addr, TEST_PREFIX,
728                    &client2, TEST_PREFIX, 100, 100, 0, FAULT_KEYREJECT,
729                    1, &client2);
730
731         client_add_fail_tests(&port);
732         client_vrf_tests(&port);
733
734         return NULL;
735 }
736
737 int main(int argc, char *argv[])
738 {
739         test_init(72, server_fn, client_fn);
740         return 0;
741 }