/*
 * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
 * Copyright (c) 2012-2013 Pablo Neira Ayuso <pablo@netfilter.org>
 *
 * 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.
 *
 * Development of this code funded by Astaro AG (http://www.astaro.com/)
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/ipv6.h>
#include <linux/netfilter_ipv6.h>
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_ipv6.h>

static unsigned int nft_do_chain_ipv6(void *priv,
				      struct sk_buff *skb,
				      const struct nf_hook_state *state)
{
	struct nft_pktinfo pkt;

	nft_set_pktinfo_ipv6(&pkt, skb, state);

	return nft_do_chain(&pkt, priv);
}

static unsigned int nft_ipv6_output(void *priv,
				    struct sk_buff *skb,
				    const struct nf_hook_state *state)
{
	if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
		if (net_ratelimit())
			pr_info("nf_tables_ipv6: ignoring short SOCK_RAW "
				"packet\n");
		return NF_ACCEPT;
	}

	return nft_do_chain_ipv6(priv, skb, state);
}

struct nft_af_info nft_af_ipv6 __read_mostly = {
	.family		= NFPROTO_IPV6,
	.nhooks		= NF_INET_NUMHOOKS,
	.owner		= THIS_MODULE,
	.nops		= 1,
	.hooks		= {
		[NF_INET_LOCAL_IN]	= nft_do_chain_ipv6,
		[NF_INET_LOCAL_OUT]	= nft_ipv6_output,
		[NF_INET_FORWARD]	= nft_do_chain_ipv6,
		[NF_INET_PRE_ROUTING]	= nft_do_chain_ipv6,
		[NF_INET_POST_ROUTING]	= nft_do_chain_ipv6,
	},
};
EXPORT_SYMBOL_GPL(nft_af_ipv6);

static int nf_tables_ipv6_init_net(struct net *net)
{
	net->nft.ipv6 = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
	if (net->nft.ipv6 == NULL)
		return -ENOMEM;

	memcpy(net->nft.ipv6, &nft_af_ipv6, sizeof(nft_af_ipv6));

	if (nft_register_afinfo(net, net->nft.ipv6) < 0)
		goto err;

	return 0;
err:
	kfree(net->nft.ipv6);
	return -ENOMEM;
}

static void nf_tables_ipv6_exit_net(struct net *net)
{
	nft_unregister_afinfo(net, net->nft.ipv6);
	kfree(net->nft.ipv6);
}

static struct pernet_operations nf_tables_ipv6_net_ops = {
	.init	= nf_tables_ipv6_init_net,
	.exit	= nf_tables_ipv6_exit_net,
};

static const struct nf_chain_type filter_ipv6 = {
	.name		= "filter",
	.type		= NFT_CHAIN_T_DEFAULT,
	.family		= NFPROTO_IPV6,
	.owner		= THIS_MODULE,
	.hook_mask	= (1 << NF_INET_LOCAL_IN) |
			  (1 << NF_INET_LOCAL_OUT) |
			  (1 << NF_INET_FORWARD) |
			  (1 << NF_INET_PRE_ROUTING) |
			  (1 << NF_INET_POST_ROUTING),
};

static int __init nf_tables_ipv6_init(void)
{
	int ret;

	ret = nft_register_chain_type(&filter_ipv6);
	if (ret < 0)
		return ret;

	ret = register_pernet_subsys(&nf_tables_ipv6_net_ops);
	if (ret < 0)
		nft_unregister_chain_type(&filter_ipv6);

	return ret;
}

static void __exit nf_tables_ipv6_exit(void)
{
	unregister_pernet_subsys(&nf_tables_ipv6_net_ops);
	nft_unregister_chain_type(&filter_ipv6);
}

module_init(nf_tables_ipv6_init);
module_exit(nf_tables_ipv6_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
MODULE_ALIAS_NFT_FAMILY(AF_INET6);
