aboutsummaryrefslogtreecommitdiff
path: root/net/netfilter/nf_conntrack_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/nf_conntrack_core.c')
-rw-r--r--net/netfilter/nf_conntrack_core.c191
1 files changed, 111 insertions, 80 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e4a0c4fb3a7..c8e001a9c45 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -45,6 +45,7 @@
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_conntrack_timestamp.h>
#include <net/netfilter/nf_conntrack_timeout.h>
+#include <net/netfilter/nf_conntrack_labels.h>
#include <net/netfilter/nf_nat.h>
#include <net/netfilter/nf_nat_core.h>
@@ -763,6 +764,7 @@ void nf_conntrack_free(struct nf_conn *ct)
}
EXPORT_SYMBOL_GPL(nf_conntrack_free);
+
/* Allocate a new conntrack: we return -ENOMEM if classification
failed due to stress. Otherwise it really is unclassifiable. */
static struct nf_conntrack_tuple_hash *
@@ -809,6 +811,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
+ nf_ct_labels_ext_add(ct);
ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
@@ -1331,18 +1334,42 @@ static int untrack_refs(void)
return cnt;
}
-static void nf_conntrack_cleanup_init_net(void)
+void nf_conntrack_cleanup_start(void)
+{
+ RCU_INIT_POINTER(ip_ct_attach, NULL);
+}
+
+void nf_conntrack_cleanup_end(void)
{
+ RCU_INIT_POINTER(nf_ct_destroy, NULL);
while (untrack_refs() > 0)
schedule();
#ifdef CONFIG_NF_CONNTRACK_ZONES
nf_ct_extend_unregister(&nf_ct_zone_extend);
#endif
+ nf_conntrack_proto_fini();
+ nf_conntrack_labels_fini();
+ nf_conntrack_helper_fini();
+ nf_conntrack_timeout_fini();
+ nf_conntrack_ecache_fini();
+ nf_conntrack_tstamp_fini();
+ nf_conntrack_acct_fini();
+ nf_conntrack_expect_fini();
}
-static void nf_conntrack_cleanup_net(struct net *net)
+/*
+ * Mishearing the voices in his head, our hero wonders how he's
+ * supposed to kill the mall.
+ */
+void nf_conntrack_cleanup_net(struct net *net)
{
+ /*
+ * This makes sure all current packets have passed through
+ * netfilter framework. Roll on, two-stage module
+ * delete...
+ */
+ synchronize_net();
i_see_dead_people:
nf_ct_iterate_cleanup(net, kill_all, NULL);
nf_ct_release_dying_list(net);
@@ -1352,38 +1379,17 @@ static void nf_conntrack_cleanup_net(struct net *net)
}
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
- nf_conntrack_helper_fini(net);
- nf_conntrack_timeout_fini(net);
- nf_conntrack_ecache_fini(net);
- nf_conntrack_tstamp_fini(net);
- nf_conntrack_acct_fini(net);
- nf_conntrack_expect_fini(net);
+ nf_conntrack_proto_pernet_fini(net);
+ nf_conntrack_helper_pernet_fini(net);
+ nf_conntrack_ecache_pernet_fini(net);
+ nf_conntrack_tstamp_pernet_fini(net);
+ nf_conntrack_acct_pernet_fini(net);
+ nf_conntrack_expect_pernet_fini(net);
kmem_cache_destroy(net->ct.nf_conntrack_cachep);
kfree(net->ct.slabname);
free_percpu(net->ct.stat);
}
-/* Mishearing the voices in his head, our hero wonders how he's
- supposed to kill the mall. */
-void nf_conntrack_cleanup(struct net *net)
-{
- if (net_eq(net, &init_net))
- RCU_INIT_POINTER(ip_ct_attach, NULL);
-
- /* This makes sure all current packets have passed through
- netfilter framework. Roll on, two-stage module
- delete... */
- synchronize_net();
- nf_conntrack_proto_fini(net);
- nf_conntrack_cleanup_net(net);
-}
-
-void nf_conntrack_cleanup_end(void)
-{
- RCU_INIT_POINTER(nf_ct_destroy, NULL);
- nf_conntrack_cleanup_init_net();
-}
-
void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
{
struct hlist_nulls_head *hash;
@@ -1474,7 +1480,7 @@ void nf_ct_untracked_status_or(unsigned long bits)
}
EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or);
-static int nf_conntrack_init_init_net(void)
+int nf_conntrack_init_start(void)
{
int max_factor = 8;
int ret, cpu;
@@ -1501,11 +1507,44 @@ static int nf_conntrack_init_init_net(void)
printk(KERN_INFO "nf_conntrack version %s (%u buckets, %d max)\n",
NF_CONNTRACK_VERSION, nf_conntrack_htable_size,
nf_conntrack_max);
+
+ ret = nf_conntrack_expect_init();
+ if (ret < 0)
+ goto err_expect;
+
+ ret = nf_conntrack_acct_init();
+ if (ret < 0)
+ goto err_acct;
+
+ ret = nf_conntrack_tstamp_init();
+ if (ret < 0)
+ goto err_tstamp;
+
+ ret = nf_conntrack_ecache_init();
+ if (ret < 0)
+ goto err_ecache;
+
+ ret = nf_conntrack_timeout_init();
+ if (ret < 0)
+ goto err_timeout;
+
+ ret = nf_conntrack_helper_init();
+ if (ret < 0)
+ goto err_helper;
+
+ ret = nf_conntrack_labels_init();
+ if (ret < 0)
+ goto err_labels;
+
#ifdef CONFIG_NF_CONNTRACK_ZONES
ret = nf_ct_extend_register(&nf_ct_zone_extend);
if (ret < 0)
goto err_extend;
#endif
+ ret = nf_conntrack_proto_init();
+ if (ret < 0)
+ goto err_proto;
+
/* Set up fake conntrack: to never be deleted, not in any hashes */
for_each_possible_cpu(cpu) {
struct nf_conn *ct = &per_cpu(nf_conntrack_untracked, cpu);
@@ -1516,12 +1555,38 @@ static int nf_conntrack_init_init_net(void)
nf_ct_untracked_status_or(IPS_CONFIRMED | IPS_UNTRACKED);
return 0;
+err_proto:
#ifdef CONFIG_NF_CONNTRACK_ZONES
+ nf_ct_extend_unregister(&nf_ct_zone_extend);
err_extend:
#endif
+ nf_conntrack_labels_fini();
+err_labels:
+ nf_conntrack_helper_fini();
+err_helper:
+ nf_conntrack_timeout_fini();
+err_timeout:
+ nf_conntrack_ecache_fini();
+err_ecache:
+ nf_conntrack_tstamp_fini();
+err_tstamp:
+ nf_conntrack_acct_fini();
+err_acct:
+ nf_conntrack_expect_fini();
+err_expect:
return ret;
}
+void nf_conntrack_init_end(void)
+{
+ /* For use by REJECT target */
+ RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
+ RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
+
+ /* Howto get NAT offsets */
+ RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
+}
+
/*
* We need to use special "null" values, not used in hash table
*/
@@ -1529,7 +1594,7 @@ err_extend:
#define DYING_NULLS_VAL ((1<<30)+1)
#define TEMPLATE_NULLS_VAL ((1<<30)+2)
-static int nf_conntrack_init_net(struct net *net)
+int nf_conntrack_init_net(struct net *net)
{
int ret;
@@ -1565,35 +1630,36 @@ static int nf_conntrack_init_net(struct net *net)
printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
goto err_hash;
}
- ret = nf_conntrack_expect_init(net);
+ ret = nf_conntrack_expect_pernet_init(net);
if (ret < 0)
goto err_expect;
- ret = nf_conntrack_acct_init(net);
+ ret = nf_conntrack_acct_pernet_init(net);
if (ret < 0)
goto err_acct;
- ret = nf_conntrack_tstamp_init(net);
+ ret = nf_conntrack_tstamp_pernet_init(net);
if (ret < 0)
goto err_tstamp;
- ret = nf_conntrack_ecache_init(net);
+ ret = nf_conntrack_ecache_pernet_init(net);
if (ret < 0)
goto err_ecache;
- ret = nf_conntrack_timeout_init(net);
- if (ret < 0)
- goto err_timeout;
- ret = nf_conntrack_helper_init(net);
+ ret = nf_conntrack_helper_pernet_init(net);
if (ret < 0)
goto err_helper;
+ ret = nf_conntrack_proto_pernet_init(net);
+ if (ret < 0)
+ goto err_proto;
return 0;
+
+err_proto:
+ nf_conntrack_helper_pernet_fini(net);
err_helper:
- nf_conntrack_timeout_fini(net);
-err_timeout:
- nf_conntrack_ecache_fini(net);
+ nf_conntrack_ecache_pernet_fini(net);
err_ecache:
- nf_conntrack_tstamp_fini(net);
+ nf_conntrack_tstamp_pernet_fini(net);
err_tstamp:
- nf_conntrack_acct_fini(net);
+ nf_conntrack_acct_pernet_fini(net);
err_acct:
- nf_conntrack_expect_fini(net);
+ nf_conntrack_expect_pernet_fini(net);
err_expect:
nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
err_hash:
@@ -1610,38 +1676,3 @@ s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
enum ip_conntrack_dir dir,
u32 seq);
EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
-
-int nf_conntrack_init(struct net *net)
-{
- int ret;
-
- if (net_eq(net, &init_net)) {
- ret = nf_conntrack_init_init_net();
- if (ret < 0)
- goto out_init_net;
- }
- ret = nf_conntrack_proto_init(net);
- if (ret < 0)
- goto out_proto;
- ret = nf_conntrack_init_net(net);
- if (ret < 0)
- goto out_net;
-
- if (net_eq(net, &init_net)) {
- /* For use by REJECT target */
- RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
- RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
-
- /* Howto get NAT offsets */
- RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
- }
- return 0;
-
-out_net:
- nf_conntrack_proto_fini(net);
-out_proto:
- if (net_eq(net, &init_net))
- nf_conntrack_cleanup_init_net();
-out_init_net:
- return ret;
-}