|
@@ -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;
|
|
|
-}
|