// SPDX-License-Identifier: GPL-2.0
/*
 * The test checks that both active and passive reset have correct TCP-AO
 * signature. An "active" reset (abort) here is procured from closing
 * listen() socket with non-accepted connections in the queue:
 * inet_csk_listen_stop() => inet_child_forget() =>
 *                        => tcp_disconnect() => tcp_send_active_reset()
 *
 * The passive reset is quite hard to get on established TCP connections.
 * It could be procured from non-established states, but the synchronization
 * part from userspace in order to reliably get RST seems uneasy.
 * So, instead it's procured by corrupting SEQ number on TIMED-WAIT state.
 *
 * It's important to test both passive and active RST as they go through
 * different code-paths:
 * - tcp_send_active_reset() makes no-data skb, sends it with tcp_transmit_skb()
 * - tcp_v*_send_reset() create their reply skbs and send them with
 *   ip_send_unicast_reply()
 *
 * In both cases TCP-AO signatures have to be correct, which is verified by
 * (1) checking that the TCP-AO connection was reset and (2) TCP-AO counters.
 *
 * Author: Dmitry Safonov <dima@arista.com>
 */
#include <inttypes.h>
#include "../../../../include/linux/kernel.h"
#include "aolib.h"

const size_t quota = 1000;
const size_t packet_sz = 100;
/*
 * Backlog == 0 means 1 connection in queue, see:
 * commit 64a146513f8f ("[NET]: Revert incorrect accept queue...")
 */
const unsigned int backlog;

static void netstats_check(struct netstat *before, struct netstat *after,
			   char *msg)
{
	uint64_t before_cnt, after_cnt;

	before_cnt = netstat_get(before, "TCPAORequired", NULL);
	after_cnt = netstat_get(after, "TCPAORequired", NULL);
	if (after_cnt > before_cnt)
		test_fail("Segments without AO sign (%s): %" PRIu64 " => %" PRIu64,
			  msg, before_cnt, after_cnt);
	else
		test_ok("No segments without AO sign (%s)", msg);

	before_cnt = netstat_get(before, "TCPAOGood", NULL);
	after_cnt = netstat_get(after, "TCPAOGood", NULL);
	if (after_cnt <= before_cnt)
		test_fail("Signed AO segments (%s): %" PRIu64 " => %" PRIu64,
			  msg, before_cnt, after_cnt);
	else
		test_ok("Signed AO segments (%s): %" PRIu64 " => %" PRIu64,
			  msg, before_cnt, after_cnt);

	before_cnt = netstat_get(before, "TCPAOBad", NULL);
	after_cnt = netstat_get(after, "TCPAOBad", NULL);
	if (after_cnt > before_cnt)
		test_fail("Segments with bad AO sign (%s): %" PRIu64 " => %" PRIu64,
			  msg, before_cnt, after_cnt);
	else
		test_ok("No segments with bad AO sign (%s)", msg);
}

/*
 * Another way to send RST, but not through tcp_v{4,6}_send_reset()
 * is tcp_send_active_reset(), that is not in reply to inbound segment,
 * but rather active send. It uses tcp_transmit_skb(), so that should
 * work, but as it also sends RST - nice that it can be covered as well.
 */
static void close_forced(int sk)
{
	struct linger sl;

	sl.l_onoff = 1;
	sl.l_linger = 0;
	if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl)))
		test_error("setsockopt(SO_LINGER)");
	close(sk);
}

static void test_server_active_rst(unsigned int port)
{
	struct tcp_ao_counters cnt1, cnt2;
	ssize_t bytes;
	int sk, lsk;

	lsk = test_listen_socket(this_ip_addr, port, backlog);
	if (test_add_key(lsk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");
	if (test_get_tcp_ao_counters(lsk, &cnt1))
		test_error("test_get_tcp_ao_counters()");

	synchronize_threads(); /* 1: MKT added */
	if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0))
		test_error("test_wait_fd()");

	sk = accept(lsk, NULL, NULL);
	if (sk < 0)
		test_error("accept()");

	synchronize_threads(); /* 2: connection accept()ed, another queued */
	if (test_get_tcp_ao_counters(lsk, &cnt2))
		test_error("test_get_tcp_ao_counters()");

	synchronize_threads(); /* 3: close listen socket */
	close(lsk);
	bytes = test_server_run(sk, quota, 0);
	if (bytes != quota)
		test_error("servered only %zd bytes", bytes);
	else
		test_ok("servered %zd bytes", bytes);

	synchronize_threads(); /* 4: finishing up */
	close_forced(sk);

	synchronize_threads(); /* 5: closed active sk */

	synchronize_threads(); /* 6: counters checks */
	if (test_tcp_ao_counters_cmp("active RST server", &cnt1, &cnt2, TEST_CNT_GOOD))
		test_fail("MKT counters (server) have not only good packets");
	else
		test_ok("MKT counters are good on server");
}

static void test_server_passive_rst(unsigned int port)
{
	struct tcp_ao_counters ao1, ao2;
	int sk, lsk;
	ssize_t bytes;

	lsk = test_listen_socket(this_ip_addr, port, 1);

	if (test_add_key(lsk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");

	synchronize_threads(); /* 1: MKT added => connect() */
	if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0))
		test_error("test_wait_fd()");

	sk = accept(lsk, NULL, NULL);
	if (sk < 0)
		test_error("accept()");

	synchronize_threads(); /* 2: accepted => send data */
	close(lsk);
	if (test_get_tcp_ao_counters(sk, &ao1))
		test_error("test_get_tcp_ao_counters()");

	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
	if (bytes != quota) {
		if (bytes > 0)
			test_fail("server served: %zd", bytes);
		else
			test_fail("server returned %zd", bytes);
	}

	synchronize_threads(); /* 3: checkpoint the client */
	synchronize_threads(); /* 4: close the server, creating twsk */
	if (test_get_tcp_ao_counters(sk, &ao2))
		test_error("test_get_tcp_ao_counters()");
	close(sk);

	synchronize_threads(); /* 5: restore the socket, send more data */
	test_tcp_ao_counters_cmp("passive RST server", &ao1, &ao2, TEST_CNT_GOOD);

	synchronize_threads(); /* 6: server exits */
}

static void *server_fn(void *arg)
{
	struct netstat *ns_before, *ns_after;
	unsigned int port = test_server_port;

	ns_before = netstat_read();

	test_server_active_rst(port++);
	test_server_passive_rst(port++);

	ns_after = netstat_read();
	netstats_check(ns_before, ns_after, "server");
	netstat_free(ns_after);
	netstat_free(ns_before);
	synchronize_threads(); /* exit */

	synchronize_threads(); /* don't race to exit() - client exits */
	return NULL;
}

static int test_wait_fds(int sk[], size_t nr, bool is_writable[],
			 ssize_t wait_for, time_t sec)
{
	struct timeval tv = { .tv_sec = sec };
	struct timeval *ptv = NULL;
	fd_set left;
	size_t i;
	int ret;

	FD_ZERO(&left);
	for (i = 0; i < nr; i++) {
		FD_SET(sk[i], &left);
		if (is_writable)
			is_writable[i] = false;
	}

	if (sec)
		ptv = &tv;

	do {
		bool is_empty = true;
		fd_set fds, efds;
		int nfd = 0;

		FD_ZERO(&fds);
		FD_ZERO(&efds);
		for (i = 0; i < nr; i++) {
			if (!FD_ISSET(sk[i], &left))
				continue;

			if (sk[i] > nfd)
				nfd = sk[i];

			FD_SET(sk[i], &fds);
			FD_SET(sk[i], &efds);
			is_empty = false;
		}
		if (is_empty)
			return -ENOENT;

		errno = 0;
		ret = select(nfd + 1, NULL, &fds, &efds, ptv);
		if (ret < 0)
			return -errno;
		if (!ret)
			return -ETIMEDOUT;
		for (i = 0; i < nr; i++) {
			if (FD_ISSET(sk[i], &fds)) {
				if (is_writable)
					is_writable[i] = true;
				FD_CLR(sk[i], &left);
				wait_for--;
				continue;
			}
			if (FD_ISSET(sk[i], &efds)) {
				FD_CLR(sk[i], &left);
				wait_for--;
			}
		}
	} while (wait_for > 0);

	return 0;
}

static void test_client_active_rst(unsigned int port)
{
	/* one in queue, another accept()ed */
	unsigned int wait_for = backlog + 2;
	int i, sk[3], err;
	bool is_writable[ARRAY_SIZE(sk)] = {false};
	unsigned int last = ARRAY_SIZE(sk) - 1;

	for (i = 0; i < ARRAY_SIZE(sk); i++) {
		sk[i] = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
		if (sk[i] < 0)
			test_error("socket()");
		if (test_add_key(sk[i], DEFAULT_TEST_PASSWORD,
				 this_ip_dest, -1, 100, 100))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
	}

	synchronize_threads(); /* 1: MKT added */
	for (i = 0; i < last; i++) {
		err = _test_connect_socket(sk[i], this_ip_dest, port,
					       (i == 0) ? TEST_TIMEOUT_SEC : -1);

		if (err < 0)
			test_error("failed to connect()");
	}

	synchronize_threads(); /* 2: connection accept()ed, another queued */
	err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC);
	if (err < 0)
		test_error("test_wait_fds(): %d", err);

	synchronize_threads(); /* 3: close listen socket */
	if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
		test_fail("Failed to send data on connected socket");
	else
		test_ok("Verified established tcp connection");

	synchronize_threads(); /* 4: finishing up */
	err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
	if (err < 0)
		test_error("failed to connect()");

	synchronize_threads(); /* 5: closed active sk */
	err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL,
			    wait_for, TEST_TIMEOUT_SEC);
	if (err < 0)
		test_error("select(): %d", err);

	for (i = 0; i < ARRAY_SIZE(sk); i++) {
		socklen_t slen = sizeof(err);

		if (getsockopt(sk[i], SOL_SOCKET, SO_ERROR, &err, &slen))
			test_error("getsockopt()");
		if (is_writable[i] && err != ECONNRESET) {
			test_fail("sk[%d] = %d, err = %d, connection wasn't reset",
				  i, sk[i], err);
		} else {
			test_ok("sk[%d] = %d%s", i, sk[i],
				is_writable[i] ? ", connection was reset" : "");
		}
	}
	synchronize_threads(); /* 6: counters checks */
}

static void test_client_passive_rst(unsigned int port)
{
	struct tcp_ao_counters ao1, ao2;
	struct tcp_ao_repair ao_img;
	struct tcp_sock_state img;
	sockaddr_af saddr;
	int sk, err;

	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
	if (sk < 0)
		test_error("socket()");

	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");

	synchronize_threads(); /* 1: MKT added => connect() */
	if (test_connect_socket(sk, this_ip_dest, port) <= 0)
		test_error("failed to connect()");

	synchronize_threads(); /* 2: accepted => send data */
	if (test_client_verify(sk, packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
		test_fail("Failed to send data on connected socket");
	else
		test_ok("Verified established tcp connection");

	synchronize_threads(); /* 3: checkpoint the client */
	test_enable_repair(sk);
	test_sock_checkpoint(sk, &img, &saddr);
	test_ao_checkpoint(sk, &ao_img);
	test_disable_repair(sk);

	synchronize_threads(); /* 4: close the server, creating twsk */

	/*
	 * The "corruption" in SEQ has to be small enough to fit into TCP
	 * window, see tcp_timewait_state_process() for out-of-window
	 * segments.
	 */
	img.out.seq += 5; /* 5 is more noticeable in tcpdump than 1 */

	/*
	 * FIXME: This is kind-of ugly and dirty, but it works.
	 *
	 * At this moment, the server has close'ed(sk).
	 * The passive RST that is being targeted here is new data after
	 * half-duplex close, see tcp_timewait_state_process() => TCP_TW_RST
	 *
	 * What is needed here is:
	 * (1) wait for FIN from the server
	 * (2) make sure that the ACK from the client went out
	 * (3) make sure that the ACK was received and processed by the server
	 *
	 * Otherwise, the data that will be sent from "repaired" socket
	 * post SEQ corruption may get to the server before it's in
	 * TCP_FIN_WAIT2.
	 *
	 * (1) is easy with select()/poll()
	 * (2) is possible by polling tcpi_state from TCP_INFO
	 * (3) is quite complex: as server's socket was already closed,
	 *     probably the way to do it would be tcp-diag.
	 */
	sleep(TEST_RETRANSMIT_SEC);

	synchronize_threads(); /* 5: restore the socket, send more data */
	test_kill_sk(sk);

	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
	if (sk < 0)
		test_error("socket()");

	test_enable_repair(sk);
	test_sock_restore(sk, &img, &saddr, this_ip_dest, port);
	if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0, this_ip_dest, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");
	test_ao_restore(sk, &ao_img);

	if (test_get_tcp_ao_counters(sk, &ao1))
		test_error("test_get_tcp_ao_counters()");

	test_disable_repair(sk);
	test_sock_state_free(&img);

	/*
	 * This is how "passive reset" is acquired in this test from TCP_TW_RST:
	 *
	 * IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [P.], seq 901:1001, ack 1001, win 249,
	 *    options [tcp-ao keyid 100 rnextkeyid 100 mac 0x10217d6c36a22379086ef3b1], length 100
	 * IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [F.], seq 1001, ack 1001, win 249,
	 *    options [tcp-ao keyid 100 rnextkeyid 100 mac 0x104ffc99b98c10a5298cc268], length 0
	 * IP 10.0.1.1.59772 > 10.0.254.1.7011: Flags [.], ack 1002, win 251,
	 *    options [tcp-ao keyid 100 rnextkeyid 100 mac 0xe496dd4f7f5a8a66873c6f93,nop,nop,sack 1 {1001:1002}], length 0
	 * IP 10.0.1.1.59772 > 10.0.254.1.7011: Flags [P.], seq 1006:1106, ack 1001, win 251,
	 *    options [tcp-ao keyid 100 rnextkeyid 100 mac 0x1b5f3330fb23fbcd0c77d0ca], length 100
	 * IP 10.0.254.1.7011 > 10.0.1.1.59772: Flags [R], seq 3215596252, win 0,
	 *    options [tcp-ao keyid 100 rnextkeyid 100 mac 0x0bcfbbf497bce844312304b2], length 0
	 */
	err = test_client_verify(sk, packet_sz, quota / packet_sz, 2 * TEST_TIMEOUT_SEC);
	/* Make sure that the connection was reset, not timeouted */
	if (err && err == -ECONNRESET)
		test_ok("client sock was passively reset post-seq-adjust");
	else if (err)
		test_fail("client sock was not reset post-seq-adjust: %d", err);
	else
		test_fail("client sock is yet connected post-seq-adjust");

	if (test_get_tcp_ao_counters(sk, &ao2))
		test_error("test_get_tcp_ao_counters()");

	synchronize_threads(); /* 6: server exits */
	close(sk);
	test_tcp_ao_counters_cmp("client passive RST", &ao1, &ao2, TEST_CNT_GOOD);
}

static void *client_fn(void *arg)
{
	struct netstat *ns_before, *ns_after;
	unsigned int port = test_server_port;

	ns_before = netstat_read();

	test_client_active_rst(port++);
	test_client_passive_rst(port++);

	ns_after = netstat_read();
	netstats_check(ns_before, ns_after, "client");
	netstat_free(ns_after);
	netstat_free(ns_before);

	synchronize_threads(); /* exit */
	return NULL;
}

int main(int argc, char *argv[])
{
	test_init(14, server_fn, client_fn);
	return 0;
}
