diff options
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_expect.h | 5 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_helper.h | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 18 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 40 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_helper.c | 13 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 4 |
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 | ||
9 | extern struct list_head nf_ct_expect_list; | ||
10 | extern struct hlist_head *nf_ct_expect_hash; | 9 | extern struct hlist_head *nf_ct_expect_hash; |
11 | extern unsigned int nf_ct_expect_hsize; | 10 | extern unsigned int nf_ct_expect_hsize; |
12 | 11 | ||
13 | struct nf_conntrack_expect | 12 | struct 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); | |||
52 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); | 52 | extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); |
53 | extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); | 53 | extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); |
54 | 54 | ||
55 | extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); | ||
56 | |||
55 | static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) | 57 | static 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 | ||
30 | LIST_HEAD(nf_ct_expect_list); | ||
31 | EXPORT_SYMBOL_GPL(nf_ct_expect_list); | ||
32 | |||
33 | struct hlist_head *nf_ct_expect_hash __read_mostly; | 30 | struct hlist_head *nf_ct_expect_hash __read_mostly; |
34 | EXPORT_SYMBOL_GPL(nf_ct_expect_hash); | 31 | EXPORT_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 | } |
63 | EXPORT_SYMBOL_GPL(nf_ct_unlink_expect); | 61 | EXPORT_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 */ |
154 | void nf_ct_remove_expectations(struct nf_conn *ct) | 152 | void 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. */ |
309 | static void evict_oldest_expect(struct nf_conn *master) | 309 | static 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 | } |
88 | EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); | 88 | EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); |
89 | 89 | ||
90 | struct 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 | } | ||
101 | EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); | ||
102 | |||
90 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, | 103 | static 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; |