aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Josefsson <gandalf@wlug.westbo.se>2006-11-28 20:35:03 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:07 -0500
commit8f03dea52b1d0227656319e1b0822628b43791a8 (patch)
tree51517b728d7d465c82e2143f1a28ddd1319911d7
parentf61801218a58381f498ae5c38ae3eae0bc73e976 (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/Makefile2
-rw-r--r--net/netfilter/nf_conntrack_core.c81
-rw-r--r--net/netfilter/nf_conntrack_proto.c225
-rw-r--r--net/netfilter/nf_conntrack_standalone.c116
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 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2 2
3nf_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 3nf_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
4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o 4nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
5 5
6obj-$(CONFIG_NETFILTER) = netfilter.o 6obj-$(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);
73atomic_t nf_conntrack_count = ATOMIC_INIT(0); 73atomic_t nf_conntrack_count = ATOMIC_INIT(0);
74 74
75void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; 75void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL;
76struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
77struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
78unsigned int nf_conntrack_htable_size __read_mostly = 0; 76unsigned int nf_conntrack_htable_size __read_mostly = 0;
79int nf_conntrack_max __read_mostly; 77int nf_conntrack_max __read_mostly;
80struct list_head *nf_conntrack_hash __read_mostly; 78struct 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 */
116static DEFINE_MUTEX(nf_ct_cache_mutex); 114static DEFINE_MUTEX(nf_ct_cache_mutex);
117 115
118extern struct nf_conntrack_protocol nf_conntrack_generic_protocol;
119struct 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 */
130struct nf_conntrack_protocol *
131nf_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
144void nf_ct_proto_put(struct nf_conntrack_protocol *p)
145{
146 module_put(p->me);
147}
148
149struct nf_conntrack_l3proto *
150nf_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
163void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
164{
165 module_put(p->me);
166}
167
168int
169nf_ct_l3proto_try_module_get(unsigned short l3proto)
170{
171 int ret;
172 struct nf_conntrack_l3proto *p;
173
174retry: 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
186void 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
197static int nf_conntrack_hash_rnd_initted; 116static int nf_conntrack_hash_rnd_initted;
198static unsigned int nf_conntrack_hash_rnd; 117static 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
30struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly;
31struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly;
32
33struct 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 */
44struct nf_conntrack_protocol *
45nf_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
58void nf_ct_proto_put(struct nf_conntrack_protocol *p)
59{
60 module_put(p->me);
61}
62
63struct nf_conntrack_l3proto *
64nf_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
77void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
78{
79 module_put(p->me);
80}
81
82int
83nf_ct_l3proto_try_module_get(unsigned short l3proto)
84{
85 int ret;
86 struct nf_conntrack_l3proto *p;
87
88retry: 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
100void 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
111static 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
117static 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
127int 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;
137out:
138 write_unlock_bh(&nf_conntrack_lock);
139
140 return ret;
141}
142
143void 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 */
158int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
159{
160 int ret = 0;
161
162retry:
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
207out_unlock:
208 write_unlock_bh(&nf_conntrack_lock);
209out:
210 return ret;
211}
212
213void 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");
50extern atomic_t nf_conntrack_count; 50extern atomic_t nf_conntrack_count;
51DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); 51DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat);
52 52
53static 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
59static 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
70int 54int
71print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, 55print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
@@ -585,106 +569,6 @@ static ctl_table nf_ct_net_table[] = {
585EXPORT_SYMBOL(nf_ct_log_invalid); 569EXPORT_SYMBOL(nf_ct_log_invalid);
586#endif /* CONFIG_SYSCTL */ 570#endif /* CONFIG_SYSCTL */
587 571
588int 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;
598out:
599 write_unlock_bh(&nf_conntrack_lock);
600
601 return ret;
602}
603
604void 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 */
619int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto)
620{
621 int ret = 0;
622
623retry:
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
668out_unlock:
669 write_unlock_bh(&nf_conntrack_lock);
670out:
671 return ret;
672}
673
674void 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
688static int __init nf_conntrack_standalone_init(void) 572static int __init nf_conntrack_standalone_init(void)
689{ 573{
690#ifdef CONFIG_PROC_FS 574#ifdef CONFIG_PROC_FS