|
@@ -28,17 +28,12 @@
|
|
#include <net/netfilter/nf_conntrack_helper.h>
|
|
#include <net/netfilter/nf_conntrack_helper.h>
|
|
#include <net/netfilter/nf_conntrack_tuple.h>
|
|
#include <net/netfilter/nf_conntrack_tuple.h>
|
|
|
|
|
|
-struct hlist_head *nf_ct_expect_hash __read_mostly;
|
|
|
|
-EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
|
|
|
|
-
|
|
|
|
unsigned int nf_ct_expect_hsize __read_mostly;
|
|
unsigned int nf_ct_expect_hsize __read_mostly;
|
|
EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
|
|
EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
|
|
|
|
|
|
static unsigned int nf_ct_expect_hash_rnd __read_mostly;
|
|
static unsigned int nf_ct_expect_hash_rnd __read_mostly;
|
|
-static unsigned int nf_ct_expect_count;
|
|
|
|
unsigned int nf_ct_expect_max __read_mostly;
|
|
unsigned int nf_ct_expect_max __read_mostly;
|
|
static int nf_ct_expect_hash_rnd_initted __read_mostly;
|
|
static int nf_ct_expect_hash_rnd_initted __read_mostly;
|
|
-static int nf_ct_expect_vmalloc;
|
|
|
|
|
|
|
|
static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
|
|
static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
|
|
|
|
|
|
@@ -46,12 +41,13 @@ static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
|
|
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
|
|
void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
|
|
{
|
|
{
|
|
struct nf_conn_help *master_help = nfct_help(exp->master);
|
|
struct nf_conn_help *master_help = nfct_help(exp->master);
|
|
|
|
+ struct net *net = nf_ct_exp_net(exp);
|
|
|
|
|
|
NF_CT_ASSERT(master_help);
|
|
NF_CT_ASSERT(master_help);
|
|
NF_CT_ASSERT(!timer_pending(&exp->timeout));
|
|
NF_CT_ASSERT(!timer_pending(&exp->timeout));
|
|
|
|
|
|
hlist_del_rcu(&exp->hnode);
|
|
hlist_del_rcu(&exp->hnode);
|
|
- nf_ct_expect_count--;
|
|
|
|
|
|
+ net->ct.expect_count--;
|
|
|
|
|
|
hlist_del(&exp->lnode);
|
|
hlist_del(&exp->lnode);
|
|
master_help->expecting[exp->class]--;
|
|
master_help->expecting[exp->class]--;
|
|
@@ -87,17 +83,17 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple
|
|
}
|
|
}
|
|
|
|
|
|
struct nf_conntrack_expect *
|
|
struct nf_conntrack_expect *
|
|
-__nf_ct_expect_find(const struct nf_conntrack_tuple *tuple)
|
|
|
|
|
|
+__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
|
|
{
|
|
{
|
|
struct nf_conntrack_expect *i;
|
|
struct nf_conntrack_expect *i;
|
|
struct hlist_node *n;
|
|
struct hlist_node *n;
|
|
unsigned int h;
|
|
unsigned int h;
|
|
|
|
|
|
- if (!nf_ct_expect_count)
|
|
|
|
|
|
+ if (!net->ct.expect_count)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
h = nf_ct_expect_dst_hash(tuple);
|
|
h = nf_ct_expect_dst_hash(tuple);
|
|
- hlist_for_each_entry_rcu(i, n, &nf_ct_expect_hash[h], hnode) {
|
|
|
|
|
|
+ hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) {
|
|
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
|
|
if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask))
|
|
return i;
|
|
return i;
|
|
}
|
|
}
|
|
@@ -107,12 +103,12 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
|
|
|
|
|
|
/* Just find a expectation corresponding to a tuple. */
|
|
/* Just find a expectation corresponding to a tuple. */
|
|
struct nf_conntrack_expect *
|
|
struct nf_conntrack_expect *
|
|
-nf_ct_expect_find_get(const struct nf_conntrack_tuple *tuple)
|
|
|
|
|
|
+nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple)
|
|
{
|
|
{
|
|
struct nf_conntrack_expect *i;
|
|
struct nf_conntrack_expect *i;
|
|
|
|
|
|
rcu_read_lock();
|
|
rcu_read_lock();
|
|
- i = __nf_ct_expect_find(tuple);
|
|
|
|
|
|
+ i = __nf_ct_expect_find(net, tuple);
|
|
if (i && !atomic_inc_not_zero(&i->use))
|
|
if (i && !atomic_inc_not_zero(&i->use))
|
|
i = NULL;
|
|
i = NULL;
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
@@ -124,17 +120,17 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
|
|
/* If an expectation for this connection is found, it gets delete from
|
|
/* If an expectation for this connection is found, it gets delete from
|
|
* global list then returned. */
|
|
* global list then returned. */
|
|
struct nf_conntrack_expect *
|
|
struct nf_conntrack_expect *
|
|
-nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
|
|
|
|
|
|
+nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
|
|
{
|
|
{
|
|
struct nf_conntrack_expect *i, *exp = NULL;
|
|
struct nf_conntrack_expect *i, *exp = NULL;
|
|
struct hlist_node *n;
|
|
struct hlist_node *n;
|
|
unsigned int h;
|
|
unsigned int h;
|
|
|
|
|
|
- if (!nf_ct_expect_count)
|
|
|
|
|
|
+ if (!net->ct.expect_count)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
h = nf_ct_expect_dst_hash(tuple);
|
|
h = nf_ct_expect_dst_hash(tuple);
|
|
- hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
|
|
|
|
|
|
+ hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
|
|
if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
|
|
if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
|
|
nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
|
|
nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) {
|
|
exp = i;
|
|
exp = i;
|
|
@@ -311,6 +307,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_put);
|
|
static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
|
|
static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
|
|
{
|
|
{
|
|
struct nf_conn_help *master_help = nfct_help(exp->master);
|
|
struct nf_conn_help *master_help = nfct_help(exp->master);
|
|
|
|
+ struct net *net = nf_ct_exp_net(exp);
|
|
const struct nf_conntrack_expect_policy *p;
|
|
const struct nf_conntrack_expect_policy *p;
|
|
unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
|
|
unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
|
|
|
|
|
|
@@ -319,8 +316,8 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
|
|
hlist_add_head(&exp->lnode, &master_help->expectations);
|
|
hlist_add_head(&exp->lnode, &master_help->expectations);
|
|
master_help->expecting[exp->class]++;
|
|
master_help->expecting[exp->class]++;
|
|
|
|
|
|
- hlist_add_head_rcu(&exp->hnode, &nf_ct_expect_hash[h]);
|
|
|
|
- nf_ct_expect_count++;
|
|
|
|
|
|
+ hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]);
|
|
|
|
+ net->ct.expect_count++;
|
|
|
|
|
|
setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
|
|
setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
|
|
(unsigned long)exp);
|
|
(unsigned long)exp);
|
|
@@ -371,6 +368,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
|
|
struct nf_conntrack_expect *i;
|
|
struct nf_conntrack_expect *i;
|
|
struct nf_conn *master = expect->master;
|
|
struct nf_conn *master = expect->master;
|
|
struct nf_conn_help *master_help = nfct_help(master);
|
|
struct nf_conn_help *master_help = nfct_help(master);
|
|
|
|
+ struct net *net = nf_ct_exp_net(expect);
|
|
struct hlist_node *n;
|
|
struct hlist_node *n;
|
|
unsigned int h;
|
|
unsigned int h;
|
|
int ret;
|
|
int ret;
|
|
@@ -383,7 +381,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
h = nf_ct_expect_dst_hash(&expect->tuple);
|
|
h = nf_ct_expect_dst_hash(&expect->tuple);
|
|
- hlist_for_each_entry(i, n, &nf_ct_expect_hash[h], hnode) {
|
|
|
|
|
|
+ hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
|
|
if (expect_matches(i, expect)) {
|
|
if (expect_matches(i, expect)) {
|
|
/* Refresh timer: if it's dying, ignore.. */
|
|
/* Refresh timer: if it's dying, ignore.. */
|
|
if (refresh_timer(i)) {
|
|
if (refresh_timer(i)) {
|
|
@@ -406,7 +404,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (nf_ct_expect_count >= nf_ct_expect_max) {
|
|
|
|
|
|
+ if (net->ct.expect_count >= nf_ct_expect_max) {
|
|
if (net_ratelimit())
|
|
if (net_ratelimit())
|
|
printk(KERN_WARNING
|
|
printk(KERN_WARNING
|
|
"nf_conntrack: expectation table full\n");
|
|
"nf_conntrack: expectation table full\n");
|
|
@@ -430,11 +428,12 @@ struct ct_expect_iter_state {
|
|
|
|
|
|
static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
|
|
static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
|
|
{
|
|
{
|
|
|
|
+ struct net *net = &init_net;
|
|
struct ct_expect_iter_state *st = seq->private;
|
|
struct ct_expect_iter_state *st = seq->private;
|
|
struct hlist_node *n;
|
|
struct hlist_node *n;
|
|
|
|
|
|
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
|
|
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
|
|
- n = rcu_dereference(nf_ct_expect_hash[st->bucket].first);
|
|
|
|
|
|
+ n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
|
|
if (n)
|
|
if (n)
|
|
return n;
|
|
return n;
|
|
}
|
|
}
|
|
@@ -444,13 +443,14 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
|
|
static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
|
|
static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
|
|
struct hlist_node *head)
|
|
struct hlist_node *head)
|
|
{
|
|
{
|
|
|
|
+ struct net *net = &init_net;
|
|
struct ct_expect_iter_state *st = seq->private;
|
|
struct ct_expect_iter_state *st = seq->private;
|
|
|
|
|
|
head = rcu_dereference(head->next);
|
|
head = rcu_dereference(head->next);
|
|
while (head == NULL) {
|
|
while (head == NULL) {
|
|
if (++st->bucket >= nf_ct_expect_hsize)
|
|
if (++st->bucket >= nf_ct_expect_hsize)
|
|
return NULL;
|
|
return NULL;
|
|
- head = rcu_dereference(nf_ct_expect_hash[st->bucket].first);
|
|
|
|
|
|
+ head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
|
|
}
|
|
}
|
|
return head;
|
|
return head;
|
|
}
|
|
}
|
|
@@ -558,7 +558,7 @@ static void exp_proc_remove(void)
|
|
|
|
|
|
module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
|
|
module_param_named(expect_hashsize, nf_ct_expect_hsize, uint, 0600);
|
|
|
|
|
|
-int nf_conntrack_expect_init(void)
|
|
|
|
|
|
+int nf_conntrack_expect_init(struct net *net)
|
|
{
|
|
{
|
|
int err = -ENOMEM;
|
|
int err = -ENOMEM;
|
|
|
|
|
|
@@ -569,9 +569,10 @@ int nf_conntrack_expect_init(void)
|
|
}
|
|
}
|
|
nf_ct_expect_max = nf_ct_expect_hsize * 4;
|
|
nf_ct_expect_max = nf_ct_expect_hsize * 4;
|
|
|
|
|
|
- nf_ct_expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
|
|
|
|
- &nf_ct_expect_vmalloc);
|
|
|
|
- if (nf_ct_expect_hash == NULL)
|
|
|
|
|
|
+ net->ct.expect_count = 0;
|
|
|
|
+ net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
|
|
|
|
+ &net->ct.expect_vmalloc);
|
|
|
|
+ if (net->ct.expect_hash == NULL)
|
|
goto err1;
|
|
goto err1;
|
|
|
|
|
|
nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
|
|
nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
|
|
@@ -589,16 +590,16 @@ int nf_conntrack_expect_init(void)
|
|
err3:
|
|
err3:
|
|
kmem_cache_destroy(nf_ct_expect_cachep);
|
|
kmem_cache_destroy(nf_ct_expect_cachep);
|
|
err2:
|
|
err2:
|
|
- nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
|
|
|
|
|
|
+ nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
|
|
nf_ct_expect_hsize);
|
|
nf_ct_expect_hsize);
|
|
err1:
|
|
err1:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
-void nf_conntrack_expect_fini(void)
|
|
|
|
|
|
+void nf_conntrack_expect_fini(struct net *net)
|
|
{
|
|
{
|
|
exp_proc_remove();
|
|
exp_proc_remove();
|
|
kmem_cache_destroy(nf_ct_expect_cachep);
|
|
kmem_cache_destroy(nf_ct_expect_cachep);
|
|
- nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_vmalloc,
|
|
|
|
|
|
+ nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
|
|
nf_ct_expect_hsize);
|
|
nf_ct_expect_hsize);
|
|
}
|
|
}
|