/*
 * Copyright (c) 2021 BayLibre SAS
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_REGISTER(npf_base, CONFIG_NET_PKT_FILTER_LOG_LEVEL);

#include <net/net_core.h>
#include <net/net_pkt_filter.h>
#include <spinlock.h>

/*
 * Our actual rule lists for supported test points
 */

struct npf_rule_list npf_send_rules = {
	.rule_head = SYS_SLIST_STATIC_INIT(&send_rules.rule_head),
	.lock = { },
};

struct npf_rule_list npf_recv_rules = {
	.rule_head = SYS_SLIST_STATIC_INIT(&recv_rules.rule_head),
	.lock = { },
};

/*
 * Rule application
 */

/*
 * All tests must be true to return true.
 * If no tests then it is true.
 */
static bool apply_tests(struct npf_rule *rule, struct net_pkt *pkt)
{
	struct npf_test *test;
	unsigned int i;
	bool result;

	for (i = 0; i < rule->nb_tests; i++) {
		test = rule->tests[i];
		result = test->fn(test, pkt);
		NET_DBG("test %p result %d", test, result);
		if (result == false) {
			return false;
		}
	}

	return true;
}

/*
 * We return the specified result for the first rule whose tests are all true.
 */
static enum net_verdict evaluate(sys_slist_t *rule_head, struct net_pkt *pkt)
{
	struct npf_rule *rule;

	NET_DBG("rule_head %p on pkt %p", rule_head, pkt);

	if (sys_slist_is_empty(rule_head)) {
		NET_DBG("no rules");
		return NET_OK;
	}

	SYS_SLIST_FOR_EACH_CONTAINER(rule_head, rule, node) {
		if (apply_tests(rule, pkt) == true) {
			return rule->result;
		}
	}

	NET_DBG("no matching rules from rule_head %p", rule_head);
	return NET_DROP;
}

static enum net_verdict lock_evaluate(struct npf_rule_list *rules, struct net_pkt *pkt)
{
	k_spinlock_key_t key = k_spin_lock(&rules->lock);
	enum net_verdict result = evaluate(&rules->rule_head, pkt);

	k_spin_unlock(&rules->lock, key);
	return result;
}

bool net_pkt_filter_send_ok(struct net_pkt *pkt)
{
	enum net_verdict result = lock_evaluate(&npf_send_rules, pkt);

	return result == NET_OK;
}

bool net_pkt_filter_recv_ok(struct net_pkt *pkt)
{
	enum net_verdict result = lock_evaluate(&npf_recv_rules, pkt);

	return result == NET_OK;
}

/*
 * Rule management
 */

void npf_insert_rule(struct npf_rule_list *rules, struct npf_rule *rule)
{
	k_spinlock_key_t key = k_spin_lock(&rules->lock);

	NET_DBG("inserting rule %p into %p", rule, rules);
	sys_slist_prepend(&rules->rule_head, &rule->node);

	k_spin_unlock(&rules->lock, key);
}

void npf_append_rule(struct npf_rule_list *rules, struct npf_rule *rule)
{
	__ASSERT(sys_slist_peek_tail(&rules->rule_head) != &npf_default_ok.node, "");
	__ASSERT(sys_slist_peek_tail(&rules->rule_head) != &npf_default_drop.node, "");

	k_spinlock_key_t key = k_spin_lock(&rules->lock);

	NET_DBG("appending rule %p into %p", rule, rules);
	sys_slist_append(&rules->rule_head, &rule->node);

	k_spin_unlock(&rules->lock, key);
}

bool npf_remove_rule(struct npf_rule_list *rules, struct npf_rule *rule)
{
	k_spinlock_key_t key = k_spin_lock(&rules->lock);
	bool result = sys_slist_find_and_remove(&rules->rule_head, &rule->node);

	k_spin_unlock(&rules->lock, key);
	NET_DBG("removing rule %p from %p: %d", rule, rules, result);
	return result;
}

bool npf_remove_all_rules(struct npf_rule_list *rules)
{
	k_spinlock_key_t key = k_spin_lock(&rules->lock);
	bool result = !sys_slist_is_empty(&rules->rule_head);

	if (result) {
		sys_slist_init(&rules->rule_head);
		NET_DBG("removing all rules from %p", rules);
	}

	k_spin_unlock(&rules->lock, key);
	return result;
}

/*
 * Default rule list terminations.
 */

struct npf_rule npf_default_ok = {
	.result = NET_OK,
};

struct npf_rule npf_default_drop = {
	.result = NET_DROP,
};

/*
 * Some simple generic conditions
 */

bool npf_iface_match(struct npf_test *test, struct net_pkt *pkt)
{
	struct npf_test_iface *test_iface =
			CONTAINER_OF(test, struct npf_test_iface, test);

	return test_iface->iface == net_pkt_iface(pkt);
}

bool npf_iface_unmatch(struct npf_test *test, struct net_pkt *pkt)
{
	return !npf_iface_match(test, pkt);
}

bool npf_orig_iface_match(struct npf_test *test, struct net_pkt *pkt)
{
	struct npf_test_iface *test_iface =
			CONTAINER_OF(test, struct npf_test_iface, test);

	return test_iface->iface == net_pkt_orig_iface(pkt);
}

bool npf_orig_iface_unmatch(struct npf_test *test, struct net_pkt *pkt)
{
	return !npf_orig_iface_match(test, pkt);
}

bool npf_size_inbounds(struct npf_test *test, struct net_pkt *pkt)
{
	struct npf_test_size_bounds *bounds =
			CONTAINER_OF(test, struct npf_test_size_bounds, test);
	size_t pkt_size = net_pkt_get_len(pkt);

	return pkt_size >= bounds->min && pkt_size <= bounds->max;
}
