aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-09-20 14:57:53 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:19:45 -0400
commitdf0933dcb027e156cb5253570ad694b81bd52b69 (patch)
tree48588f78dfda69f737b5ccfff02787ca0dad6036
parent1bf38a36b6a0e810dafae048fdbb999e587f0f2f (diff)
[NETFILTER]: kill listhelp.h
Kill listhelp.h and use the list.h functions instead. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter/x_tables.h4
-rw-r--r--include/linux/netfilter_ipv4/listhelp.h123
-rw-r--r--net/bridge/netfilter/ebtables.c76
-rw-r--r--net/ipv4/netfilter/arp_tables.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c189
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c24
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c1
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c4
-rw-r--r--net/ipv6/netfilter/ip6_tables.c3
-rw-r--r--net/netfilter/nf_conntrack_core.c185
-rw-r--r--net/netfilter/nf_conntrack_standalone.c1
-rw-r--r--net/netfilter/x_tables.c17
15 files changed, 237 insertions, 404 deletions
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 03d1027fb0e8..c832295dbf61 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -138,10 +138,6 @@ struct xt_counters_info
138 138
139#include <linux/netdevice.h> 139#include <linux/netdevice.h>
140 140
141#define ASSERT_READ_LOCK(x)
142#define ASSERT_WRITE_LOCK(x)
143#include <linux/netfilter_ipv4/listhelp.h>
144
145#ifdef CONFIG_COMPAT 141#ifdef CONFIG_COMPAT
146#define COMPAT_TO_USER 1 142#define COMPAT_TO_USER 1
147#define COMPAT_FROM_USER -1 143#define COMPAT_FROM_USER -1
diff --git a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h
deleted file mode 100644
index 5d92cf044d91..000000000000
--- a/include/linux/netfilter_ipv4/listhelp.h
+++ /dev/null
@@ -1,123 +0,0 @@
1#ifndef _LISTHELP_H
2#define _LISTHELP_H
3#include <linux/list.h>
4
5/* Header to do more comprehensive job than linux/list.h; assume list
6 is first entry in structure. */
7
8/* Return pointer to first true entry, if any, or NULL. A macro
9 required to allow inlining of cmpfn. */
10#define LIST_FIND(head, cmpfn, type, args...) \
11({ \
12 const struct list_head *__i, *__j = NULL; \
13 \
14 ASSERT_READ_LOCK(head); \
15 list_for_each(__i, (head)) \
16 if (cmpfn((const type)__i , ## args)) { \
17 __j = __i; \
18 break; \
19 } \
20 (type)__j; \
21})
22
23#define LIST_FIND_W(head, cmpfn, type, args...) \
24({ \
25 const struct list_head *__i, *__j = NULL; \
26 \
27 ASSERT_WRITE_LOCK(head); \
28 list_for_each(__i, (head)) \
29 if (cmpfn((type)__i , ## args)) { \
30 __j = __i; \
31 break; \
32 } \
33 (type)__j; \
34})
35
36/* Just like LIST_FIND but we search backwards */
37#define LIST_FIND_B(head, cmpfn, type, args...) \
38({ \
39 const struct list_head *__i, *__j = NULL; \
40 \
41 ASSERT_READ_LOCK(head); \
42 list_for_each_prev(__i, (head)) \
43 if (cmpfn((const type)__i , ## args)) { \
44 __j = __i; \
45 break; \
46 } \
47 (type)__j; \
48})
49
50static inline int
51__list_cmp_same(const void *p1, const void *p2) { return p1 == p2; }
52
53/* Is this entry in the list? */
54static inline int
55list_inlist(struct list_head *head, const void *entry)
56{
57 return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL;
58}
59
60/* Delete from list. */
61#ifdef CONFIG_NETFILTER_DEBUG
62#define LIST_DELETE(head, oldentry) \
63do { \
64 ASSERT_WRITE_LOCK(head); \
65 if (!list_inlist(head, oldentry)) \
66 printk("LIST_DELETE: %s:%u `%s'(%p) not in %s.\n", \
67 __FILE__, __LINE__, #oldentry, oldentry, #head); \
68 else list_del((struct list_head *)oldentry); \
69} while(0)
70#else
71#define LIST_DELETE(head, oldentry) list_del((struct list_head *)oldentry)
72#endif
73
74/* Append. */
75static inline void
76list_append(struct list_head *head, void *new)
77{
78 ASSERT_WRITE_LOCK(head);
79 list_add((new), (head)->prev);
80}
81
82/* Prepend. */
83static inline void
84list_prepend(struct list_head *head, void *new)
85{
86 ASSERT_WRITE_LOCK(head);
87 list_add(new, head);
88}
89
90/* Insert according to ordering function; insert before first true. */
91#define LIST_INSERT(head, new, cmpfn) \
92do { \
93 struct list_head *__i; \
94 ASSERT_WRITE_LOCK(head); \
95 list_for_each(__i, (head)) \
96 if ((new), (typeof (new))__i) \
97 break; \
98 list_add((struct list_head *)(new), __i->prev); \
99} while(0)
100
101/* If the field after the list_head is a nul-terminated string, you
102 can use these functions. */
103static inline int __list_cmp_name(const void *i, const char *name)
104{
105 return strcmp(name, i+sizeof(struct list_head)) == 0;
106}
107
108/* Returns false if same name already in list, otherwise does insert. */
109static inline int
110list_named_insert(struct list_head *head, void *new)
111{
112 if (LIST_FIND(head, __list_cmp_name, void *,
113 new + sizeof(struct list_head)))
114 return 0;
115 list_prepend(head, new);
116 return 1;
117}
118
119/* Find this named element in the list. */
120#define list_named_find(head, name) \
121LIST_FIND(head, __list_cmp_name, void *, name)
122
123#endif /*_LISTHELP_H*/
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index d06a5075b5f6..3df55b2bd91d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -24,6 +24,7 @@
24#include <linux/vmalloc.h> 24#include <linux/vmalloc.h>
25#include <linux/netfilter_bridge/ebtables.h> 25#include <linux/netfilter_bridge/ebtables.h>
26#include <linux/spinlock.h> 26#include <linux/spinlock.h>
27#include <linux/mutex.h>
27#include <asm/uaccess.h> 28#include <asm/uaccess.h>
28#include <linux/smp.h> 29#include <linux/smp.h>
29#include <linux/cpumask.h> 30#include <linux/cpumask.h>
@@ -31,12 +32,6 @@
31/* needed for logical [in,out]-dev filtering */ 32/* needed for logical [in,out]-dev filtering */
32#include "../br_private.h" 33#include "../br_private.h"
33 34
34/* list_named_find */
35#define ASSERT_READ_LOCK(x)
36#define ASSERT_WRITE_LOCK(x)
37#include <linux/netfilter_ipv4/listhelp.h>
38#include <linux/mutex.h>
39
40#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ 35#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
41 "report to author: "format, ## args) 36 "report to author: "format, ## args)
42/* #define BUGPRINT(format, args...) */ 37/* #define BUGPRINT(format, args...) */
@@ -278,18 +273,22 @@ static inline void *
278find_inlist_lock_noload(struct list_head *head, const char *name, int *error, 273find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
279 struct mutex *mutex) 274 struct mutex *mutex)
280{ 275{
281 void *ret; 276 struct {
277 struct list_head list;
278 char name[EBT_FUNCTION_MAXNAMELEN];
279 } *e;
282 280
283 *error = mutex_lock_interruptible(mutex); 281 *error = mutex_lock_interruptible(mutex);
284 if (*error != 0) 282 if (*error != 0)
285 return NULL; 283 return NULL;
286 284
287 ret = list_named_find(head, name); 285 list_for_each_entry(e, head, list) {
288 if (!ret) { 286 if (strcmp(e->name, name) == 0)
289 *error = -ENOENT; 287 return e;
290 mutex_unlock(mutex);
291 } 288 }
292 return ret; 289 *error = -ENOENT;
290 mutex_unlock(mutex);
291 return NULL;
293} 292}
294 293
295#ifndef CONFIG_KMOD 294#ifndef CONFIG_KMOD
@@ -1043,15 +1042,19 @@ free_newinfo:
1043 1042
1044int ebt_register_target(struct ebt_target *target) 1043int ebt_register_target(struct ebt_target *target)
1045{ 1044{
1045 struct ebt_target *t;
1046 int ret; 1046 int ret;
1047 1047
1048 ret = mutex_lock_interruptible(&ebt_mutex); 1048 ret = mutex_lock_interruptible(&ebt_mutex);
1049 if (ret != 0) 1049 if (ret != 0)
1050 return ret; 1050 return ret;
1051 if (!list_named_insert(&ebt_targets, target)) { 1051 list_for_each_entry(t, &ebt_targets, list) {
1052 mutex_unlock(&ebt_mutex); 1052 if (strcmp(t->name, target->name) == 0) {
1053 return -EEXIST; 1053 mutex_unlock(&ebt_mutex);
1054 return -EEXIST;
1055 }
1054 } 1056 }
1057 list_add(&target->list, &ebt_targets);
1055 mutex_unlock(&ebt_mutex); 1058 mutex_unlock(&ebt_mutex);
1056 1059
1057 return 0; 1060 return 0;
@@ -1060,21 +1063,25 @@ int ebt_register_target(struct ebt_target *target)
1060void ebt_unregister_target(struct ebt_target *target) 1063void ebt_unregister_target(struct ebt_target *target)
1061{ 1064{
1062 mutex_lock(&ebt_mutex); 1065 mutex_lock(&ebt_mutex);
1063 LIST_DELETE(&ebt_targets, target); 1066 list_del(&target->list);
1064 mutex_unlock(&ebt_mutex); 1067 mutex_unlock(&ebt_mutex);
1065} 1068}
1066 1069
1067int ebt_register_match(struct ebt_match *match) 1070int ebt_register_match(struct ebt_match *match)
1068{ 1071{
1072 struct ebt_match *m;
1069 int ret; 1073 int ret;
1070 1074
1071 ret = mutex_lock_interruptible(&ebt_mutex); 1075 ret = mutex_lock_interruptible(&ebt_mutex);
1072 if (ret != 0) 1076 if (ret != 0)
1073 return ret; 1077 return ret;
1074 if (!list_named_insert(&ebt_matches, match)) { 1078 list_for_each_entry(m, &ebt_matches, list) {
1075 mutex_unlock(&ebt_mutex); 1079 if (strcmp(m->name, match->name) == 0) {
1076 return -EEXIST; 1080 mutex_unlock(&ebt_mutex);
1081 return -EEXIST;
1082 }
1077 } 1083 }
1084 list_add(&match->list, &ebt_matches);
1078 mutex_unlock(&ebt_mutex); 1085 mutex_unlock(&ebt_mutex);
1079 1086
1080 return 0; 1087 return 0;
@@ -1083,21 +1090,25 @@ int ebt_register_match(struct ebt_match *match)
1083void ebt_unregister_match(struct ebt_match *match) 1090void ebt_unregister_match(struct ebt_match *match)
1084{ 1091{
1085 mutex_lock(&ebt_mutex); 1092 mutex_lock(&ebt_mutex);
1086 LIST_DELETE(&ebt_matches, match); 1093 list_del(&match->list);
1087 mutex_unlock(&ebt_mutex); 1094 mutex_unlock(&ebt_mutex);
1088} 1095}
1089 1096
1090int ebt_register_watcher(struct ebt_watcher *watcher) 1097int ebt_register_watcher(struct ebt_watcher *watcher)
1091{ 1098{
1099 struct ebt_watcher *w;
1092 int ret; 1100 int ret;
1093 1101
1094 ret = mutex_lock_interruptible(&ebt_mutex); 1102 ret = mutex_lock_interruptible(&ebt_mutex);
1095 if (ret != 0) 1103 if (ret != 0)
1096 return ret; 1104 return ret;
1097 if (!list_named_insert(&ebt_watchers, watcher)) { 1105 list_for_each_entry(w, &ebt_watchers, list) {
1098 mutex_unlock(&ebt_mutex); 1106 if (strcmp(w->name, watcher->name) == 0) {
1099 return -EEXIST; 1107 mutex_unlock(&ebt_mutex);
1108 return -EEXIST;
1109 }
1100 } 1110 }
1111 list_add(&watcher->list, &ebt_watchers);
1101 mutex_unlock(&ebt_mutex); 1112 mutex_unlock(&ebt_mutex);
1102 1113
1103 return 0; 1114 return 0;
@@ -1106,13 +1117,14 @@ int ebt_register_watcher(struct ebt_watcher *watcher)
1106void ebt_unregister_watcher(struct ebt_watcher *watcher) 1117void ebt_unregister_watcher(struct ebt_watcher *watcher)
1107{ 1118{
1108 mutex_lock(&ebt_mutex); 1119 mutex_lock(&ebt_mutex);
1109 LIST_DELETE(&ebt_watchers, watcher); 1120 list_del(&watcher->list);
1110 mutex_unlock(&ebt_mutex); 1121 mutex_unlock(&ebt_mutex);
1111} 1122}
1112 1123
1113int ebt_register_table(struct ebt_table *table) 1124int ebt_register_table(struct ebt_table *table)
1114{ 1125{
1115 struct ebt_table_info *newinfo; 1126 struct ebt_table_info *newinfo;
1127 struct ebt_table *t;
1116 int ret, i, countersize; 1128 int ret, i, countersize;
1117 1129
1118 if (!table || !table->table ||!table->table->entries || 1130 if (!table || !table->table ||!table->table->entries ||
@@ -1158,10 +1170,12 @@ int ebt_register_table(struct ebt_table *table)
1158 if (ret != 0) 1170 if (ret != 0)
1159 goto free_chainstack; 1171 goto free_chainstack;
1160 1172
1161 if (list_named_find(&ebt_tables, table->name)) { 1173 list_for_each_entry(t, &ebt_tables, list) {
1162 ret = -EEXIST; 1174 if (strcmp(t->name, table->name) == 0) {
1163 BUGPRINT("Table name already exists\n"); 1175 ret = -EEXIST;
1164 goto free_unlock; 1176 BUGPRINT("Table name already exists\n");
1177 goto free_unlock;
1178 }
1165 } 1179 }
1166 1180
1167 /* Hold a reference count if the chains aren't empty */ 1181 /* Hold a reference count if the chains aren't empty */
@@ -1169,7 +1183,7 @@ int ebt_register_table(struct ebt_table *table)
1169 ret = -ENOENT; 1183 ret = -ENOENT;
1170 goto free_unlock; 1184 goto free_unlock;
1171 } 1185 }
1172 list_prepend(&ebt_tables, table); 1186 list_add(&table->list, &ebt_tables);
1173 mutex_unlock(&ebt_mutex); 1187 mutex_unlock(&ebt_mutex);
1174 return 0; 1188 return 0;
1175free_unlock: 1189free_unlock:
@@ -1195,7 +1209,7 @@ void ebt_unregister_table(struct ebt_table *table)
1195 return; 1209 return;
1196 } 1210 }
1197 mutex_lock(&ebt_mutex); 1211 mutex_lock(&ebt_mutex);
1198 LIST_DELETE(&ebt_tables, table); 1212 list_del(&table->list);
1199 mutex_unlock(&ebt_mutex); 1213 mutex_unlock(&ebt_mutex);
1200 vfree(table->private->entries); 1214 vfree(table->private->entries);
1201 if (table->private->chainstack) { 1215 if (table->private->chainstack) {
@@ -1465,7 +1479,7 @@ static int __init ebtables_init(void)
1465 int ret; 1479 int ret;
1466 1480
1467 mutex_lock(&ebt_mutex); 1481 mutex_lock(&ebt_mutex);
1468 list_named_insert(&ebt_targets, &ebt_standard_target); 1482 list_add(&ebt_standard_target.list, &ebt_targets);
1469 mutex_unlock(&ebt_mutex); 1483 mutex_unlock(&ebt_mutex);
1470 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) 1484 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1471 return ret; 1485 return ret;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 4f10b06413a1..aaeaa9ce0f28 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -56,8 +56,6 @@ do { \
56#define ARP_NF_ASSERT(x) 56#define ARP_NF_ASSERT(x)
57#endif 57#endif
58 58
59#include <linux/netfilter_ipv4/listhelp.h>
60
61static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 59static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
62 char *hdr_addr, int len) 60 char *hdr_addr, int len)
63{ 61{
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 5da25ad50309..2568d480e9a9 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -47,7 +47,6 @@
47#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 47#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
48#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 48#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
49#include <linux/netfilter_ipv4/ip_conntrack_core.h> 49#include <linux/netfilter_ipv4/ip_conntrack_core.h>
50#include <linux/netfilter_ipv4/listhelp.h>
51 50
52#define IP_CONNTRACK_VERSION "2.4" 51#define IP_CONNTRACK_VERSION "2.4"
53 52
@@ -294,15 +293,10 @@ void ip_ct_remove_expectations(struct ip_conntrack *ct)
294static void 293static void
295clean_from_lists(struct ip_conntrack *ct) 294clean_from_lists(struct ip_conntrack *ct)
296{ 295{
297 unsigned int ho, hr;
298
299 DEBUGP("clean_from_lists(%p)\n", ct); 296 DEBUGP("clean_from_lists(%p)\n", ct);
300 ASSERT_WRITE_LOCK(&ip_conntrack_lock); 297 ASSERT_WRITE_LOCK(&ip_conntrack_lock);
301 298 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
302 ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 299 list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
303 hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
304 LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
305 LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
306 300
307 /* Destroy all pending expectations */ 301 /* Destroy all pending expectations */
308 ip_ct_remove_expectations(ct); 302 ip_ct_remove_expectations(ct);
@@ -367,16 +361,6 @@ static void death_by_timeout(unsigned long ul_conntrack)
367 ip_conntrack_put(ct); 361 ip_conntrack_put(ct);
368} 362}
369 363
370static inline int
371conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i,
372 const struct ip_conntrack_tuple *tuple,
373 const struct ip_conntrack *ignored_conntrack)
374{
375 ASSERT_READ_LOCK(&ip_conntrack_lock);
376 return tuplehash_to_ctrack(i) != ignored_conntrack
377 && ip_ct_tuple_equal(tuple, &i->tuple);
378}
379
380struct ip_conntrack_tuple_hash * 364struct ip_conntrack_tuple_hash *
381__ip_conntrack_find(const struct ip_conntrack_tuple *tuple, 365__ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
382 const struct ip_conntrack *ignored_conntrack) 366 const struct ip_conntrack *ignored_conntrack)
@@ -386,7 +370,8 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
386 370
387 ASSERT_READ_LOCK(&ip_conntrack_lock); 371 ASSERT_READ_LOCK(&ip_conntrack_lock);
388 list_for_each_entry(h, &ip_conntrack_hash[hash], list) { 372 list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
389 if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) { 373 if (tuplehash_to_ctrack(h) != ignored_conntrack &&
374 ip_ct_tuple_equal(tuple, &h->tuple)) {
390 CONNTRACK_STAT_INC(found); 375 CONNTRACK_STAT_INC(found);
391 return h; 376 return h;
392 } 377 }
@@ -417,10 +402,10 @@ static void __ip_conntrack_hash_insert(struct ip_conntrack *ct,
417 unsigned int repl_hash) 402 unsigned int repl_hash)
418{ 403{
419 ct->id = ++ip_conntrack_next_id; 404 ct->id = ++ip_conntrack_next_id;
420 list_prepend(&ip_conntrack_hash[hash], 405 list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
421 &ct->tuplehash[IP_CT_DIR_ORIGINAL].list); 406 &ip_conntrack_hash[hash]);
422 list_prepend(&ip_conntrack_hash[repl_hash], 407 list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
423 &ct->tuplehash[IP_CT_DIR_REPLY].list); 408 &ip_conntrack_hash[repl_hash]);
424} 409}
425 410
426void ip_conntrack_hash_insert(struct ip_conntrack *ct) 411void ip_conntrack_hash_insert(struct ip_conntrack *ct)
@@ -440,6 +425,7 @@ int
440__ip_conntrack_confirm(struct sk_buff **pskb) 425__ip_conntrack_confirm(struct sk_buff **pskb)
441{ 426{
442 unsigned int hash, repl_hash; 427 unsigned int hash, repl_hash;
428 struct ip_conntrack_tuple_hash *h;
443 struct ip_conntrack *ct; 429 struct ip_conntrack *ct;
444 enum ip_conntrack_info ctinfo; 430 enum ip_conntrack_info ctinfo;
445 431
@@ -470,43 +456,43 @@ __ip_conntrack_confirm(struct sk_buff **pskb)
470 /* See if there's one in the list already, including reverse: 456 /* See if there's one in the list already, including reverse:
471 NAT could have grabbed it without realizing, since we're 457 NAT could have grabbed it without realizing, since we're
472 not in the hash. If there is, we lost race. */ 458 not in the hash. If there is, we lost race. */
473 if (!LIST_FIND(&ip_conntrack_hash[hash], 459 list_for_each_entry(h, &ip_conntrack_hash[hash], list)
474 conntrack_tuple_cmp, 460 if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
475 struct ip_conntrack_tuple_hash *, 461 &h->tuple))
476 &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) 462 goto out;
477 && !LIST_FIND(&ip_conntrack_hash[repl_hash], 463 list_for_each_entry(h, &ip_conntrack_hash[repl_hash], list)
478 conntrack_tuple_cmp, 464 if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
479 struct ip_conntrack_tuple_hash *, 465 &h->tuple))
480 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { 466 goto out;
481 /* Remove from unconfirmed list */
482 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
483 467
484 __ip_conntrack_hash_insert(ct, hash, repl_hash); 468 /* Remove from unconfirmed list */
485 /* Timer relative to confirmation time, not original 469 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
486 setting time, otherwise we'd get timer wrap in 470
487 weird delay cases. */ 471 __ip_conntrack_hash_insert(ct, hash, repl_hash);
488 ct->timeout.expires += jiffies; 472 /* Timer relative to confirmation time, not original
489 add_timer(&ct->timeout); 473 setting time, otherwise we'd get timer wrap in
490 atomic_inc(&ct->ct_general.use); 474 weird delay cases. */
491 set_bit(IPS_CONFIRMED_BIT, &ct->status); 475 ct->timeout.expires += jiffies;
492 CONNTRACK_STAT_INC(insert); 476 add_timer(&ct->timeout);
493 write_unlock_bh(&ip_conntrack_lock); 477 atomic_inc(&ct->ct_general.use);
494 if (ct->helper) 478 set_bit(IPS_CONFIRMED_BIT, &ct->status);
495 ip_conntrack_event_cache(IPCT_HELPER, *pskb); 479 CONNTRACK_STAT_INC(insert);
480 write_unlock_bh(&ip_conntrack_lock);
481 if (ct->helper)
482 ip_conntrack_event_cache(IPCT_HELPER, *pskb);
496#ifdef CONFIG_IP_NF_NAT_NEEDED 483#ifdef CONFIG_IP_NF_NAT_NEEDED
497 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || 484 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
498 test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) 485 test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
499 ip_conntrack_event_cache(IPCT_NATINFO, *pskb); 486 ip_conntrack_event_cache(IPCT_NATINFO, *pskb);
500#endif 487#endif
501 ip_conntrack_event_cache(master_ct(ct) ? 488 ip_conntrack_event_cache(master_ct(ct) ?
502 IPCT_RELATED : IPCT_NEW, *pskb); 489 IPCT_RELATED : IPCT_NEW, *pskb);
503 490
504 return NF_ACCEPT; 491 return NF_ACCEPT;
505 }
506 492
493out:
507 CONNTRACK_STAT_INC(insert_failed); 494 CONNTRACK_STAT_INC(insert_failed);
508 write_unlock_bh(&ip_conntrack_lock); 495 write_unlock_bh(&ip_conntrack_lock);
509
510 return NF_DROP; 496 return NF_DROP;
511} 497}
512 498
@@ -527,23 +513,21 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
527 513
528/* There's a small race here where we may free a just-assured 514/* There's a small race here where we may free a just-assured
529 connection. Too bad: we're in trouble anyway. */ 515 connection. Too bad: we're in trouble anyway. */
530static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
531{
532 return !(test_bit(IPS_ASSURED_BIT, &tuplehash_to_ctrack(i)->status));
533}
534
535static int early_drop(struct list_head *chain) 516static int early_drop(struct list_head *chain)
536{ 517{
537 /* Traverse backwards: gives us oldest, which is roughly LRU */ 518 /* Traverse backwards: gives us oldest, which is roughly LRU */
538 struct ip_conntrack_tuple_hash *h; 519 struct ip_conntrack_tuple_hash *h;
539 struct ip_conntrack *ct = NULL; 520 struct ip_conntrack *ct = NULL, *tmp;
540 int dropped = 0; 521 int dropped = 0;
541 522
542 read_lock_bh(&ip_conntrack_lock); 523 read_lock_bh(&ip_conntrack_lock);
543 h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *); 524 list_for_each_entry_reverse(h, chain, list) {
544 if (h) { 525 tmp = tuplehash_to_ctrack(h);
545 ct = tuplehash_to_ctrack(h); 526 if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
546 atomic_inc(&ct->ct_general.use); 527 ct = tmp;
528 atomic_inc(&ct->ct_general.use);
529 break;
530 }
547 } 531 }
548 read_unlock_bh(&ip_conntrack_lock); 532 read_unlock_bh(&ip_conntrack_lock);
549 533
@@ -559,18 +543,16 @@ static int early_drop(struct list_head *chain)
559 return dropped; 543 return dropped;
560} 544}
561 545
562static inline int helper_cmp(const struct ip_conntrack_helper *i,
563 const struct ip_conntrack_tuple *rtuple)
564{
565 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
566}
567
568static struct ip_conntrack_helper * 546static struct ip_conntrack_helper *
569__ip_conntrack_helper_find( const struct ip_conntrack_tuple *tuple) 547__ip_conntrack_helper_find( const struct ip_conntrack_tuple *tuple)
570{ 548{
571 return LIST_FIND(&helpers, helper_cmp, 549 struct ip_conntrack_helper *h;
572 struct ip_conntrack_helper *, 550
573 tuple); 551 list_for_each_entry(h, &helpers, list) {
552 if (ip_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
553 return h;
554 }
555 return NULL;
574} 556}
575 557
576struct ip_conntrack_helper * 558struct ip_conntrack_helper *
@@ -1062,7 +1044,7 @@ int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
1062{ 1044{
1063 BUG_ON(me->timeout == 0); 1045 BUG_ON(me->timeout == 0);
1064 write_lock_bh(&ip_conntrack_lock); 1046 write_lock_bh(&ip_conntrack_lock);
1065 list_prepend(&helpers, me); 1047 list_add(&me->list, &helpers);
1066 write_unlock_bh(&ip_conntrack_lock); 1048 write_unlock_bh(&ip_conntrack_lock);
1067 1049
1068 return 0; 1050 return 0;
@@ -1081,24 +1063,24 @@ __ip_conntrack_helper_find_byname(const char *name)
1081 return NULL; 1063 return NULL;
1082} 1064}
1083 1065
1084static inline int unhelp(struct ip_conntrack_tuple_hash *i, 1066static inline void unhelp(struct ip_conntrack_tuple_hash *i,
1085 const struct ip_conntrack_helper *me) 1067 const struct ip_conntrack_helper *me)
1086{ 1068{
1087 if (tuplehash_to_ctrack(i)->helper == me) { 1069 if (tuplehash_to_ctrack(i)->helper == me) {
1088 ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i)); 1070 ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i));
1089 tuplehash_to_ctrack(i)->helper = NULL; 1071 tuplehash_to_ctrack(i)->helper = NULL;
1090 } 1072 }
1091 return 0;
1092} 1073}
1093 1074
1094void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) 1075void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1095{ 1076{
1096 unsigned int i; 1077 unsigned int i;
1078 struct ip_conntrack_tuple_hash *h;
1097 struct ip_conntrack_expect *exp, *tmp; 1079 struct ip_conntrack_expect *exp, *tmp;
1098 1080
1099 /* Need write lock here, to delete helper. */ 1081 /* Need write lock here, to delete helper. */
1100 write_lock_bh(&ip_conntrack_lock); 1082 write_lock_bh(&ip_conntrack_lock);
1101 LIST_DELETE(&helpers, me); 1083 list_del(&me->list);
1102 1084
1103 /* Get rid of expectations */ 1085 /* Get rid of expectations */
1104 list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) { 1086 list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) {
@@ -1108,10 +1090,12 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1108 } 1090 }
1109 } 1091 }
1110 /* Get rid of expecteds, set helpers to NULL. */ 1092 /* Get rid of expecteds, set helpers to NULL. */
1111 LIST_FIND_W(&unconfirmed, unhelp, struct ip_conntrack_tuple_hash*, me); 1093 list_for_each_entry(h, &unconfirmed, list)
1112 for (i = 0; i < ip_conntrack_htable_size; i++) 1094 unhelp(h, me);
1113 LIST_FIND_W(&ip_conntrack_hash[i], unhelp, 1095 for (i = 0; i < ip_conntrack_htable_size; i++) {
1114 struct ip_conntrack_tuple_hash *, me); 1096 list_for_each_entry(h, &ip_conntrack_hash[i], list)
1097 unhelp(h, me);
1098 }
1115 write_unlock_bh(&ip_conntrack_lock); 1099 write_unlock_bh(&ip_conntrack_lock);
1116 1100
1117 /* Someone could be still looking at the helper in a bh. */ 1101 /* Someone could be still looking at the helper in a bh. */
@@ -1237,46 +1221,43 @@ static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb)
1237 nf_conntrack_get(nskb->nfct); 1221 nf_conntrack_get(nskb->nfct);
1238} 1222}
1239 1223
1240static inline int
1241do_iter(const struct ip_conntrack_tuple_hash *i,
1242 int (*iter)(struct ip_conntrack *i, void *data),
1243 void *data)
1244{
1245 return iter(tuplehash_to_ctrack(i), data);
1246}
1247
1248/* Bring out ya dead! */ 1224/* Bring out ya dead! */
1249static struct ip_conntrack_tuple_hash * 1225static struct ip_conntrack *
1250get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data), 1226get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data),
1251 void *data, unsigned int *bucket) 1227 void *data, unsigned int *bucket)
1252{ 1228{
1253 struct ip_conntrack_tuple_hash *h = NULL; 1229 struct ip_conntrack_tuple_hash *h;
1230 struct ip_conntrack *ct;
1254 1231
1255 write_lock_bh(&ip_conntrack_lock); 1232 write_lock_bh(&ip_conntrack_lock);
1256 for (; *bucket < ip_conntrack_htable_size; (*bucket)++) { 1233 for (; *bucket < ip_conntrack_htable_size; (*bucket)++) {
1257 h = LIST_FIND_W(&ip_conntrack_hash[*bucket], do_iter, 1234 list_for_each_entry(h, &ip_conntrack_hash[*bucket], list) {
1258 struct ip_conntrack_tuple_hash *, iter, data); 1235 ct = tuplehash_to_ctrack(h);
1259 if (h) 1236 if (iter(ct, data))
1260 break; 1237 goto found;
1238 }
1239 }
1240 list_for_each_entry(h, &unconfirmed, list) {
1241 ct = tuplehash_to_ctrack(h);
1242 if (iter(ct, data))
1243 goto found;
1261 } 1244 }
1262 if (!h)
1263 h = LIST_FIND_W(&unconfirmed, do_iter,
1264 struct ip_conntrack_tuple_hash *, iter, data);
1265 if (h)
1266 atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
1267 write_unlock_bh(&ip_conntrack_lock); 1245 write_unlock_bh(&ip_conntrack_lock);
1246 return NULL;
1268 1247
1269 return h; 1248found:
1249 atomic_inc(&ct->ct_general.use);
1250 write_unlock_bh(&ip_conntrack_lock);
1251 return ct;
1270} 1252}
1271 1253
1272void 1254void
1273ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *), void *data) 1255ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *), void *data)
1274{ 1256{
1275 struct ip_conntrack_tuple_hash *h; 1257 struct ip_conntrack *ct;
1276 unsigned int bucket = 0; 1258 unsigned int bucket = 0;
1277 1259
1278 while ((h = get_next_corpse(iter, data, &bucket)) != NULL) { 1260 while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
1279 struct ip_conntrack *ct = tuplehash_to_ctrack(h);
1280 /* Time to push up daises... */ 1261 /* Time to push up daises... */
1281 if (del_timer(&ct->timeout)) 1262 if (del_timer(&ct->timeout))
1282 death_by_timeout((unsigned long)ct); 1263 death_by_timeout((unsigned long)ct);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 4ee016c427b4..92c6d8b178c9 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -37,7 +37,6 @@ static DEFINE_RWLOCK(ip_ct_gre_lock);
37#define ASSERT_READ_LOCK(x) 37#define ASSERT_READ_LOCK(x)
38#define ASSERT_WRITE_LOCK(x) 38#define ASSERT_WRITE_LOCK(x)
39 39
40#include <linux/netfilter_ipv4/listhelp.h>
41#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 40#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
42#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 41#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
43#include <linux/netfilter_ipv4/ip_conntrack_core.h> 42#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -82,10 +81,12 @@ static __be16 gre_keymap_lookup(struct ip_conntrack_tuple *t)
82 __be16 key = 0; 81 __be16 key = 0;
83 82
84 read_lock_bh(&ip_ct_gre_lock); 83 read_lock_bh(&ip_ct_gre_lock);
85 km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, 84 list_for_each_entry(km, &gre_keymap_list, list) {
86 struct ip_ct_gre_keymap *, t); 85 if (gre_key_cmpfn(km, t)) {
87 if (km) 86 key = km->tuple.src.u.gre.key;
88 key = km->tuple.src.u.gre.key; 87 break;
88 }
89 }
89 read_unlock_bh(&ip_ct_gre_lock); 90 read_unlock_bh(&ip_ct_gre_lock);
90 91
91 DEBUGP("lookup src key 0x%x up key for ", key); 92 DEBUGP("lookup src key 0x%x up key for ", key);
@@ -99,7 +100,7 @@ int
99ip_ct_gre_keymap_add(struct ip_conntrack *ct, 100ip_ct_gre_keymap_add(struct ip_conntrack *ct,
100 struct ip_conntrack_tuple *t, int reply) 101 struct ip_conntrack_tuple *t, int reply)
101{ 102{
102 struct ip_ct_gre_keymap **exist_km, *km, *old; 103 struct ip_ct_gre_keymap **exist_km, *km;
103 104
104 if (!ct->helper || strcmp(ct->helper->name, "pptp")) { 105 if (!ct->helper || strcmp(ct->helper->name, "pptp")) {
105 DEBUGP("refusing to add GRE keymap to non-pptp session\n"); 106 DEBUGP("refusing to add GRE keymap to non-pptp session\n");
@@ -113,13 +114,10 @@ ip_ct_gre_keymap_add(struct ip_conntrack *ct,
113 114
114 if (*exist_km) { 115 if (*exist_km) {
115 /* check whether it's a retransmission */ 116 /* check whether it's a retransmission */
116 old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, 117 list_for_each_entry(km, &gre_keymap_list, list) {
117 struct ip_ct_gre_keymap *, t); 118 if (gre_key_cmpfn(km, t) && km == *exist_km)
118 if (old == *exist_km) { 119 return 0;
119 DEBUGP("retransmission\n");
120 return 0;
121 } 120 }
122
123 DEBUGP("trying to override keymap_%s for ct %p\n", 121 DEBUGP("trying to override keymap_%s for ct %p\n",
124 reply? "reply":"orig", ct); 122 reply? "reply":"orig", ct);
125 return -EEXIST; 123 return -EEXIST;
@@ -136,7 +134,7 @@ ip_ct_gre_keymap_add(struct ip_conntrack *ct,
136 DUMP_TUPLE_GRE(&km->tuple); 134 DUMP_TUPLE_GRE(&km->tuple);
137 135
138 write_lock_bh(&ip_ct_gre_lock); 136 write_lock_bh(&ip_ct_gre_lock);
139 list_append(&gre_keymap_list, km); 137 list_add_tail(&km->list, &gre_keymap_list);
140 write_unlock_bh(&ip_ct_gre_lock); 138 write_unlock_bh(&ip_ct_gre_lock);
141 139
142 return 0; 140 return 0;
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 3f5d495b853b..02135756562e 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -35,7 +35,6 @@
35#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 35#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
36#include <linux/netfilter_ipv4/ip_conntrack_core.h> 36#include <linux/netfilter_ipv4/ip_conntrack_core.h>
37#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 37#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
38#include <linux/netfilter_ipv4/listhelp.h>
39 38
40#if 0 39#if 0
41#define DEBUGP printk 40#define DEBUGP printk
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 4c540d03d48e..71f3e09cbc84 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -22,9 +22,6 @@
22#include <linux/udp.h> 22#include <linux/udp.h>
23#include <linux/jhash.h> 23#include <linux/jhash.h>
24 24
25#define ASSERT_READ_LOCK(x)
26#define ASSERT_WRITE_LOCK(x)
27
28#include <linux/netfilter_ipv4/ip_conntrack.h> 25#include <linux/netfilter_ipv4/ip_conntrack.h>
29#include <linux/netfilter_ipv4/ip_conntrack_core.h> 26#include <linux/netfilter_ipv4/ip_conntrack_core.h>
30#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> 27#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -33,7 +30,6 @@
33#include <linux/netfilter_ipv4/ip_nat_core.h> 30#include <linux/netfilter_ipv4/ip_nat_core.h>
34#include <linux/netfilter_ipv4/ip_nat_helper.h> 31#include <linux/netfilter_ipv4/ip_nat_helper.h>
35#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 32#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
36#include <linux/netfilter_ipv4/listhelp.h>
37 33
38#if 0 34#if 0
39#define DEBUGP printk 35#define DEBUGP printk
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 021c3daae3ed..7f6a75984f6c 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -27,16 +27,12 @@
27#include <net/tcp.h> 27#include <net/tcp.h>
28#include <net/udp.h> 28#include <net/udp.h>
29 29
30#define ASSERT_READ_LOCK(x)
31#define ASSERT_WRITE_LOCK(x)
32
33#include <linux/netfilter_ipv4/ip_conntrack.h> 30#include <linux/netfilter_ipv4/ip_conntrack.h>
34#include <linux/netfilter_ipv4/ip_conntrack_helper.h> 31#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
35#include <linux/netfilter_ipv4/ip_nat.h> 32#include <linux/netfilter_ipv4/ip_nat.h>
36#include <linux/netfilter_ipv4/ip_nat_protocol.h> 33#include <linux/netfilter_ipv4/ip_nat_protocol.h>
37#include <linux/netfilter_ipv4/ip_nat_core.h> 34#include <linux/netfilter_ipv4/ip_nat_core.h>
38#include <linux/netfilter_ipv4/ip_nat_helper.h> 35#include <linux/netfilter_ipv4/ip_nat_helper.h>
39#include <linux/netfilter_ipv4/listhelp.h>
40 36
41#if 0 37#if 0
42#define DEBUGP printk 38#define DEBUGP printk
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index e59f5a8ecb6b..7b703839aa58 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -19,14 +19,10 @@
19#include <net/route.h> 19#include <net/route.h>
20#include <linux/bitops.h> 20#include <linux/bitops.h>
21 21
22#define ASSERT_READ_LOCK(x)
23#define ASSERT_WRITE_LOCK(x)
24
25#include <linux/netfilter_ipv4/ip_tables.h> 22#include <linux/netfilter_ipv4/ip_tables.h>
26#include <linux/netfilter_ipv4/ip_nat.h> 23#include <linux/netfilter_ipv4/ip_nat.h>
27#include <linux/netfilter_ipv4/ip_nat_core.h> 24#include <linux/netfilter_ipv4/ip_nat_core.h>
28#include <linux/netfilter_ipv4/ip_nat_rule.h> 25#include <linux/netfilter_ipv4/ip_nat_rule.h>
29#include <linux/netfilter_ipv4/listhelp.h>
30 26
31#if 0 27#if 0
32#define DEBUGP printk 28#define DEBUGP printk
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index f3b778355432..9c577db62047 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -30,9 +30,6 @@
30#include <net/checksum.h> 30#include <net/checksum.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32 32
33#define ASSERT_READ_LOCK(x)
34#define ASSERT_WRITE_LOCK(x)
35
36#include <linux/netfilter_ipv4/ip_nat.h> 33#include <linux/netfilter_ipv4/ip_nat.h>
37#include <linux/netfilter_ipv4/ip_nat_rule.h> 34#include <linux/netfilter_ipv4/ip_nat_rule.h>
38#include <linux/netfilter_ipv4/ip_nat_protocol.h> 35#include <linux/netfilter_ipv4/ip_nat_protocol.h>
@@ -40,7 +37,6 @@
40#include <linux/netfilter_ipv4/ip_nat_helper.h> 37#include <linux/netfilter_ipv4/ip_nat_helper.h>
41#include <linux/netfilter_ipv4/ip_tables.h> 38#include <linux/netfilter_ipv4/ip_tables.h>
42#include <linux/netfilter_ipv4/ip_conntrack_core.h> 39#include <linux/netfilter_ipv4/ip_conntrack_core.h>
43#include <linux/netfilter_ipv4/listhelp.h>
44 40
45#if 0 41#if 0
46#define DEBUGP printk 42#define DEBUGP printk
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index d1c315364ee7..73d477ce216b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -70,9 +70,6 @@ do { \
70#define IP_NF_ASSERT(x) 70#define IP_NF_ASSERT(x)
71#endif 71#endif
72 72
73
74#include <linux/netfilter_ipv4/listhelp.h>
75
76#if 0 73#if 0
77/* All the better to debug you with... */ 74/* All the better to debug you with... */
78#define static 75#define static
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3b64dbee6620..927137b8b3b5 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -57,7 +57,6 @@
57#include <net/netfilter/nf_conntrack_protocol.h> 57#include <net/netfilter/nf_conntrack_protocol.h>
58#include <net/netfilter/nf_conntrack_helper.h> 58#include <net/netfilter/nf_conntrack_helper.h>
59#include <net/netfilter/nf_conntrack_core.h> 59#include <net/netfilter/nf_conntrack_core.h>
60#include <linux/netfilter_ipv4/listhelp.h>
61 60
62#define NF_CONNTRACK_VERSION "0.5.0" 61#define NF_CONNTRACK_VERSION "0.5.0"
63 62
@@ -539,15 +538,10 @@ void nf_ct_remove_expectations(struct nf_conn *ct)
539static void 538static void
540clean_from_lists(struct nf_conn *ct) 539clean_from_lists(struct nf_conn *ct)
541{ 540{
542 unsigned int ho, hr;
543
544 DEBUGP("clean_from_lists(%p)\n", ct); 541 DEBUGP("clean_from_lists(%p)\n", ct);
545 ASSERT_WRITE_LOCK(&nf_conntrack_lock); 542 ASSERT_WRITE_LOCK(&nf_conntrack_lock);
546 543 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
547 ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 544 list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list);
548 hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
549 LIST_DELETE(&nf_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
550 LIST_DELETE(&nf_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
551 545
552 /* Destroy all pending expectations */ 546 /* Destroy all pending expectations */
553 nf_ct_remove_expectations(ct); 547 nf_ct_remove_expectations(ct);
@@ -617,16 +611,6 @@ static void death_by_timeout(unsigned long ul_conntrack)
617 nf_ct_put(ct); 611 nf_ct_put(ct);
618} 612}
619 613
620static inline int
621conntrack_tuple_cmp(const struct nf_conntrack_tuple_hash *i,
622 const struct nf_conntrack_tuple *tuple,
623 const struct nf_conn *ignored_conntrack)
624{
625 ASSERT_READ_LOCK(&nf_conntrack_lock);
626 return nf_ct_tuplehash_to_ctrack(i) != ignored_conntrack
627 && nf_ct_tuple_equal(tuple, &i->tuple);
628}
629
630struct nf_conntrack_tuple_hash * 614struct nf_conntrack_tuple_hash *
631__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, 615__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
632 const struct nf_conn *ignored_conntrack) 616 const struct nf_conn *ignored_conntrack)
@@ -636,7 +620,8 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
636 620
637 ASSERT_READ_LOCK(&nf_conntrack_lock); 621 ASSERT_READ_LOCK(&nf_conntrack_lock);
638 list_for_each_entry(h, &nf_conntrack_hash[hash], list) { 622 list_for_each_entry(h, &nf_conntrack_hash[hash], list) {
639 if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) { 623 if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack &&
624 nf_ct_tuple_equal(tuple, &h->tuple)) {
640 NF_CT_STAT_INC(found); 625 NF_CT_STAT_INC(found);
641 return h; 626 return h;
642 } 627 }
@@ -667,10 +652,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
667 unsigned int repl_hash) 652 unsigned int repl_hash)
668{ 653{
669 ct->id = ++nf_conntrack_next_id; 654 ct->id = ++nf_conntrack_next_id;
670 list_prepend(&nf_conntrack_hash[hash], 655 list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list,
671 &ct->tuplehash[IP_CT_DIR_ORIGINAL].list); 656 &nf_conntrack_hash[hash]);
672 list_prepend(&nf_conntrack_hash[repl_hash], 657 list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list,
673 &ct->tuplehash[IP_CT_DIR_REPLY].list); 658 &nf_conntrack_hash[repl_hash]);
674} 659}
675 660
676void nf_conntrack_hash_insert(struct nf_conn *ct) 661void nf_conntrack_hash_insert(struct nf_conn *ct)
@@ -690,7 +675,9 @@ int
690__nf_conntrack_confirm(struct sk_buff **pskb) 675__nf_conntrack_confirm(struct sk_buff **pskb)
691{ 676{
692 unsigned int hash, repl_hash; 677 unsigned int hash, repl_hash;
678 struct nf_conntrack_tuple_hash *h;
693 struct nf_conn *ct; 679 struct nf_conn *ct;
680 struct nf_conn_help *help;
694 enum ip_conntrack_info ctinfo; 681 enum ip_conntrack_info ctinfo;
695 682
696 ct = nf_ct_get(*pskb, &ctinfo); 683 ct = nf_ct_get(*pskb, &ctinfo);
@@ -720,41 +707,41 @@ __nf_conntrack_confirm(struct sk_buff **pskb)
720 /* See if there's one in the list already, including reverse: 707 /* See if there's one in the list already, including reverse:
721 NAT could have grabbed it without realizing, since we're 708 NAT could have grabbed it without realizing, since we're
722 not in the hash. If there is, we lost race. */ 709 not in the hash. If there is, we lost race. */
723 if (!LIST_FIND(&nf_conntrack_hash[hash], 710 list_for_each_entry(h, &nf_conntrack_hash[hash], list)
724 conntrack_tuple_cmp, 711 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
725 struct nf_conntrack_tuple_hash *, 712 &h->tuple))
726 &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) 713 goto out;
727 && !LIST_FIND(&nf_conntrack_hash[repl_hash], 714 list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list)
728 conntrack_tuple_cmp, 715 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
729 struct nf_conntrack_tuple_hash *, 716 &h->tuple))
730 &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { 717 goto out;
731 struct nf_conn_help *help;
732 /* Remove from unconfirmed list */
733 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
734 718
735 __nf_conntrack_hash_insert(ct, hash, repl_hash); 719 /* Remove from unconfirmed list */
736 /* Timer relative to confirmation time, not original 720 list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list);
737 setting time, otherwise we'd get timer wrap in 721
738 weird delay cases. */ 722 __nf_conntrack_hash_insert(ct, hash, repl_hash);
739 ct->timeout.expires += jiffies; 723 /* Timer relative to confirmation time, not original
740 add_timer(&ct->timeout); 724 setting time, otherwise we'd get timer wrap in
741 atomic_inc(&ct->ct_general.use); 725 weird delay cases. */
742 set_bit(IPS_CONFIRMED_BIT, &ct->status); 726 ct->timeout.expires += jiffies;
743 NF_CT_STAT_INC(insert); 727 add_timer(&ct->timeout);
744 write_unlock_bh(&nf_conntrack_lock); 728 atomic_inc(&ct->ct_general.use);
745 help = nfct_help(ct); 729 set_bit(IPS_CONFIRMED_BIT, &ct->status);
746 if (help && help->helper) 730 NF_CT_STAT_INC(insert);
747 nf_conntrack_event_cache(IPCT_HELPER, *pskb); 731 write_unlock_bh(&nf_conntrack_lock);
732 help = nfct_help(ct);
733 if (help && help->helper)
734 nf_conntrack_event_cache(IPCT_HELPER, *pskb);
748#ifdef CONFIG_NF_NAT_NEEDED 735#ifdef CONFIG_NF_NAT_NEEDED
749 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || 736 if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) ||
750 test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) 737 test_bit(IPS_DST_NAT_DONE_BIT, &ct->status))
751 nf_conntrack_event_cache(IPCT_NATINFO, *pskb); 738 nf_conntrack_event_cache(IPCT_NATINFO, *pskb);
752#endif 739#endif
753 nf_conntrack_event_cache(master_ct(ct) ? 740 nf_conntrack_event_cache(master_ct(ct) ?
754 IPCT_RELATED : IPCT_NEW, *pskb); 741 IPCT_RELATED : IPCT_NEW, *pskb);
755 return NF_ACCEPT; 742 return NF_ACCEPT;
756 }
757 743
744out:
758 NF_CT_STAT_INC(insert_failed); 745 NF_CT_STAT_INC(insert_failed);
759 write_unlock_bh(&nf_conntrack_lock); 746 write_unlock_bh(&nf_conntrack_lock);
760 return NF_DROP; 747 return NF_DROP;
@@ -777,24 +764,21 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
777 764
778/* There's a small race here where we may free a just-assured 765/* There's a small race here where we may free a just-assured
779 connection. Too bad: we're in trouble anyway. */ 766 connection. Too bad: we're in trouble anyway. */
780static inline int unreplied(const struct nf_conntrack_tuple_hash *i)
781{
782 return !(test_bit(IPS_ASSURED_BIT,
783 &nf_ct_tuplehash_to_ctrack(i)->status));
784}
785
786static int early_drop(struct list_head *chain) 767static int early_drop(struct list_head *chain)
787{ 768{
788 /* Traverse backwards: gives us oldest, which is roughly LRU */ 769 /* Traverse backwards: gives us oldest, which is roughly LRU */
789 struct nf_conntrack_tuple_hash *h; 770 struct nf_conntrack_tuple_hash *h;
790 struct nf_conn *ct = NULL; 771 struct nf_conn *ct = NULL, *tmp;
791 int dropped = 0; 772 int dropped = 0;
792 773
793 read_lock_bh(&nf_conntrack_lock); 774 read_lock_bh(&nf_conntrack_lock);
794 h = LIST_FIND_B(chain, unreplied, struct nf_conntrack_tuple_hash *); 775 list_for_each_entry_reverse(h, chain, list) {
795 if (h) { 776 tmp = nf_ct_tuplehash_to_ctrack(h);
796 ct = nf_ct_tuplehash_to_ctrack(h); 777 if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) {
797 atomic_inc(&ct->ct_general.use); 778 ct = tmp;
779 atomic_inc(&ct->ct_general.use);
780 break;
781 }
798 } 782 }
799 read_unlock_bh(&nf_conntrack_lock); 783 read_unlock_bh(&nf_conntrack_lock);
800 784
@@ -810,18 +794,16 @@ static int early_drop(struct list_head *chain)
810 return dropped; 794 return dropped;
811} 795}
812 796
813static inline int helper_cmp(const struct nf_conntrack_helper *i,
814 const struct nf_conntrack_tuple *rtuple)
815{
816 return nf_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
817}
818
819static struct nf_conntrack_helper * 797static struct nf_conntrack_helper *
820__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) 798__nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
821{ 799{
822 return LIST_FIND(&helpers, helper_cmp, 800 struct nf_conntrack_helper *h;
823 struct nf_conntrack_helper *, 801
824 tuple); 802 list_for_each_entry(h, &helpers, list) {
803 if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask))
804 return h;
805 }
806 return NULL;
825} 807}
826 808
827struct nf_conntrack_helper * 809struct nf_conntrack_helper *
@@ -1323,7 +1305,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
1323 return ret; 1305 return ret;
1324 } 1306 }
1325 write_lock_bh(&nf_conntrack_lock); 1307 write_lock_bh(&nf_conntrack_lock);
1326 list_prepend(&helpers, me); 1308 list_add(&me->list, &helpers);
1327 write_unlock_bh(&nf_conntrack_lock); 1309 write_unlock_bh(&nf_conntrack_lock);
1328 1310
1329 return 0; 1311 return 0;
@@ -1342,8 +1324,8 @@ __nf_conntrack_helper_find_byname(const char *name)
1342 return NULL; 1324 return NULL;
1343} 1325}
1344 1326
1345static inline int unhelp(struct nf_conntrack_tuple_hash *i, 1327static inline void unhelp(struct nf_conntrack_tuple_hash *i,
1346 const struct nf_conntrack_helper *me) 1328 const struct nf_conntrack_helper *me)
1347{ 1329{
1348 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 1330 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
1349 struct nf_conn_help *help = nfct_help(ct); 1331 struct nf_conn_help *help = nfct_help(ct);
@@ -1352,17 +1334,17 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
1352 nf_conntrack_event(IPCT_HELPER, ct); 1334 nf_conntrack_event(IPCT_HELPER, ct);
1353 help->helper = NULL; 1335 help->helper = NULL;
1354 } 1336 }
1355 return 0;
1356} 1337}
1357 1338
1358void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) 1339void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
1359{ 1340{
1360 unsigned int i; 1341 unsigned int i;
1342 struct nf_conntrack_tuple_hash *h;
1361 struct nf_conntrack_expect *exp, *tmp; 1343 struct nf_conntrack_expect *exp, *tmp;
1362 1344
1363 /* Need write lock here, to delete helper. */ 1345 /* Need write lock here, to delete helper. */
1364 write_lock_bh(&nf_conntrack_lock); 1346 write_lock_bh(&nf_conntrack_lock);
1365 LIST_DELETE(&helpers, me); 1347 list_del(&me->list);
1366 1348
1367 /* Get rid of expectations */ 1349 /* Get rid of expectations */
1368 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { 1350 list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) {
@@ -1374,10 +1356,12 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
1374 } 1356 }
1375 1357
1376 /* Get rid of expecteds, set helpers to NULL. */ 1358 /* Get rid of expecteds, set helpers to NULL. */
1377 LIST_FIND_W(&unconfirmed, unhelp, struct nf_conntrack_tuple_hash*, me); 1359 list_for_each_entry(h, &unconfirmed, list)
1378 for (i = 0; i < nf_conntrack_htable_size; i++) 1360 unhelp(h, me);
1379 LIST_FIND_W(&nf_conntrack_hash[i], unhelp, 1361 for (i = 0; i < nf_conntrack_htable_size; i++) {
1380 struct nf_conntrack_tuple_hash *, me); 1362 list_for_each_entry(h, &nf_conntrack_hash[i], list)
1363 unhelp(h, me);
1364 }
1381 write_unlock_bh(&nf_conntrack_lock); 1365 write_unlock_bh(&nf_conntrack_lock);
1382 1366
1383 /* Someone could be still looking at the helper in a bh. */ 1367 /* Someone could be still looking at the helper in a bh. */
@@ -1510,37 +1494,40 @@ do_iter(const struct nf_conntrack_tuple_hash *i,
1510} 1494}
1511 1495
1512/* Bring out ya dead! */ 1496/* Bring out ya dead! */
1513static struct nf_conntrack_tuple_hash * 1497static struct nf_conn *
1514get_next_corpse(int (*iter)(struct nf_conn *i, void *data), 1498get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
1515 void *data, unsigned int *bucket) 1499 void *data, unsigned int *bucket)
1516{ 1500{
1517 struct nf_conntrack_tuple_hash *h = NULL; 1501 struct nf_conntrack_tuple_hash *h;
1502 struct nf_conn *ct;
1518 1503
1519 write_lock_bh(&nf_conntrack_lock); 1504 write_lock_bh(&nf_conntrack_lock);
1520 for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { 1505 for (; *bucket < nf_conntrack_htable_size; (*bucket)++) {
1521 h = LIST_FIND_W(&nf_conntrack_hash[*bucket], do_iter, 1506 list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) {
1522 struct nf_conntrack_tuple_hash *, iter, data); 1507 ct = nf_ct_tuplehash_to_ctrack(h);
1523 if (h) 1508 if (iter(ct, data))
1524 break; 1509 goto found;
1510 }
1525 } 1511 }
1526 if (!h) 1512 list_for_each_entry(h, &unconfirmed, list) {
1527 h = LIST_FIND_W(&unconfirmed, do_iter, 1513 ct = nf_ct_tuplehash_to_ctrack(h);
1528 struct nf_conntrack_tuple_hash *, iter, data); 1514 if (iter(ct, data))
1529 if (h) 1515 goto found;
1530 atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); 1516 }
1517 return NULL;
1518found:
1519 atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use);
1531 write_unlock_bh(&nf_conntrack_lock); 1520 write_unlock_bh(&nf_conntrack_lock);
1532 1521 return ct;
1533 return h;
1534} 1522}
1535 1523
1536void 1524void
1537nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data) 1525nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data)
1538{ 1526{
1539 struct nf_conntrack_tuple_hash *h; 1527 struct nf_conn *ct;
1540 unsigned int bucket = 0; 1528 unsigned int bucket = 0;
1541 1529
1542 while ((h = get_next_corpse(iter, data, &bucket)) != NULL) { 1530 while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) {
1543 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
1544 /* Time to push up daises... */ 1531 /* Time to push up daises... */
1545 if (del_timer(&ct->timeout)) 1532 if (del_timer(&ct->timeout))
1546 death_by_timeout((unsigned long)ct); 1533 death_by_timeout((unsigned long)ct);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 9a1de0ca475b..5954f6773810 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -37,7 +37,6 @@
37#include <net/netfilter/nf_conntrack_protocol.h> 37#include <net/netfilter/nf_conntrack_protocol.h>
38#include <net/netfilter/nf_conntrack_core.h> 38#include <net/netfilter/nf_conntrack_core.h>
39#include <net/netfilter/nf_conntrack_helper.h> 39#include <net/netfilter/nf_conntrack_helper.h>
40#include <linux/netfilter_ipv4/listhelp.h>
41 40
42#if 0 41#if 0
43#define DEBUGP printk 42#define DEBUGP printk
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8037ba63d587..be7baf4f6846 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -81,7 +81,7 @@ xt_unregister_target(struct xt_target *target)
81 int af = target->family; 81 int af = target->family;
82 82
83 mutex_lock(&xt[af].mutex); 83 mutex_lock(&xt[af].mutex);
84 LIST_DELETE(&xt[af].target, target); 84 list_del(&target->list);
85 mutex_unlock(&xt[af].mutex); 85 mutex_unlock(&xt[af].mutex);
86} 86}
87EXPORT_SYMBOL(xt_unregister_target); 87EXPORT_SYMBOL(xt_unregister_target);
@@ -138,7 +138,7 @@ xt_unregister_match(struct xt_match *match)
138 int af = match->family; 138 int af = match->family;
139 139
140 mutex_lock(&xt[af].mutex); 140 mutex_lock(&xt[af].mutex);
141 LIST_DELETE(&xt[af].match, match); 141 list_del(&match->list);
142 mutex_unlock(&xt[af].mutex); 142 mutex_unlock(&xt[af].mutex);
143} 143}
144EXPORT_SYMBOL(xt_unregister_match); 144EXPORT_SYMBOL(xt_unregister_match);
@@ -575,15 +575,18 @@ int xt_register_table(struct xt_table *table,
575{ 575{
576 int ret; 576 int ret;
577 struct xt_table_info *private; 577 struct xt_table_info *private;
578 struct xt_table *t;
578 579
579 ret = mutex_lock_interruptible(&xt[table->af].mutex); 580 ret = mutex_lock_interruptible(&xt[table->af].mutex);
580 if (ret != 0) 581 if (ret != 0)
581 return ret; 582 return ret;
582 583
583 /* Don't autoload: we'd eat our tail... */ 584 /* Don't autoload: we'd eat our tail... */
584 if (list_named_find(&xt[table->af].tables, table->name)) { 585 list_for_each_entry(t, &xt[table->af].tables, list) {
585 ret = -EEXIST; 586 if (strcmp(t->name, table->name) == 0) {
586 goto unlock; 587 ret = -EEXIST;
588 goto unlock;
589 }
587 } 590 }
588 591
589 /* Simplifies replace_table code. */ 592 /* Simplifies replace_table code. */
@@ -598,7 +601,7 @@ int xt_register_table(struct xt_table *table,
598 /* save number of initial entries */ 601 /* save number of initial entries */
599 private->initial_entries = private->number; 602 private->initial_entries = private->number;
600 603
601 list_prepend(&xt[table->af].tables, table); 604 list_add(&table->list, &xt[table->af].tables);
602 605
603 ret = 0; 606 ret = 0;
604 unlock: 607 unlock:
@@ -613,7 +616,7 @@ void *xt_unregister_table(struct xt_table *table)
613 616
614 mutex_lock(&xt[table->af].mutex); 617 mutex_lock(&xt[table->af].mutex);
615 private = table->private; 618 private = table->private;
616 LIST_DELETE(&xt[table->af].tables, table); 619 list_del(&table->list);
617 mutex_unlock(&xt[table->af].mutex); 620 mutex_unlock(&xt[table->af].mutex);
618 621
619 return private; 622 return private;