netfilter: nf_defrag_ipv6: use net_generic infra

This allows followup patch to remove these members from struct net.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2021-04-01 16:11:07 +02:00 committed by Pablo Neira Ayuso
parent ebfbe67568
commit 8b0adbe3e3
3 changed files with 52 additions and 37 deletions

View File

@ -13,4 +13,10 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user);
struct inet_frags_ctl; struct inet_frags_ctl;
struct nft_ct_frag6_pernet {
struct ctl_table_header *nf_frag_frags_hdr;
struct fqdir *fqdir;
unsigned int users;
};
#endif /* _NF_DEFRAG_IPV6_H */ #endif /* _NF_DEFRAG_IPV6_H */

View File

@ -15,28 +15,13 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/jiffies.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/in6.h>
#include <linux/ipv6.h> #include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/random.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/ipv6_frag.h> #include <net/ipv6_frag.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
#include <net/rawv6.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/inet_ecn.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
@ -44,11 +29,18 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h> #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
#include <net/netns/generic.h>
static const char nf_frags_cache_name[] = "nf-frags"; static const char nf_frags_cache_name[] = "nf-frags";
unsigned int nf_frag_pernet_id __read_mostly;
static struct inet_frags nf_frags; static struct inet_frags nf_frags;
static struct nft_ct_frag6_pernet *nf_frag_pernet(struct net *net)
{
return net_generic(net, nf_frag_pernet_id);
}
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
static struct ctl_table nf_ct_frag6_sysctl_table[] = { static struct ctl_table nf_ct_frag6_sysctl_table[] = {
@ -75,6 +67,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
static int nf_ct_frag6_sysctl_register(struct net *net) static int nf_ct_frag6_sysctl_register(struct net *net)
{ {
struct nft_ct_frag6_pernet *nf_frag;
struct ctl_table *table; struct ctl_table *table;
struct ctl_table_header *hdr; struct ctl_table_header *hdr;
@ -86,18 +79,20 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
goto err_alloc; goto err_alloc;
} }
table[0].data = &net->nf_frag.fqdir->timeout; nf_frag = nf_frag_pernet(net);
table[1].data = &net->nf_frag.fqdir->low_thresh;
table[1].extra2 = &net->nf_frag.fqdir->high_thresh; table[0].data = &nf_frag->fqdir->timeout;
table[2].data = &net->nf_frag.fqdir->high_thresh; table[1].data = &nf_frag->fqdir->low_thresh;
table[2].extra1 = &net->nf_frag.fqdir->low_thresh; table[1].extra2 = &nf_frag->fqdir->high_thresh;
table[2].extra2 = &init_net.nf_frag.fqdir->high_thresh; table[2].data = &nf_frag->fqdir->high_thresh;
table[2].extra1 = &nf_frag->fqdir->low_thresh;
table[2].extra2 = &nf_frag->fqdir->high_thresh;
hdr = register_net_sysctl(net, "net/netfilter", table); hdr = register_net_sysctl(net, "net/netfilter", table);
if (hdr == NULL) if (hdr == NULL)
goto err_reg; goto err_reg;
net->nf_frag_frags_hdr = hdr; nf_frag->nf_frag_frags_hdr = hdr;
return 0; return 0;
err_reg: err_reg:
@ -109,10 +104,11 @@ err_alloc:
static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
{ {
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
struct ctl_table *table; struct ctl_table *table;
table = net->nf_frag_frags_hdr->ctl_table_arg; table = nf_frag->nf_frag_frags_hdr->ctl_table_arg;
unregister_net_sysctl_table(net->nf_frag_frags_hdr); unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr);
if (!net_eq(net, &init_net)) if (!net_eq(net, &init_net))
kfree(table); kfree(table);
} }
@ -149,6 +145,7 @@ static void nf_ct_frag6_expire(struct timer_list *t)
static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user, static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
const struct ipv6hdr *hdr, int iif) const struct ipv6hdr *hdr, int iif)
{ {
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
struct frag_v6_compare_key key = { struct frag_v6_compare_key key = {
.id = id, .id = id,
.saddr = hdr->saddr, .saddr = hdr->saddr,
@ -158,7 +155,7 @@ static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
}; };
struct inet_frag_queue *q; struct inet_frag_queue *q;
q = inet_frag_find(net->nf_frag.fqdir, &key); q = inet_frag_find(nf_frag->fqdir, &key);
if (!q) if (!q)
return NULL; return NULL;
@ -495,37 +492,44 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_gather);
static int nf_ct_net_init(struct net *net) static int nf_ct_net_init(struct net *net)
{ {
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
int res; int res;
res = fqdir_init(&net->nf_frag.fqdir, &nf_frags, net); res = fqdir_init(&nf_frag->fqdir, &nf_frags, net);
if (res < 0) if (res < 0)
return res; return res;
net->nf_frag.fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH; nf_frag->fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
net->nf_frag.fqdir->low_thresh = IPV6_FRAG_LOW_THRESH; nf_frag->fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
net->nf_frag.fqdir->timeout = IPV6_FRAG_TIMEOUT; nf_frag->fqdir->timeout = IPV6_FRAG_TIMEOUT;
res = nf_ct_frag6_sysctl_register(net); res = nf_ct_frag6_sysctl_register(net);
if (res < 0) if (res < 0)
fqdir_exit(net->nf_frag.fqdir); fqdir_exit(nf_frag->fqdir);
return res; return res;
} }
static void nf_ct_net_pre_exit(struct net *net) static void nf_ct_net_pre_exit(struct net *net)
{ {
fqdir_pre_exit(net->nf_frag.fqdir); struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
fqdir_pre_exit(nf_frag->fqdir);
} }
static void nf_ct_net_exit(struct net *net) static void nf_ct_net_exit(struct net *net)
{ {
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
nf_ct_frags6_sysctl_unregister(net); nf_ct_frags6_sysctl_unregister(net);
fqdir_exit(net->nf_frag.fqdir); fqdir_exit(nf_frag->fqdir);
} }
static struct pernet_operations nf_ct_net_ops = { static struct pernet_operations nf_ct_net_ops = {
.init = nf_ct_net_init, .init = nf_ct_net_init,
.pre_exit = nf_ct_net_pre_exit, .pre_exit = nf_ct_net_pre_exit,
.exit = nf_ct_net_exit, .exit = nf_ct_net_exit,
.id = &nf_frag_pernet_id,
.size = sizeof(struct nft_ct_frag6_pernet),
}; };
static const struct rhashtable_params nfct_rhash_params = { static const struct rhashtable_params nfct_rhash_params = {

View File

@ -25,6 +25,8 @@
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_defrag_ipv6.h> #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
extern unsigned int nf_frag_pernet_id;
static DEFINE_MUTEX(defrag6_mutex); static DEFINE_MUTEX(defrag6_mutex);
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
@ -89,10 +91,12 @@ static const struct nf_hook_ops ipv6_defrag_ops[] = {
static void __net_exit defrag6_net_exit(struct net *net) static void __net_exit defrag6_net_exit(struct net *net)
{ {
if (net->nf.defrag_ipv6) { struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
if (nf_frag->users) {
nf_unregister_net_hooks(net, ipv6_defrag_ops, nf_unregister_net_hooks(net, ipv6_defrag_ops,
ARRAY_SIZE(ipv6_defrag_ops)); ARRAY_SIZE(ipv6_defrag_ops));
net->nf.defrag_ipv6 = false; nf_frag->users = 0;
} }
} }
@ -130,21 +134,22 @@ static void __exit nf_defrag_fini(void)
int nf_defrag_ipv6_enable(struct net *net) int nf_defrag_ipv6_enable(struct net *net)
{ {
struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
int err = 0; int err = 0;
might_sleep(); might_sleep();
if (net->nf.defrag_ipv6) if (nf_frag->users)
return 0; return 0;
mutex_lock(&defrag6_mutex); mutex_lock(&defrag6_mutex);
if (net->nf.defrag_ipv6) if (nf_frag->users)
goto out_unlock; goto out_unlock;
err = nf_register_net_hooks(net, ipv6_defrag_ops, err = nf_register_net_hooks(net, ipv6_defrag_ops,
ARRAY_SIZE(ipv6_defrag_ops)); ARRAY_SIZE(ipv6_defrag_ops));
if (err == 0) if (err == 0)
net->nf.defrag_ipv6 = true; nf_frag->users = 1;
out_unlock: out_unlock:
mutex_unlock(&defrag6_mutex); mutex_unlock(&defrag6_mutex);