File Index
Files and directories
Sign in
FILE

self-connect.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/tcp_ao/self-connect.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Author: Dmitry Safonov <dima@arista.com> */
  3#include <inttypes.h>
  4#include "aolib.h"
  5
  6static union tcp_addr local_addr;
  7
  8static void __setup_lo_intf(const char *lo_intf,
  9			    const char *addr_str, uint8_t prefix)
 10{
 11	if (inet_pton(TEST_FAMILY, addr_str, &local_addr) != 1)
 12		test_error("Can't convert local ip address");
 13
 14	if (ip_addr_add(lo_intf, TEST_FAMILY, local_addr, prefix))
 15		test_error("Failed to add %s ip address", lo_intf);
 16
 17	if (link_set_up(lo_intf))
 18		test_error("Failed to bring %s up", lo_intf);
 19
 20	if (ip_route_add(lo_intf, TEST_FAMILY, local_addr, local_addr))
 21		test_error("Failed to add a local route %s", lo_intf);
 22}
 23
 24static void setup_lo_intf(const char *lo_intf)
 25{
 26#ifdef IPV6_TEST
 27	__setup_lo_intf(lo_intf, "::1", 128);
 28#else
 29	__setup_lo_intf(lo_intf, "127.0.0.1", 8);
 30#endif
 31}
 32
 33static void tcp_self_connect(const char *tst, unsigned int port,
 34			     bool different_keyids, bool check_restore)
 35{
 36	struct tcp_counters before, after;
 37	uint64_t before_aogood, after_aogood;
 38	struct netstat *ns_before, *ns_after;
 39	const size_t nr_packets = 20;
 40	struct tcp_ao_repair ao_img;
 41	struct tcp_sock_state img;
 42	sockaddr_af addr;
 43	int sk;
 44
 45	tcp_addr_to_sockaddr_in(&addr, &local_addr, htons(port));
 46
 47	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
 48	if (sk < 0)
 49		test_error("socket()");
 50
 51	if (different_keyids) {
 52		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 5, 7))
 53			test_error("setsockopt(TCP_AO_ADD_KEY)");
 54		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 7, 5))
 55			test_error("setsockopt(TCP_AO_ADD_KEY)");
 56	} else {
 57		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 100, 100))
 58			test_error("setsockopt(TCP_AO_ADD_KEY)");
 59	}
 60
 61	if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0)
 62		test_error("bind()");
 63
 64	ns_before = netstat_read();
 65	before_aogood = netstat_get(ns_before, "TCPAOGood", NULL);
 66	if (test_get_tcp_counters(sk, &before))
 67		test_error("test_get_tcp_counters()");
 68
 69	if (__test_connect_socket(sk, "lo", (struct sockaddr *)&addr,
 70				  sizeof(addr), 0) < 0) {
 71		ns_after = netstat_read();
 72		netstat_print_diff(ns_before, ns_after);
 73		test_error("failed to connect()");
 74	}
 75
 76	if (test_client_verify(sk, 100, nr_packets)) {
 77		test_fail("%s: tcp connection verify failed", tst);
 78		close(sk);
 79		return;
 80	}
 81
 82	ns_after = netstat_read();
 83	after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
 84	if (test_get_tcp_counters(sk, &after))
 85		test_error("test_get_tcp_counters()");
 86	if (!check_restore) {
 87		/* to debug: netstat_print_diff(ns_before, ns_after); */
 88		netstat_free(ns_before);
 89	}
 90	netstat_free(ns_after);
 91
 92	if (after_aogood <= before_aogood) {
 93		test_fail("%s: TCPAOGood counter mismatch: %" PRIu64 " <= %" PRIu64,
 94			  tst, after_aogood, before_aogood);
 95		close(sk);
 96		return;
 97	}
 98
 99	if (test_assert_counters(tst, &before, &after, TEST_CNT_GOOD)) {
100		close(sk);
101		return;
102	}
103
104	if (!check_restore) {
105		test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
106				tst, before_aogood, after_aogood);
107		close(sk);
108		return;
109	}
110
111	test_enable_repair(sk);
112	test_sock_checkpoint(sk, &img, &addr);
113#ifdef IPV6_TEST
114	addr.sin6_port = htons(port + 1);
115#else
116	addr.sin_port = htons(port + 1);
117#endif
118	test_ao_checkpoint(sk, &ao_img);
119	test_kill_sk(sk);
120
121	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
122	if (sk < 0)
123		test_error("socket()");
124
125	test_enable_repair(sk);
126	__test_sock_restore(sk, "lo", &img, &addr, &addr, sizeof(addr));
127	if (different_keyids) {
128		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
129					  local_addr, -1, 7, 5))
130			test_error("setsockopt(TCP_AO_ADD_KEY)");
131		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
132					  local_addr, -1, 5, 7))
133			test_error("setsockopt(TCP_AO_ADD_KEY)");
134	} else {
135		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
136					  local_addr, -1, 100, 100))
137			test_error("setsockopt(TCP_AO_ADD_KEY)");
138	}
139	test_ao_restore(sk, &ao_img);
140	test_disable_repair(sk);
141	test_sock_state_free(&img);
142	if (test_client_verify(sk, 100, nr_packets)) {
143		test_fail("%s: tcp connection verify failed", tst);
144		close(sk);
145		return;
146	}
147	ns_after = netstat_read();
148	after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
149	/* to debug: netstat_print_diff(ns_before, ns_after); */
150	netstat_free(ns_before);
151	netstat_free(ns_after);
152	close(sk);
153	if (after_aogood <= before_aogood) {
154		test_fail("%s: TCPAOGood counter mismatch: %" PRIu64 " <= %" PRIu64,
155			  tst, after_aogood, before_aogood);
156		return;
157	}
158	test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
159			tst, before_aogood, after_aogood);
160}
161
162static void *client_fn(void *arg)
163{
164	unsigned int port = test_server_port;
165
166	setup_lo_intf("lo");
167
168	tcp_self_connect("self-connect(same keyids)", port++, false, false);
169
170	/* expecting rnext to change based on the first segment RNext != Current */
171	trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
172			      port, port, 0, -1, -1, -1, -1, -1, 7, 5, -1);
173	tcp_self_connect("self-connect(different keyids)", port++, true, false);
174	tcp_self_connect("self-connect(restore)", port, false, true);
175	port += 2; /* restore test restores over different port */
176	trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
177			      port, port, 0, -1, -1, -1, -1, -1, 7, 5, -1);
178	/* intentionally on restore they are added to the socket in different order */
179	trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
180			      port + 1, port + 1, 0, -1, -1, -1, -1, -1, 5, 7, -1);
181	tcp_self_connect("self-connect(restore, different keyids)", port, true, true);
182	port += 2; /* restore test restores over different port */
183
184	return NULL;
185}
186
187int main(int argc, char *argv[])
188{
189	test_init(5, client_fn, NULL);
190	return 0;
191}
~/ Read-only file preview.