// SPDX-License-Identifier: GPL-2.0
/* Author: Dmitry Safonov <dima@arista.com> */
#include <inttypes.h>
#include "aolib.h"

static union tcp_addr local_addr;

static void __setup_lo_intf(const char *lo_intf,
			    const char *addr_str, uint8_t prefix)
{
	if (inet_pton(TEST_FAMILY, addr_str, &local_addr) != 1)
		test_error("Can't convert local ip address");

	if (ip_addr_add(lo_intf, TEST_FAMILY, local_addr, prefix))
		test_error("Failed to add %s ip address", lo_intf);

	if (link_set_up(lo_intf))
		test_error("Failed to bring %s up", lo_intf);
}

static void setup_lo_intf(const char *lo_intf)
{
#ifdef IPV6_TEST
	__setup_lo_intf(lo_intf, "::1", 128);
#else
	__setup_lo_intf(lo_intf, "127.0.0.1", 8);
#endif
}

static void tcp_self_connect(const char *tst, unsigned int port,
			     bool different_keyids, bool check_restore)
{
	uint64_t before_challenge_ack, after_challenge_ack;
	uint64_t before_syn_challenge, after_syn_challenge;
	struct tcp_ao_counters before_ao, after_ao;
	uint64_t before_aogood, after_aogood;
	struct netstat *ns_before, *ns_after;
	const size_t nr_packets = 20;
	struct tcp_ao_repair ao_img;
	struct tcp_sock_state img;
	sockaddr_af addr;
	int sk;

	tcp_addr_to_sockaddr_in(&addr, &local_addr, htons(port));

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

	if (different_keyids) {
		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 5, 7))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 7, 5))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
	} else {
		if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 100, 100))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
	}

	if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0)
		test_error("bind()");

	ns_before = netstat_read();
	before_aogood = netstat_get(ns_before, "TCPAOGood", NULL);
	before_challenge_ack = netstat_get(ns_before, "TCPChallengeACK", NULL);
	before_syn_challenge = netstat_get(ns_before, "TCPSYNChallenge", NULL);
	if (test_get_tcp_ao_counters(sk, &before_ao))
		test_error("test_get_tcp_ao_counters()");

	if (__test_connect_socket(sk, "lo", (struct sockaddr *)&addr,
				  sizeof(addr), TEST_TIMEOUT_SEC) < 0) {
		ns_after = netstat_read();
		netstat_print_diff(ns_before, ns_after);
		test_error("failed to connect()");
	}

	if (test_client_verify(sk, 100, nr_packets, TEST_TIMEOUT_SEC)) {
		test_fail("%s: tcp connection verify failed", tst);
		close(sk);
		return;
	}

	ns_after = netstat_read();
	after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
	after_challenge_ack = netstat_get(ns_after, "TCPChallengeACK", NULL);
	after_syn_challenge = netstat_get(ns_after, "TCPSYNChallenge", NULL);
	if (test_get_tcp_ao_counters(sk, &after_ao))
		test_error("test_get_tcp_ao_counters()");
	if (!check_restore) {
		/* to debug: netstat_print_diff(ns_before, ns_after); */
		netstat_free(ns_before);
	}
	netstat_free(ns_after);

	if (after_aogood <= before_aogood) {
		test_fail("%s: TCPAOGood counter mismatch: %zu <= %zu",
			  tst, after_aogood, before_aogood);
		close(sk);
		return;
	}
	if (after_challenge_ack <= before_challenge_ack ||
	    after_syn_challenge <= before_syn_challenge) {
		/*
		 * It's also meant to test simultaneous open, so check
		 * these counters as well.
		 */
		test_fail("%s: Didn't challenge SYN or ACK: %zu <= %zu OR %zu <= %zu",
			  tst, after_challenge_ack, before_challenge_ack,
			  after_syn_challenge, before_syn_challenge);
		close(sk);
		return;
	}

	if (test_tcp_ao_counters_cmp(tst, &before_ao, &after_ao, TEST_CNT_GOOD)) {
		close(sk);
		return;
	}

	if (!check_restore) {
		test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
				tst, before_aogood, after_aogood);
		close(sk);
		return;
	}

	test_enable_repair(sk);
	test_sock_checkpoint(sk, &img, &addr);
#ifdef IPV6_TEST
	addr.sin6_port = htons(port + 1);
#else
	addr.sin_port = htons(port + 1);
#endif
	test_ao_checkpoint(sk, &ao_img);
	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, "lo", &img, &addr, &addr, sizeof(addr));
	if (different_keyids) {
		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
					  local_addr, -1, 7, 5))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
					  local_addr, -1, 5, 7))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
	} else {
		if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
					  local_addr, -1, 100, 100))
			test_error("setsockopt(TCP_AO_ADD_KEY)");
	}
	test_ao_restore(sk, &ao_img);
	test_disable_repair(sk);
	test_sock_state_free(&img);
	if (test_client_verify(sk, 100, nr_packets, TEST_TIMEOUT_SEC)) {
		test_fail("%s: tcp connection verify failed", tst);
		close(sk);
		return;
	}
	ns_after = netstat_read();
	after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
	/* to debug: netstat_print_diff(ns_before, ns_after); */
	netstat_free(ns_before);
	netstat_free(ns_after);
	close(sk);
	if (after_aogood <= before_aogood) {
		test_fail("%s: TCPAOGood counter mismatch: %zu <= %zu",
			  tst, after_aogood, before_aogood);
		return;
	}
	test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
			tst, before_aogood, after_aogood);
}

static void *client_fn(void *arg)
{
	unsigned int port = test_server_port;

	setup_lo_intf("lo");

	tcp_self_connect("self-connect(same keyids)", port++, false, false);
	tcp_self_connect("self-connect(different keyids)", port++, true, false);
	tcp_self_connect("self-connect(restore)", port, false, true);
	port += 2;
	tcp_self_connect("self-connect(restore, different keyids)", port, true, true);
	port += 2;

	return NULL;
}

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