1 // SPDX-License-Identifier: GPL-2.0
2 /* Author: Dmitry Safonov <dima@arista.com> */
6 static union tcp_addr local_addr
;
8 static void __setup_lo_intf(const char *lo_intf
,
9 const char *addr_str
, uint8_t prefix
)
11 if (inet_pton(TEST_FAMILY
, addr_str
, &local_addr
) != 1)
12 test_error("Can't convert local ip address");
14 if (ip_addr_add(lo_intf
, TEST_FAMILY
, local_addr
, prefix
))
15 test_error("Failed to add %s ip address", lo_intf
);
17 if (link_set_up(lo_intf
))
18 test_error("Failed to bring %s up", lo_intf
);
21 static void setup_lo_intf(const char *lo_intf
)
24 __setup_lo_intf(lo_intf
, "::1", 128);
26 __setup_lo_intf(lo_intf
, "127.0.0.1", 8);
30 static void tcp_self_connect(const char *tst
, unsigned int port
,
31 bool different_keyids
, bool check_restore
)
33 struct tcp_ao_counters before_ao
, after_ao
;
34 uint64_t before_aogood
, after_aogood
;
35 struct netstat
*ns_before
, *ns_after
;
36 const size_t nr_packets
= 20;
37 struct tcp_ao_repair ao_img
;
38 struct tcp_sock_state img
;
42 tcp_addr_to_sockaddr_in(&addr
, &local_addr
, htons(port
));
44 sk
= socket(test_family
, SOCK_STREAM
, IPPROTO_TCP
);
46 test_error("socket()");
48 if (different_keyids
) {
49 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, local_addr
, -1, 5, 7))
50 test_error("setsockopt(TCP_AO_ADD_KEY)");
51 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, local_addr
, -1, 7, 5))
52 test_error("setsockopt(TCP_AO_ADD_KEY)");
54 if (test_add_key(sk
, DEFAULT_TEST_PASSWORD
, local_addr
, -1, 100, 100))
55 test_error("setsockopt(TCP_AO_ADD_KEY)");
58 if (bind(sk
, (struct sockaddr
*)&addr
, sizeof(addr
)) < 0)
61 ns_before
= netstat_read();
62 before_aogood
= netstat_get(ns_before
, "TCPAOGood", NULL
);
63 if (test_get_tcp_ao_counters(sk
, &before_ao
))
64 test_error("test_get_tcp_ao_counters()");
66 if (__test_connect_socket(sk
, "lo", (struct sockaddr
*)&addr
,
67 sizeof(addr
), TEST_TIMEOUT_SEC
) < 0) {
68 ns_after
= netstat_read();
69 netstat_print_diff(ns_before
, ns_after
);
70 test_error("failed to connect()");
73 if (test_client_verify(sk
, 100, nr_packets
, TEST_TIMEOUT_SEC
)) {
74 test_fail("%s: tcp connection verify failed", tst
);
79 ns_after
= netstat_read();
80 after_aogood
= netstat_get(ns_after
, "TCPAOGood", NULL
);
81 if (test_get_tcp_ao_counters(sk
, &after_ao
))
82 test_error("test_get_tcp_ao_counters()");
84 /* to debug: netstat_print_diff(ns_before, ns_after); */
85 netstat_free(ns_before
);
87 netstat_free(ns_after
);
89 if (after_aogood
<= before_aogood
) {
90 test_fail("%s: TCPAOGood counter mismatch: %" PRIu64
" <= %" PRIu64
,
91 tst
, after_aogood
, before_aogood
);
96 if (test_tcp_ao_counters_cmp(tst
, &before_ao
, &after_ao
, TEST_CNT_GOOD
)) {
101 if (!check_restore
) {
102 test_ok("%s: connect TCPAOGood %" PRIu64
" => %" PRIu64
,
103 tst
, before_aogood
, after_aogood
);
108 test_enable_repair(sk
);
109 test_sock_checkpoint(sk
, &img
, &addr
);
111 addr
.sin6_port
= htons(port
+ 1);
113 addr
.sin_port
= htons(port
+ 1);
115 test_ao_checkpoint(sk
, &ao_img
);
118 sk
= socket(test_family
, SOCK_STREAM
, IPPROTO_TCP
);
120 test_error("socket()");
122 test_enable_repair(sk
);
123 __test_sock_restore(sk
, "lo", &img
, &addr
, &addr
, sizeof(addr
));
124 if (different_keyids
) {
125 if (test_add_repaired_key(sk
, DEFAULT_TEST_PASSWORD
, 0,
126 local_addr
, -1, 7, 5))
127 test_error("setsockopt(TCP_AO_ADD_KEY)");
128 if (test_add_repaired_key(sk
, DEFAULT_TEST_PASSWORD
, 0,
129 local_addr
, -1, 5, 7))
130 test_error("setsockopt(TCP_AO_ADD_KEY)");
132 if (test_add_repaired_key(sk
, DEFAULT_TEST_PASSWORD
, 0,
133 local_addr
, -1, 100, 100))
134 test_error("setsockopt(TCP_AO_ADD_KEY)");
136 test_ao_restore(sk
, &ao_img
);
137 test_disable_repair(sk
);
138 test_sock_state_free(&img
);
139 if (test_client_verify(sk
, 100, nr_packets
, TEST_TIMEOUT_SEC
)) {
140 test_fail("%s: tcp connection verify failed", tst
);
144 ns_after
= netstat_read();
145 after_aogood
= netstat_get(ns_after
, "TCPAOGood", NULL
);
146 /* to debug: netstat_print_diff(ns_before, ns_after); */
147 netstat_free(ns_before
);
148 netstat_free(ns_after
);
150 if (after_aogood
<= before_aogood
) {
151 test_fail("%s: TCPAOGood counter mismatch: %" PRIu64
" <= %" PRIu64
,
152 tst
, after_aogood
, before_aogood
);
155 test_ok("%s: connect TCPAOGood %" PRIu64
" => %" PRIu64
,
156 tst
, before_aogood
, after_aogood
);
159 static void *client_fn(void *arg
)
161 unsigned int port
= test_server_port
;
165 tcp_self_connect("self-connect(same keyids)", port
++, false, false);
167 /* expecting rnext to change based on the first segment RNext != Current */
168 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST
, local_addr
, local_addr
,
169 port
, port
, 0, -1, -1, -1, -1, -1, 7, 5, -1);
170 tcp_self_connect("self-connect(different keyids)", port
++, true, false);
171 tcp_self_connect("self-connect(restore)", port
, false, true);
172 port
+= 2; /* restore test restores over different port */
173 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST
, local_addr
, local_addr
,
174 port
, port
, 0, -1, -1, -1, -1, -1, 7, 5, -1);
175 /* intentionally on restore they are added to the socket in different order */
176 trace_ao_event_expect(TCP_AO_RNEXT_REQUEST
, local_addr
, local_addr
,
177 port
+ 1, port
+ 1, 0, -1, -1, -1, -1, -1, 5, 7, -1);
178 tcp_self_connect("self-connect(restore, different keyids)", port
, true, true);
179 port
+= 2; /* restore test restores over different port */
184 int main(int argc
, char *argv
[])
186 test_init(5, client_fn
, NULL
);