aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2006-03-22 16:56:08 -0500
committerDavid S. Miller <davem@davemloft.net>2006-03-22 16:56:08 -0500
commitb9f78f9fca626875af8adc0f7366a38b8e625a0e (patch)
tree1087c6f6a6cc39e4e55c2a02f93d93da67a68ed3
parenta45049c51ce6a3fecf2a909b591b28164c927112 (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.h4
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c1
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c1
-rw-r--r--net/netfilter/nf_conntrack_core.c31
-rw-r--r--net/netfilter/nf_conntrack_standalone.c2
-rw-r--r--net/netfilter/xt_connmark.c17
-rw-r--r--net/netfilter/xt_conntrack.c28
-rw-r--r--net/netfilter/xt_helper.c17
-rw-r--r--net/netfilter/xt_state.c29
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 */
199extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
200extern void nf_ct_l3proto_module_put(unsigned short l3proto);
201
198extern struct nf_conntrack_tuple_hash * 202extern 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
571MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
571MODULE_LICENSE("GPL"); 572MODULE_LICENSE("GPL");
572 573
573static int __init init(void) 574static 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
587MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
587MODULE_LICENSE("GPL"); 588MODULE_LICENSE("GPL");
588MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); 589MODULE_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
246int
247nf_ct_l3proto_try_module_get(unsigned short l3proto)
248{
249 int ret;
250 struct nf_conntrack_l3proto *p;
251
252retry: 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
264void 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
244static int nf_conntrack_hash_rnd_initted; 275static int nf_conntrack_hash_rnd_initted;
245static unsigned int nf_conntrack_hash_rnd; 276static 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);
834EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); 834EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
835EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); 835EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
836#endif 836#endif
837EXPORT_SYMBOL(nf_ct_l3proto_try_module_get);
838EXPORT_SYMBOL(nf_ct_l3proto_module_put);
837EXPORT_SYMBOL(nf_conntrack_l3proto_register); 839EXPORT_SYMBOL(nf_conntrack_l3proto_register);
838EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); 840EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
839EXPORT_SYMBOL(nf_conntrack_protocol_register); 841EXPORT_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
77static void
78destroy(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
70static struct xt_match connmark_match = { 85static 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
206static int
207checkentry(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
224static void
225destroy(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
206static struct xt_match conntrack_match = { 232static 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
158static void
159destroy(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
151static struct xt_match helper_match = { 166static 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
47static 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
64static void
65destroy(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
47static struct xt_match state_match = { 72static 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 = {
55static struct xt_match state6_match = { 82static 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,