diff options
author | Martin Josefsson <gandalf@wlug.westbo.se> | 2006-11-28 20:35:03 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:07 -0500 |
commit | 8f03dea52b1d0227656319e1b0822628b43791a8 (patch) | |
tree | 51517b728d7d465c82e2143f1a28ddd1319911d7 | |
parent | f61801218a58381f498ae5c38ae3eae0bc73e976 (diff) |
[NETFILTER]: nf_conntrack: split out protocol handling
This patch splits out L3/L4 protocol handling into its own file
nf_conntrack_proto.c
Signed-off-by: Martin Josefsson <gandalf@wlug.westbo.se>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | net/netfilter/Makefile | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 81 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto.c | 225 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_standalone.c | 116 |
4 files changed, 226 insertions, 198 deletions
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index fd0641d6679a..627105df1040 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | 2 | ||
3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | 3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o |
4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o | 4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o |
5 | 5 | ||
6 | obj-$(CONFIG_NETFILTER) = netfilter.o | 6 | obj-$(CONFIG_NETFILTER) = netfilter.o |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 029acc4f9643..09c0e6311044 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -73,8 +73,6 @@ DEFINE_RWLOCK(nf_conntrack_lock); | |||
73 | atomic_t nf_conntrack_count = ATOMIC_INIT(0); | 73 | atomic_t nf_conntrack_count = ATOMIC_INIT(0); |
74 | 74 | ||
75 | void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; | 75 | void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; |
76 | struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; | ||
77 | struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; | ||
78 | unsigned int nf_conntrack_htable_size __read_mostly = 0; | 76 | unsigned int nf_conntrack_htable_size __read_mostly = 0; |
79 | int nf_conntrack_max __read_mostly; | 77 | int nf_conntrack_max __read_mostly; |
80 | struct list_head *nf_conntrack_hash __read_mostly; | 78 | struct list_head *nf_conntrack_hash __read_mostly; |
@@ -115,85 +113,6 @@ DEFINE_RWLOCK(nf_ct_cache_lock); | |||
115 | /* This avoids calling kmem_cache_create() with same name simultaneously */ | 113 | /* This avoids calling kmem_cache_create() with same name simultaneously */ |
116 | static DEFINE_MUTEX(nf_ct_cache_mutex); | 114 | static DEFINE_MUTEX(nf_ct_cache_mutex); |
117 | 115 | ||
118 | extern struct nf_conntrack_protocol nf_conntrack_generic_protocol; | ||
119 | struct nf_conntrack_protocol * | ||
120 | __nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) | ||
121 | { | ||
122 | if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) | ||
123 | return &nf_conntrack_generic_protocol; | ||
124 | |||
125 | return nf_ct_protos[l3proto][protocol]; | ||
126 | } | ||
127 | |||
128 | /* this is guaranteed to always return a valid protocol helper, since | ||
129 | * it falls back to generic_protocol */ | ||
130 | struct nf_conntrack_protocol * | ||
131 | nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) | ||
132 | { | ||
133 | struct nf_conntrack_protocol *p; | ||
134 | |||
135 | preempt_disable(); | ||
136 | p = __nf_ct_proto_find(l3proto, protocol); | ||
137 | if (!try_module_get(p->me)) | ||
138 | p = &nf_conntrack_generic_protocol; | ||
139 | preempt_enable(); | ||
140 | |||
141 | return p; | ||
142 | } | ||
143 | |||
144 | void nf_ct_proto_put(struct nf_conntrack_protocol *p) | ||
145 | { | ||
146 | module_put(p->me); | ||
147 | } | ||
148 | |||
149 | struct nf_conntrack_l3proto * | ||
150 | nf_ct_l3proto_find_get(u_int16_t l3proto) | ||
151 | { | ||
152 | struct nf_conntrack_l3proto *p; | ||
153 | |||
154 | preempt_disable(); | ||
155 | p = __nf_ct_l3proto_find(l3proto); | ||
156 | if (!try_module_get(p->me)) | ||
157 | p = &nf_conntrack_generic_l3proto; | ||
158 | preempt_enable(); | ||
159 | |||
160 | return p; | ||
161 | } | ||
162 | |||
163 | void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) | ||
164 | { | ||
165 | module_put(p->me); | ||
166 | } | ||
167 | |||
168 | int | ||
169 | nf_ct_l3proto_try_module_get(unsigned short l3proto) | ||
170 | { | ||
171 | int ret; | ||
172 | struct nf_conntrack_l3proto *p; | ||
173 | |||
174 | retry: p = nf_ct_l3proto_find_get(l3proto); | ||
175 | if (p == &nf_conntrack_generic_l3proto) { | ||
176 | ret = request_module("nf_conntrack-%d", l3proto); | ||
177 | if (!ret) | ||
178 | goto retry; | ||
179 | |||
180 | return -EPROTOTYPE; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | void nf_ct_l3proto_module_put(unsigned short l3proto) | ||
187 | { | ||
188 | struct nf_conntrack_l3proto *p; | ||
189 | |||
190 | preempt_disable(); | ||
191 | p = __nf_ct_l3proto_find(l3proto); | ||
192 | preempt_enable(); | ||
193 | |||
194 | module_put(p->me); | ||
195 | } | ||
196 | |||
197 | static int nf_conntrack_hash_rnd_initted; | 116 | static int nf_conntrack_hash_rnd_initted; |
198 | static unsigned int nf_conntrack_hash_rnd; | 117 | static unsigned int nf_conntrack_hash_rnd; |
199 | 118 | ||
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c new file mode 100644 index 000000000000..24c61a384716 --- /dev/null +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* L3/L4 protocol support for nf_conntrack. */ | ||
2 | |||
3 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
4 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
5 | * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/vmalloc.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/err.h> | ||
19 | #include <linux/percpu.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/notifier.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/netdevice.h> | ||
24 | |||
25 | #include <net/netfilter/nf_conntrack.h> | ||
26 | #include <net/netfilter/nf_conntrack_l3proto.h> | ||
27 | #include <net/netfilter/nf_conntrack_protocol.h> | ||
28 | #include <net/netfilter/nf_conntrack_core.h> | ||
29 | |||
30 | struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; | ||
31 | struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; | ||
32 | |||
33 | struct nf_conntrack_protocol * | ||
34 | __nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol) | ||
35 | { | ||
36 | if (unlikely(l3proto >= AF_MAX || nf_ct_protos[l3proto] == NULL)) | ||
37 | return &nf_conntrack_generic_protocol; | ||
38 | |||
39 | return nf_ct_protos[l3proto][protocol]; | ||
40 | } | ||
41 | |||
42 | /* this is guaranteed to always return a valid protocol helper, since | ||
43 | * it falls back to generic_protocol */ | ||
44 | struct nf_conntrack_protocol * | ||
45 | nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) | ||
46 | { | ||
47 | struct nf_conntrack_protocol *p; | ||
48 | |||
49 | preempt_disable(); | ||
50 | p = __nf_ct_proto_find(l3proto, protocol); | ||
51 | if (!try_module_get(p->me)) | ||
52 | p = &nf_conntrack_generic_protocol; | ||
53 | preempt_enable(); | ||
54 | |||
55 | return p; | ||
56 | } | ||
57 | |||
58 | void nf_ct_proto_put(struct nf_conntrack_protocol *p) | ||
59 | { | ||
60 | module_put(p->me); | ||
61 | } | ||
62 | |||
63 | struct nf_conntrack_l3proto * | ||
64 | nf_ct_l3proto_find_get(u_int16_t l3proto) | ||
65 | { | ||
66 | struct nf_conntrack_l3proto *p; | ||
67 | |||
68 | preempt_disable(); | ||
69 | p = __nf_ct_l3proto_find(l3proto); | ||
70 | if (!try_module_get(p->me)) | ||
71 | p = &nf_conntrack_generic_l3proto; | ||
72 | preempt_enable(); | ||
73 | |||
74 | return p; | ||
75 | } | ||
76 | |||
77 | void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) | ||
78 | { | ||
79 | module_put(p->me); | ||
80 | } | ||
81 | |||
82 | int | ||
83 | nf_ct_l3proto_try_module_get(unsigned short l3proto) | ||
84 | { | ||
85 | int ret; | ||
86 | struct nf_conntrack_l3proto *p; | ||
87 | |||
88 | retry: p = nf_ct_l3proto_find_get(l3proto); | ||
89 | if (p == &nf_conntrack_generic_l3proto) { | ||
90 | ret = request_module("nf_conntrack-%d", l3proto); | ||
91 | if (!ret) | ||
92 | goto retry; | ||
93 | |||
94 | return -EPROTOTYPE; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | void nf_ct_l3proto_module_put(unsigned short l3proto) | ||
101 | { | ||
102 | struct nf_conntrack_l3proto *p; | ||
103 | |||
104 | preempt_disable(); | ||
105 | p = __nf_ct_l3proto_find(l3proto); | ||
106 | preempt_enable(); | ||
107 | |||
108 | module_put(p->me); | ||
109 | } | ||
110 | |||
111 | static int kill_l3proto(struct nf_conn *i, void *data) | ||
112 | { | ||
113 | return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == | ||
114 | ((struct nf_conntrack_l3proto *)data)->l3proto); | ||
115 | } | ||
116 | |||
117 | static int kill_proto(struct nf_conn *i, void *data) | ||
118 | { | ||
119 | struct nf_conntrack_protocol *proto; | ||
120 | proto = (struct nf_conntrack_protocol *)data; | ||
121 | return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == | ||
122 | proto->proto) && | ||
123 | (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == | ||
124 | proto->l3proto); | ||
125 | } | ||
126 | |||
127 | int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | ||
128 | { | ||
129 | int ret = 0; | ||
130 | |||
131 | write_lock_bh(&nf_conntrack_lock); | ||
132 | if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) { | ||
133 | ret = -EBUSY; | ||
134 | goto out; | ||
135 | } | ||
136 | nf_ct_l3protos[proto->l3proto] = proto; | ||
137 | out: | ||
138 | write_unlock_bh(&nf_conntrack_lock); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) | ||
144 | { | ||
145 | write_lock_bh(&nf_conntrack_lock); | ||
146 | nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto; | ||
147 | write_unlock_bh(&nf_conntrack_lock); | ||
148 | |||
149 | /* Somebody could be still looking at the proto in bh. */ | ||
150 | synchronize_net(); | ||
151 | |||
152 | /* Remove all contrack entries for this protocol */ | ||
153 | nf_ct_iterate_cleanup(kill_l3proto, proto); | ||
154 | } | ||
155 | |||
156 | /* FIXME: Allow NULL functions and sub in pointers to generic for | ||
157 | them. --RR */ | ||
158 | int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto) | ||
159 | { | ||
160 | int ret = 0; | ||
161 | |||
162 | retry: | ||
163 | write_lock_bh(&nf_conntrack_lock); | ||
164 | if (nf_ct_protos[proto->l3proto]) { | ||
165 | if (nf_ct_protos[proto->l3proto][proto->proto] | ||
166 | != &nf_conntrack_generic_protocol) { | ||
167 | ret = -EBUSY; | ||
168 | goto out_unlock; | ||
169 | } | ||
170 | } else { | ||
171 | /* l3proto may be loaded latter. */ | ||
172 | struct nf_conntrack_protocol **proto_array; | ||
173 | int i; | ||
174 | |||
175 | write_unlock_bh(&nf_conntrack_lock); | ||
176 | |||
177 | proto_array = (struct nf_conntrack_protocol **) | ||
178 | kmalloc(MAX_NF_CT_PROTO * | ||
179 | sizeof(struct nf_conntrack_protocol *), | ||
180 | GFP_KERNEL); | ||
181 | if (proto_array == NULL) { | ||
182 | ret = -ENOMEM; | ||
183 | goto out; | ||
184 | } | ||
185 | for (i = 0; i < MAX_NF_CT_PROTO; i++) | ||
186 | proto_array[i] = &nf_conntrack_generic_protocol; | ||
187 | |||
188 | write_lock_bh(&nf_conntrack_lock); | ||
189 | if (nf_ct_protos[proto->l3proto]) { | ||
190 | /* bad timing, but no problem */ | ||
191 | write_unlock_bh(&nf_conntrack_lock); | ||
192 | kfree(proto_array); | ||
193 | } else { | ||
194 | nf_ct_protos[proto->l3proto] = proto_array; | ||
195 | write_unlock_bh(&nf_conntrack_lock); | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * Just once because array is never freed until unloading | ||
200 | * nf_conntrack.ko | ||
201 | */ | ||
202 | goto retry; | ||
203 | } | ||
204 | |||
205 | nf_ct_protos[proto->l3proto][proto->proto] = proto; | ||
206 | |||
207 | out_unlock: | ||
208 | write_unlock_bh(&nf_conntrack_lock); | ||
209 | out: | ||
210 | return ret; | ||
211 | } | ||
212 | |||
213 | void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) | ||
214 | { | ||
215 | write_lock_bh(&nf_conntrack_lock); | ||
216 | nf_ct_protos[proto->l3proto][proto->proto] | ||
217 | = &nf_conntrack_generic_protocol; | ||
218 | write_unlock_bh(&nf_conntrack_lock); | ||
219 | |||
220 | /* Somebody could be still looking at the proto in bh. */ | ||
221 | synchronize_net(); | ||
222 | |||
223 | /* Remove all contrack entries for this protocol */ | ||
224 | nf_ct_iterate_cleanup(kill_proto, proto); | ||
225 | } | ||
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 73ca156bb098..eb031d20e510 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -50,22 +50,6 @@ MODULE_LICENSE("GPL"); | |||
50 | extern atomic_t nf_conntrack_count; | 50 | extern atomic_t nf_conntrack_count; |
51 | DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); | 51 | DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); |
52 | 52 | ||
53 | static int kill_l3proto(struct nf_conn *i, void *data) | ||
54 | { | ||
55 | return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == | ||
56 | ((struct nf_conntrack_l3proto *)data)->l3proto); | ||
57 | } | ||
58 | |||
59 | static int kill_proto(struct nf_conn *i, void *data) | ||
60 | { | ||
61 | struct nf_conntrack_protocol *proto; | ||
62 | proto = (struct nf_conntrack_protocol *)data; | ||
63 | return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == | ||
64 | proto->proto) && | ||
65 | (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num == | ||
66 | proto->l3proto); | ||
67 | } | ||
68 | |||
69 | #ifdef CONFIG_PROC_FS | 53 | #ifdef CONFIG_PROC_FS |
70 | int | 54 | int |
71 | print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, | 55 | print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, |
@@ -585,106 +569,6 @@ static ctl_table nf_ct_net_table[] = { | |||
585 | EXPORT_SYMBOL(nf_ct_log_invalid); | 569 | EXPORT_SYMBOL(nf_ct_log_invalid); |
586 | #endif /* CONFIG_SYSCTL */ | 570 | #endif /* CONFIG_SYSCTL */ |
587 | 571 | ||
588 | int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) | ||
589 | { | ||
590 | int ret = 0; | ||
591 | |||
592 | write_lock_bh(&nf_conntrack_lock); | ||
593 | if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_generic_l3proto) { | ||
594 | ret = -EBUSY; | ||
595 | goto out; | ||
596 | } | ||
597 | nf_ct_l3protos[proto->l3proto] = proto; | ||
598 | out: | ||
599 | write_unlock_bh(&nf_conntrack_lock); | ||
600 | |||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) | ||
605 | { | ||
606 | write_lock_bh(&nf_conntrack_lock); | ||
607 | nf_ct_l3protos[proto->l3proto] = &nf_conntrack_generic_l3proto; | ||
608 | write_unlock_bh(&nf_conntrack_lock); | ||
609 | |||
610 | /* Somebody could be still looking at the proto in bh. */ | ||
611 | synchronize_net(); | ||
612 | |||
613 | /* Remove all contrack entries for this protocol */ | ||
614 | nf_ct_iterate_cleanup(kill_l3proto, proto); | ||
615 | } | ||
616 | |||
617 | /* FIXME: Allow NULL functions and sub in pointers to generic for | ||
618 | them. --RR */ | ||
619 | int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto) | ||
620 | { | ||
621 | int ret = 0; | ||
622 | |||
623 | retry: | ||
624 | write_lock_bh(&nf_conntrack_lock); | ||
625 | if (nf_ct_protos[proto->l3proto]) { | ||
626 | if (nf_ct_protos[proto->l3proto][proto->proto] | ||
627 | != &nf_conntrack_generic_protocol) { | ||
628 | ret = -EBUSY; | ||
629 | goto out_unlock; | ||
630 | } | ||
631 | } else { | ||
632 | /* l3proto may be loaded latter. */ | ||
633 | struct nf_conntrack_protocol **proto_array; | ||
634 | int i; | ||
635 | |||
636 | write_unlock_bh(&nf_conntrack_lock); | ||
637 | |||
638 | proto_array = (struct nf_conntrack_protocol **) | ||
639 | kmalloc(MAX_NF_CT_PROTO * | ||
640 | sizeof(struct nf_conntrack_protocol *), | ||
641 | GFP_KERNEL); | ||
642 | if (proto_array == NULL) { | ||
643 | ret = -ENOMEM; | ||
644 | goto out; | ||
645 | } | ||
646 | for (i = 0; i < MAX_NF_CT_PROTO; i++) | ||
647 | proto_array[i] = &nf_conntrack_generic_protocol; | ||
648 | |||
649 | write_lock_bh(&nf_conntrack_lock); | ||
650 | if (nf_ct_protos[proto->l3proto]) { | ||
651 | /* bad timing, but no problem */ | ||
652 | write_unlock_bh(&nf_conntrack_lock); | ||
653 | kfree(proto_array); | ||
654 | } else { | ||
655 | nf_ct_protos[proto->l3proto] = proto_array; | ||
656 | write_unlock_bh(&nf_conntrack_lock); | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * Just once because array is never freed until unloading | ||
661 | * nf_conntrack.ko | ||
662 | */ | ||
663 | goto retry; | ||
664 | } | ||
665 | |||
666 | nf_ct_protos[proto->l3proto][proto->proto] = proto; | ||
667 | |||
668 | out_unlock: | ||
669 | write_unlock_bh(&nf_conntrack_lock); | ||
670 | out: | ||
671 | return ret; | ||
672 | } | ||
673 | |||
674 | void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto) | ||
675 | { | ||
676 | write_lock_bh(&nf_conntrack_lock); | ||
677 | nf_ct_protos[proto->l3proto][proto->proto] | ||
678 | = &nf_conntrack_generic_protocol; | ||
679 | write_unlock_bh(&nf_conntrack_lock); | ||
680 | |||
681 | /* Somebody could be still looking at the proto in bh. */ | ||
682 | synchronize_net(); | ||
683 | |||
684 | /* Remove all contrack entries for this protocol */ | ||
685 | nf_ct_iterate_cleanup(kill_proto, proto); | ||
686 | } | ||
687 | |||
688 | static int __init nf_conntrack_standalone_init(void) | 572 | static int __init nf_conntrack_standalone_init(void) |
689 | { | 573 | { |
690 | #ifdef CONFIG_PROC_FS | 574 | #ifdef CONFIG_PROC_FS |