diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2006-03-22 16:56:08 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-22 16:56:08 -0500 |
commit | b9f78f9fca626875af8adc0f7366a38b8e625a0e (patch) | |
tree | 1087c6f6a6cc39e4e55c2a02f93d93da67a68ed3 | |
parent | a45049c51ce6a3fecf2a909b591b28164c927112 (diff) |
[NETFILTER]: nf_conntrack: support for layer 3 protocol load on demand
x_tables matches and targets that require nf_conntrack_ipv[4|6] to work
don't have enough information to load on demand these modules. This
patch introduces the following changes to solve this issue:
o nf_ct_l3proto_try_module_get: try to load the layer 3 connection
tracker module and increases the refcount.
o nf_ct_l3proto_module put: drop the refcount of the module.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/netfilter/nf_conntrack.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 1 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 31 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_standalone.c | 2 | ||||
-rw-r--r-- | net/netfilter/xt_connmark.c | 17 | ||||
-rw-r--r-- | net/netfilter/xt_conntrack.c | 28 | ||||
-rw-r--r-- | net/netfilter/xt_helper.c | 17 | ||||
-rw-r--r-- | net/netfilter/xt_state.c | 29 |
9 files changed, 130 insertions, 0 deletions
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 2743c156caa0..b6f0905a4ee2 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -195,6 +195,10 @@ static inline void nf_ct_put(struct nf_conn *ct) | |||
195 | nf_conntrack_put(&ct->ct_general); | 195 | nf_conntrack_put(&ct->ct_general); |
196 | } | 196 | } |
197 | 197 | ||
198 | /* Protocol module loading */ | ||
199 | extern int nf_ct_l3proto_try_module_get(unsigned short l3proto); | ||
200 | extern void nf_ct_l3proto_module_put(unsigned short l3proto); | ||
201 | |||
198 | extern struct nf_conntrack_tuple_hash * | 202 | extern struct nf_conntrack_tuple_hash * |
199 | __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, | 203 | __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, |
200 | const struct nf_conn *ignored_conntrack); | 204 | const struct nf_conn *ignored_conntrack); |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index cb9c661f3f33..c8abc9d859b9 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -568,6 +568,7 @@ static int init_or_cleanup(int init) | |||
568 | return ret; | 568 | return ret; |
569 | } | 569 | } |
570 | 570 | ||
571 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET)); | ||
571 | MODULE_LICENSE("GPL"); | 572 | MODULE_LICENSE("GPL"); |
572 | 573 | ||
573 | static int __init init(void) | 574 | static int __init init(void) |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index ac35f9526368..c16f62934bd9 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -584,6 +584,7 @@ static int init_or_cleanup(int init) | |||
584 | return ret; | 584 | return ret; |
585 | } | 585 | } |
586 | 586 | ||
587 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | ||
587 | MODULE_LICENSE("GPL"); | 588 | MODULE_LICENSE("GPL"); |
588 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | 589 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); |
589 | 590 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index c28840656451..0ae281d9bfc3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -23,6 +23,8 @@ | |||
23 | * 26 Jan 2006: Harald Welte <laforge@netfilter.org> | 23 | * 26 Jan 2006: Harald Welte <laforge@netfilter.org> |
24 | * - restructure nf_conn (introduce nf_conn_help) | 24 | * - restructure nf_conn (introduce nf_conn_help) |
25 | * - redesign 'features' how they were originally intended | 25 | * - redesign 'features' how they were originally intended |
26 | * 26 Feb 2006: Pablo Neira Ayuso <pablo@eurodev.net> | ||
27 | * - add support for L3 protocol module load on demand. | ||
26 | * | 28 | * |
27 | * Derived from net/ipv4/netfilter/ip_conntrack_core.c | 29 | * Derived from net/ipv4/netfilter/ip_conntrack_core.c |
28 | */ | 30 | */ |
@@ -241,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) | |||
241 | module_put(p->me); | 243 | module_put(p->me); |
242 | } | 244 | } |
243 | 245 | ||
246 | int | ||
247 | nf_ct_l3proto_try_module_get(unsigned short l3proto) | ||
248 | { | ||
249 | int ret; | ||
250 | struct nf_conntrack_l3proto *p; | ||
251 | |||
252 | retry: p = nf_ct_l3proto_find_get(l3proto); | ||
253 | if (p == &nf_conntrack_generic_l3proto) { | ||
254 | ret = request_module("nf_conntrack-%d", l3proto); | ||
255 | if (!ret) | ||
256 | goto retry; | ||
257 | |||
258 | return -EPROTOTYPE; | ||
259 | } | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | void nf_ct_l3proto_module_put(unsigned short l3proto) | ||
265 | { | ||
266 | struct nf_conntrack_l3proto *p; | ||
267 | |||
268 | preempt_disable(); | ||
269 | p = __nf_ct_l3proto_find(l3proto); | ||
270 | preempt_enable(); | ||
271 | |||
272 | module_put(p->me); | ||
273 | } | ||
274 | |||
244 | static int nf_conntrack_hash_rnd_initted; | 275 | static int nf_conntrack_hash_rnd_initted; |
245 | static unsigned int nf_conntrack_hash_rnd; | 276 | static unsigned int nf_conntrack_hash_rnd; |
246 | 277 | ||
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 290d5a0c559b..75577e175b35 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -834,6 +834,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); | |||
834 | EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); | 834 | EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); |
835 | EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); | 835 | EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); |
836 | #endif | 836 | #endif |
837 | EXPORT_SYMBOL(nf_ct_l3proto_try_module_get); | ||
838 | EXPORT_SYMBOL(nf_ct_l3proto_module_put); | ||
837 | EXPORT_SYMBOL(nf_conntrack_l3proto_register); | 839 | EXPORT_SYMBOL(nf_conntrack_l3proto_register); |
838 | EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); | 840 | EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); |
839 | EXPORT_SYMBOL(nf_conntrack_protocol_register); | 841 | EXPORT_SYMBOL(nf_conntrack_protocol_register); |
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c index e810600345e3..7b16f1ee16b4 100644 --- a/net/netfilter/xt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -64,14 +64,30 @@ checkentry(const char *tablename, | |||
64 | printk(KERN_WARNING "connmark: only support 32bit mark\n"); | 64 | printk(KERN_WARNING "connmark: only support 32bit mark\n"); |
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
68 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
69 | printk(KERN_WARNING "can't load nf_conntrack support for " | ||
70 | "proto=%d\n", match->family); | ||
71 | return 0; | ||
72 | } | ||
73 | #endif | ||
67 | return 1; | 74 | return 1; |
68 | } | 75 | } |
69 | 76 | ||
77 | static void | ||
78 | destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) | ||
79 | { | ||
80 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
81 | nf_ct_l3proto_module_put(match->family); | ||
82 | #endif | ||
83 | } | ||
84 | |||
70 | static struct xt_match connmark_match = { | 85 | static struct xt_match connmark_match = { |
71 | .name = "connmark", | 86 | .name = "connmark", |
72 | .match = match, | 87 | .match = match, |
73 | .matchsize = sizeof(struct xt_connmark_info), | 88 | .matchsize = sizeof(struct xt_connmark_info), |
74 | .checkentry = checkentry, | 89 | .checkentry = checkentry, |
90 | .destroy = destroy, | ||
75 | .family = AF_INET, | 91 | .family = AF_INET, |
76 | .me = THIS_MODULE | 92 | .me = THIS_MODULE |
77 | }; | 93 | }; |
@@ -81,6 +97,7 @@ static struct xt_match connmark6_match = { | |||
81 | .match = match, | 97 | .match = match, |
82 | .matchsize = sizeof(struct xt_connmark_info), | 98 | .matchsize = sizeof(struct xt_connmark_info), |
83 | .checkentry = checkentry, | 99 | .checkentry = checkentry, |
100 | .destroy = destroy, | ||
84 | .family = AF_INET6, | 101 | .family = AF_INET6, |
85 | .me = THIS_MODULE | 102 | .me = THIS_MODULE |
86 | }; | 103 | }; |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 7d20caa0d605..65a84809fd30 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -203,9 +203,37 @@ match(const struct sk_buff *skb, | |||
203 | 203 | ||
204 | #endif /* CONFIG_NF_IP_CONNTRACK */ | 204 | #endif /* CONFIG_NF_IP_CONNTRACK */ |
205 | 205 | ||
206 | static int | ||
207 | checkentry(const char *tablename, | ||
208 | const void *ip, | ||
209 | const struct xt_match *match, | ||
210 | void *matchinfo, | ||
211 | unsigned int matchsize, | ||
212 | unsigned int hook_mask) | ||
213 | { | ||
214 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
215 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
216 | printk(KERN_WARNING "can't load nf_conntrack support for " | ||
217 | "proto=%d\n", match->family); | ||
218 | return 0; | ||
219 | } | ||
220 | #endif | ||
221 | return 1; | ||
222 | } | ||
223 | |||
224 | static void | ||
225 | destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) | ||
226 | { | ||
227 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
228 | nf_ct_l3proto_module_put(match->family); | ||
229 | #endif | ||
230 | } | ||
231 | |||
206 | static struct xt_match conntrack_match = { | 232 | static struct xt_match conntrack_match = { |
207 | .name = "conntrack", | 233 | .name = "conntrack", |
208 | .match = match, | 234 | .match = match, |
235 | .checkentry = checkentry, | ||
236 | .destroy = destroy, | ||
209 | .matchsize = sizeof(struct xt_conntrack_info), | 237 | .matchsize = sizeof(struct xt_conntrack_info), |
210 | .family = AF_INET, | 238 | .family = AF_INET, |
211 | .me = THIS_MODULE, | 239 | .me = THIS_MODULE, |
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 7d2d68b9155f..101f0005e987 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c | |||
@@ -144,15 +144,31 @@ static int check(const char *tablename, | |||
144 | { | 144 | { |
145 | struct xt_helper_info *info = matchinfo; | 145 | struct xt_helper_info *info = matchinfo; |
146 | 146 | ||
147 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
148 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
149 | printk(KERN_WARNING "can't load nf_conntrack support for " | ||
150 | "proto=%d\n", match->family); | ||
151 | return 0; | ||
152 | } | ||
153 | #endif | ||
147 | info->name[29] = '\0'; | 154 | info->name[29] = '\0'; |
148 | return 1; | 155 | return 1; |
149 | } | 156 | } |
150 | 157 | ||
158 | static void | ||
159 | destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) | ||
160 | { | ||
161 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
162 | nf_ct_l3proto_module_put(match->family); | ||
163 | #endif | ||
164 | } | ||
165 | |||
151 | static struct xt_match helper_match = { | 166 | static struct xt_match helper_match = { |
152 | .name = "helper", | 167 | .name = "helper", |
153 | .match = match, | 168 | .match = match, |
154 | .matchsize = sizeof(struct xt_helper_info), | 169 | .matchsize = sizeof(struct xt_helper_info), |
155 | .checkentry = check, | 170 | .checkentry = check, |
171 | .destroy = destroy, | ||
156 | .family = AF_INET, | 172 | .family = AF_INET, |
157 | .me = THIS_MODULE, | 173 | .me = THIS_MODULE, |
158 | }; | 174 | }; |
@@ -161,6 +177,7 @@ static struct xt_match helper6_match = { | |||
161 | .match = match, | 177 | .match = match, |
162 | .matchsize = sizeof(struct xt_helper_info), | 178 | .matchsize = sizeof(struct xt_helper_info), |
163 | .checkentry = check, | 179 | .checkentry = check, |
180 | .destroy = destroy, | ||
164 | .family = AF_INET6, | 181 | .family = AF_INET6, |
165 | .me = THIS_MODULE, | 182 | .me = THIS_MODULE, |
166 | }; | 183 | }; |
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c index 7cd557c932ba..e6c0be9d94d2 100644 --- a/net/netfilter/xt_state.c +++ b/net/netfilter/xt_state.c | |||
@@ -44,9 +44,36 @@ match(const struct sk_buff *skb, | |||
44 | return (sinfo->statemask & statebit); | 44 | return (sinfo->statemask & statebit); |
45 | } | 45 | } |
46 | 46 | ||
47 | static int check(const char *tablename, | ||
48 | const void *inf, | ||
49 | const struct xt_match *match, | ||
50 | void *matchinfo, | ||
51 | unsigned int matchsize, | ||
52 | unsigned int hook_mask) | ||
53 | { | ||
54 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
55 | if (nf_ct_l3proto_try_module_get(match->family) < 0) { | ||
56 | printk(KERN_WARNING "can't load nf_conntrack support for " | ||
57 | "proto=%d\n", match->family); | ||
58 | return 0; | ||
59 | } | ||
60 | #endif | ||
61 | return 1; | ||
62 | } | ||
63 | |||
64 | static void | ||
65 | destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) | ||
66 | { | ||
67 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | ||
68 | nf_ct_l3proto_module_put(match->family); | ||
69 | #endif | ||
70 | } | ||
71 | |||
47 | static struct xt_match state_match = { | 72 | static struct xt_match state_match = { |
48 | .name = "state", | 73 | .name = "state", |
49 | .match = match, | 74 | .match = match, |
75 | .checkentry = check, | ||
76 | .destroy = destroy, | ||
50 | .matchsize = sizeof(struct xt_state_info), | 77 | .matchsize = sizeof(struct xt_state_info), |
51 | .family = AF_INET, | 78 | .family = AF_INET, |
52 | .me = THIS_MODULE, | 79 | .me = THIS_MODULE, |
@@ -55,6 +82,8 @@ static struct xt_match state_match = { | |||
55 | static struct xt_match state6_match = { | 82 | static struct xt_match state6_match = { |
56 | .name = "state", | 83 | .name = "state", |
57 | .match = match, | 84 | .match = match, |
85 | .checkentry = check, | ||
86 | .destroy = destroy, | ||
58 | .matchsize = sizeof(struct xt_state_info), | 87 | .matchsize = sizeof(struct xt_state_info), |
59 | .family = AF_INET6, | 88 | .family = AF_INET6, |
60 | .me = THIS_MODULE, | 89 | .me = THIS_MODULE, |