aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h5
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h2
-rw-r--r--net/netfilter/nf_conntrack_core.c18
-rw-r--r--net/netfilter/nf_conntrack_expect.c40
-rw-r--r--net/netfilter/nf_conntrack_helper.c13
-rw-r--r--net/netfilter/nf_conntrack_netlink.c4
7 files changed, 45 insertions, 39 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 8f2cbb965f3d..d4f02eb0c66c 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -82,6 +82,8 @@ struct nf_conn_help {
82 82
83 union nf_conntrack_help help; 83 union nf_conntrack_help help;
84 84
85 struct hlist_head expectations;
86
85 /* Current number of expected connections */ 87 /* Current number of expected connections */
86 unsigned int expecting; 88 unsigned int expecting;
87}; 89};
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 424d4bdb9848..9d5af4e22c4f 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -6,14 +6,13 @@
6#define _NF_CONNTRACK_EXPECT_H 6#define _NF_CONNTRACK_EXPECT_H
7#include <net/netfilter/nf_conntrack.h> 7#include <net/netfilter/nf_conntrack.h>
8 8
9extern struct list_head nf_ct_expect_list;
10extern struct hlist_head *nf_ct_expect_hash; 9extern struct hlist_head *nf_ct_expect_hash;
11extern unsigned int nf_ct_expect_hsize; 10extern unsigned int nf_ct_expect_hsize;
12 11
13struct nf_conntrack_expect 12struct nf_conntrack_expect
14{ 13{
15 /* Internal linked list (global expectation list) */ 14 /* Conntrack expectation list member */
16 struct list_head list; 15 struct hlist_node lnode;
17 16
18 /* Hash member */ 17 /* Hash member */
19 struct hlist_node hnode; 18 struct hlist_node hnode;
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index d62e6f093af4..2c0e2e0fb7ff 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -52,6 +52,8 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
52extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); 52extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
53extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); 53extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
54 54
55extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
56
55static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) 57static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
56{ 58{
57 return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); 59 return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index ed44a09ae739..d1fc019760a1 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -502,12 +502,9 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
502 __set_bit(IPS_EXPECTED_BIT, &conntrack->status); 502 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
503 conntrack->master = exp->master; 503 conntrack->master = exp->master;
504 if (exp->helper) { 504 if (exp->helper) {
505 help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, 505 help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
506 GFP_ATOMIC);
507 if (help) 506 if (help)
508 rcu_assign_pointer(help->helper, exp->helper); 507 rcu_assign_pointer(help->helper, exp->helper);
509 else
510 DEBUGP("failed to add helper extension area");
511 } 508 }
512 509
513#ifdef CONFIG_NF_CONNTRACK_MARK 510#ifdef CONFIG_NF_CONNTRACK_MARK
@@ -523,14 +520,9 @@ init_conntrack(const struct nf_conntrack_tuple *tuple,
523 520
524 helper = __nf_ct_helper_find(&repl_tuple); 521 helper = __nf_ct_helper_find(&repl_tuple);
525 if (helper) { 522 if (helper) {
526 help = nf_ct_ext_add(conntrack, NF_CT_EXT_HELPER, 523 help = nf_ct_helper_ext_add(conntrack, GFP_ATOMIC);
527 GFP_ATOMIC);
528 if (help) 524 if (help)
529 /* not in hash table yet, so not strictly
530 necessary */
531 rcu_assign_pointer(help->helper, helper); 525 rcu_assign_pointer(help->helper, helper);
532 else
533 DEBUGP("failed to add helper extension area");
534 } 526 }
535 NF_CT_STAT_INC(new); 527 NF_CT_STAT_INC(new);
536 } 528 }
@@ -721,11 +713,9 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
721 } 713 }
722 714
723 if (help == NULL) { 715 if (help == NULL) {
724 help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_ATOMIC); 716 help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
725 if (help == NULL) { 717 if (help == NULL)
726 DEBUGP("failed to add helper extension area");
727 goto out; 718 goto out;
728 }
729 } else { 719 } else {
730 memset(&help->help, 0, sizeof(help->help)); 720 memset(&help->help, 0, sizeof(help->help));
731 } 721 }
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index c5006b0a4e65..5ef0dd439e76 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -27,9 +27,6 @@
27#include <net/netfilter/nf_conntrack_helper.h> 27#include <net/netfilter/nf_conntrack_helper.h>
28#include <net/netfilter/nf_conntrack_tuple.h> 28#include <net/netfilter/nf_conntrack_tuple.h>
29 29
30LIST_HEAD(nf_ct_expect_list);
31EXPORT_SYMBOL_GPL(nf_ct_expect_list);
32
33struct hlist_head *nf_ct_expect_hash __read_mostly; 30struct hlist_head *nf_ct_expect_hash __read_mostly;
34EXPORT_SYMBOL_GPL(nf_ct_expect_hash); 31EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
35 32
@@ -52,13 +49,14 @@ void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
52 NF_CT_ASSERT(master_help); 49 NF_CT_ASSERT(master_help);
53 NF_CT_ASSERT(!timer_pending(&exp->timeout)); 50 NF_CT_ASSERT(!timer_pending(&exp->timeout));
54 51
55 list_del(&exp->list);
56 hlist_del(&exp->hnode); 52 hlist_del(&exp->hnode);
57 nf_ct_expect_count--; 53 nf_ct_expect_count--;
58 54
59 NF_CT_STAT_INC(expect_delete); 55 hlist_del(&exp->lnode);
60 master_help->expecting--; 56 master_help->expecting--;
61 nf_ct_expect_put(exp); 57 nf_ct_expect_put(exp);
58
59 NF_CT_STAT_INC(expect_delete);
62} 60}
63EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); 61EXPORT_SYMBOL_GPL(nf_ct_unlink_expect);
64 62
@@ -153,17 +151,18 @@ nf_ct_find_expectation(const struct nf_conntrack_tuple *tuple)
153/* delete all expectations for this conntrack */ 151/* delete all expectations for this conntrack */
154void nf_ct_remove_expectations(struct nf_conn *ct) 152void nf_ct_remove_expectations(struct nf_conn *ct)
155{ 153{
156 struct nf_conntrack_expect *i, *tmp;
157 struct nf_conn_help *help = nfct_help(ct); 154 struct nf_conn_help *help = nfct_help(ct);
155 struct nf_conntrack_expect *exp;
156 struct hlist_node *n, *next;
158 157
159 /* Optimization: most connection never expect any others. */ 158 /* Optimization: most connection never expect any others. */
160 if (!help || help->expecting == 0) 159 if (!help || help->expecting == 0)
161 return; 160 return;
162 161
163 list_for_each_entry_safe(i, tmp, &nf_ct_expect_list, list) { 162 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
164 if (i->master == ct && del_timer(&i->timeout)) { 163 if (del_timer(&exp->timeout)) {
165 nf_ct_unlink_expect(i); 164 nf_ct_unlink_expect(exp);
166 nf_ct_expect_put(i); 165 nf_ct_expect_put(exp);
167 } 166 }
168 } 167 }
169} 168}
@@ -289,9 +288,10 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
289 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); 288 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
290 289
291 atomic_inc(&exp->use); 290 atomic_inc(&exp->use);
291
292 hlist_add_head(&exp->lnode, &master_help->expectations);
292 master_help->expecting++; 293 master_help->expecting++;
293 294
294 list_add(&exp->list, &nf_ct_expect_list);
295 hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]); 295 hlist_add_head(&exp->hnode, &nf_ct_expect_hash[h]);
296 nf_ct_expect_count++; 296 nf_ct_expect_count++;
297 297
@@ -308,16 +308,16 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
308/* Race with expectations being used means we could have none to find; OK. */ 308/* Race with expectations being used means we could have none to find; OK. */
309static void evict_oldest_expect(struct nf_conn *master) 309static void evict_oldest_expect(struct nf_conn *master)
310{ 310{
311 struct nf_conntrack_expect *i; 311 struct nf_conn_help *master_help = nfct_help(master);
312 struct nf_conntrack_expect *exp = NULL;
313 struct hlist_node *n;
312 314
313 list_for_each_entry_reverse(i, &nf_ct_expect_list, list) { 315 hlist_for_each_entry(exp, n, &master_help->expectations, lnode)
314 if (i->master == master) { 316 ; /* nothing */
315 if (del_timer(&i->timeout)) { 317
316 nf_ct_unlink_expect(i); 318 if (exp && del_timer(&exp->timeout)) {
317 nf_ct_expect_put(i); 319 nf_ct_unlink_expect(exp);
318 } 320 nf_ct_expect_put(exp);
319 break;
320 }
321 } 321 }
322} 322}
323 323
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index cc8ae7404ac4..66c209d7e09d 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -87,6 +87,19 @@ __nf_conntrack_helper_find_byname(const char *name)
87} 87}
88EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); 88EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname);
89 89
90struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
91{
92 struct nf_conn_help *help;
93
94 help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, gfp);
95 if (help)
96 INIT_HLIST_HEAD(&help->expectations);
97 else
98 pr_debug("failed to add helper extension area");
99 return help;
100}
101EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
102
90static inline int unhelp(struct nf_conntrack_tuple_hash *i, 103static inline int unhelp(struct nf_conntrack_tuple_hash *i,
91 const struct nf_conntrack_helper *me) 104 const struct nf_conntrack_helper *me)
92{ 105{
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 60af9b6b9e00..6f89b105a205 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -868,7 +868,7 @@ ctnetlink_change_helper(struct nf_conn *ct, struct nfattr *cda[])
868 /* need to zero data of old helper */ 868 /* need to zero data of old helper */
869 memset(&help->help, 0, sizeof(help->help)); 869 memset(&help->help, 0, sizeof(help->help));
870 } else { 870 } else {
871 help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); 871 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
872 if (help == NULL) 872 if (help == NULL)
873 return -ENOMEM; 873 return -ENOMEM;
874 } 874 }
@@ -989,7 +989,7 @@ ctnetlink_create_conntrack(struct nfattr *cda[],
989 989
990 helper = nf_ct_helper_find_get(rtuple); 990 helper = nf_ct_helper_find_get(rtuple);
991 if (helper) { 991 if (helper) {
992 help = nf_ct_ext_add(ct, NF_CT_EXT_HELPER, GFP_KERNEL); 992 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
993 if (help == NULL) { 993 if (help == NULL) {
994 nf_ct_helper_put(helper); 994 nf_ct_helper_put(helper);
995 err = -ENOMEM; 995 err = -ENOMEM;