df05ef874b
We have to release the existing objects on netns removal otherwise we leak them. Chains are unregistered in first place to make sure no packets are walking on our rules and sets anymore. The object release happens by when we unregister the family via nft_release_afinfo() which is called from nft_unregister_afinfo() from the corresponding __net_exit path in every family. Reported-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
105 lines
2.4 KiB
C
105 lines
2.4 KiB
C
/*
|
|
* Copyright (c) 2012-2014 Patrick McHardy <kaber@trash.net>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/netfilter_ipv4.h>
|
|
#include <linux/netfilter_ipv6.h>
|
|
#include <net/netfilter/nf_tables.h>
|
|
#include <net/netfilter/nf_tables_ipv4.h>
|
|
#include <net/netfilter/nf_tables_ipv6.h>
|
|
#include <net/ip.h>
|
|
|
|
static void nft_inet_hook_ops_init(struct nf_hook_ops *ops, unsigned int n)
|
|
{
|
|
struct nft_af_info *afi;
|
|
|
|
if (n == 1)
|
|
afi = &nft_af_ipv4;
|
|
else
|
|
afi = &nft_af_ipv6;
|
|
|
|
ops->pf = afi->family;
|
|
if (afi->hooks[ops->hooknum])
|
|
ops->hook = afi->hooks[ops->hooknum];
|
|
}
|
|
|
|
static struct nft_af_info nft_af_inet __read_mostly = {
|
|
.family = NFPROTO_INET,
|
|
.nhooks = NF_INET_NUMHOOKS,
|
|
.owner = THIS_MODULE,
|
|
.nops = 2,
|
|
.hook_ops_init = nft_inet_hook_ops_init,
|
|
};
|
|
|
|
static int __net_init nf_tables_inet_init_net(struct net *net)
|
|
{
|
|
net->nft.inet = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
|
|
if (net->nft.inet == NULL)
|
|
return -ENOMEM;
|
|
memcpy(net->nft.inet, &nft_af_inet, sizeof(nft_af_inet));
|
|
|
|
if (nft_register_afinfo(net, net->nft.inet) < 0)
|
|
goto err;
|
|
|
|
return 0;
|
|
|
|
err:
|
|
kfree(net->nft.inet);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
static void __net_exit nf_tables_inet_exit_net(struct net *net)
|
|
{
|
|
nft_unregister_afinfo(net, net->nft.inet);
|
|
kfree(net->nft.inet);
|
|
}
|
|
|
|
static struct pernet_operations nf_tables_inet_net_ops = {
|
|
.init = nf_tables_inet_init_net,
|
|
.exit = nf_tables_inet_exit_net,
|
|
};
|
|
|
|
static const struct nf_chain_type filter_inet = {
|
|
.name = "filter",
|
|
.type = NFT_CHAIN_T_DEFAULT,
|
|
.family = NFPROTO_INET,
|
|
.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_inet_init(void)
|
|
{
|
|
int ret;
|
|
|
|
nft_register_chain_type(&filter_inet);
|
|
ret = register_pernet_subsys(&nf_tables_inet_net_ops);
|
|
if (ret < 0)
|
|
nft_unregister_chain_type(&filter_inet);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void __exit nf_tables_inet_exit(void)
|
|
{
|
|
unregister_pernet_subsys(&nf_tables_inet_net_ops);
|
|
nft_unregister_chain_type(&filter_inet);
|
|
}
|
|
|
|
module_init(nf_tables_inet_init);
|
|
module_exit(nf_tables_inet_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
|
MODULE_ALIAS_NFT_FAMILY(1);
|