/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Generic part shared by ipv4 and ipv6 backends.
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nft_fib.h>

const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
	[NFTA_FIB_DREG]		= { .type = NLA_U32 },
	[NFTA_FIB_RESULT]	= { .type = NLA_U32 },
	[NFTA_FIB_FLAGS]	= { .type = NLA_U32 },
};
EXPORT_SYMBOL(nft_fib_policy);

#define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
			NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)

int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
		     const struct nft_data **data)
{
	const struct nft_fib *priv = nft_expr_priv(expr);
	unsigned int hooks;

	switch (priv->result) {
	case NFT_FIB_RESULT_OIF: /* fallthrough */
	case NFT_FIB_RESULT_OIFNAME:
		hooks = (1 << NF_INET_PRE_ROUTING);
		break;
	case NFT_FIB_RESULT_ADDRTYPE:
		if (priv->flags & NFTA_FIB_F_IIF)
			hooks = (1 << NF_INET_PRE_ROUTING) |
				(1 << NF_INET_LOCAL_IN) |
				(1 << NF_INET_FORWARD);
		else if (priv->flags & NFTA_FIB_F_OIF)
			hooks = (1 << NF_INET_LOCAL_OUT) |
				(1 << NF_INET_POST_ROUTING) |
				(1 << NF_INET_FORWARD);
		else
			hooks = (1 << NF_INET_LOCAL_IN) |
				(1 << NF_INET_LOCAL_OUT) |
				(1 << NF_INET_FORWARD) |
				(1 << NF_INET_PRE_ROUTING) |
				(1 << NF_INET_POST_ROUTING);

		break;
	default:
		return -EINVAL;
	}

	return nft_chain_validate_hooks(ctx->chain, hooks);
}
EXPORT_SYMBOL_GPL(nft_fib_validate);

int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
		 const struct nlattr * const tb[])
{
	struct nft_fib *priv = nft_expr_priv(expr);
	unsigned int len;
	int err;

	if (!tb[NFTA_FIB_DREG] || !tb[NFTA_FIB_RESULT] || !tb[NFTA_FIB_FLAGS])
		return -EINVAL;

	priv->flags = ntohl(nla_get_be32(tb[NFTA_FIB_FLAGS]));

	if (priv->flags == 0 || (priv->flags & ~NFTA_FIB_F_ALL))
		return -EINVAL;

	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) ==
			   (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR))
		return -EINVAL;
	if ((priv->flags & (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)) ==
			   (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF))
		return -EINVAL;
	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)
		return -EINVAL;

	priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
	priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);

	switch (priv->result) {
	case NFT_FIB_RESULT_OIF:
		if (priv->flags & NFTA_FIB_F_OIF)
			return -EINVAL;
		len = sizeof(int);
		break;
	case NFT_FIB_RESULT_OIFNAME:
		if (priv->flags & NFTA_FIB_F_OIF)
			return -EINVAL;
		len = IFNAMSIZ;
		break;
	case NFT_FIB_RESULT_ADDRTYPE:
		len = sizeof(u32);
		break;
	default:
		return -EINVAL;
	}

	err = nft_validate_register_store(ctx, priv->dreg, NULL,
					  NFT_DATA_VALUE, len);
	if (err < 0)
		return err;

	return nft_fib_validate(ctx, expr, NULL);
}
EXPORT_SYMBOL_GPL(nft_fib_init);

int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
{
	const struct nft_fib *priv = nft_expr_priv(expr);

	if (nft_dump_register(skb, NFTA_FIB_DREG, priv->dreg))
		return -1;

	if (nla_put_be32(skb, NFTA_FIB_RESULT, htonl(priv->result)))
		return -1;

	if (nla_put_be32(skb, NFTA_FIB_FLAGS, htonl(priv->flags)))
		return -1;

	return 0;
}
EXPORT_SYMBOL_GPL(nft_fib_dump);

void nft_fib_store_result(void *reg, enum nft_fib_result r,
			  const struct nft_pktinfo *pkt, int index)
{
	struct net_device *dev;
	u32 *dreg = reg;

	switch (r) {
	case NFT_FIB_RESULT_OIF:
		*dreg = index;
		break;
	case NFT_FIB_RESULT_OIFNAME:
		dev = dev_get_by_index_rcu(nft_net(pkt), index);
		strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
		break;
	default:
		WARN_ON_ONCE(1);
		*dreg = 0;
		break;
	}
}
EXPORT_SYMBOL_GPL(nft_fib_store_result);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
