aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/netfilter/nf_defrag_ipv6_hooks.c')
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 6646a87fb5dc..cb4eb1d2c620 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -89,10 +89,10 @@ static const struct nf_hook_ops ipv6_defrag_ops[] = {
static void __net_exit defrag6_net_exit(struct net *net)
{
- if (net->nf.defrag_ipv6) {
+ if (net->nf.defrag_ipv6_users) {
nf_unregister_net_hooks(net, ipv6_defrag_ops,
ARRAY_SIZE(ipv6_defrag_ops));
- net->nf.defrag_ipv6 = false;
+ net->nf.defrag_ipv6_users = 0;
}
}
@@ -132,19 +132,21 @@ int nf_defrag_ipv6_enable(struct net *net)
{
int err = 0;
- might_sleep();
-
- if (net->nf.defrag_ipv6)
- return 0;
-
mutex_lock(&defrag6_mutex);
- if (net->nf.defrag_ipv6)
+ if (net->nf.defrag_ipv6_users == UINT_MAX) {
+ err = -EOVERFLOW;
+ goto out_unlock;
+ }
+
+ if (net->nf.defrag_ipv6_users) {
+ net->nf.defrag_ipv6_users++;
goto out_unlock;
+ }
err = nf_register_net_hooks(net, ipv6_defrag_ops,
ARRAY_SIZE(ipv6_defrag_ops));
if (err == 0)
- net->nf.defrag_ipv6 = true;
+ net->nf.defrag_ipv6_users = 1;
out_unlock:
mutex_unlock(&defrag6_mutex);
@@ -152,6 +154,19 @@ int nf_defrag_ipv6_enable(struct net *net)
}
EXPORT_SYMBOL_GPL(nf_defrag_ipv6_enable);
+void nf_defrag_ipv6_disable(struct net *net)
+{
+ mutex_lock(&defrag6_mutex);
+ if (net->nf.defrag_ipv6_users) {
+ net->nf.defrag_ipv6_users--;
+ if (net->nf.defrag_ipv6_users == 0)
+ nf_unregister_net_hooks(net, ipv6_defrag_ops,
+ ARRAY_SIZE(ipv6_defrag_ops));
+ }
+ mutex_unlock(&defrag6_mutex);
+}
+EXPORT_SYMBOL_GPL(nf_defrag_ipv6_disable);
+
module_init(nf_defrag_init);
module_exit(nf_defrag_fini);