Commit b9f78f9f authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller

[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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a45049c5
...@@ -195,6 +195,10 @@ static inline void nf_ct_put(struct nf_conn *ct) ...@@ -195,6 +195,10 @@ static inline void nf_ct_put(struct nf_conn *ct)
nf_conntrack_put(&ct->ct_general); nf_conntrack_put(&ct->ct_general);
} }
/* Protocol module loading */
extern int nf_ct_l3proto_try_module_get(unsigned short l3proto);
extern void nf_ct_l3proto_module_put(unsigned short l3proto);
extern struct nf_conntrack_tuple_hash * extern struct nf_conntrack_tuple_hash *
__nf_conntrack_find(const struct nf_conntrack_tuple *tuple, __nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack); const struct nf_conn *ignored_conntrack);
......
...@@ -568,6 +568,7 @@ static int init_or_cleanup(int init) ...@@ -568,6 +568,7 @@ static int init_or_cleanup(int init)
return ret; return ret;
} }
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET));
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int __init init(void) static int __init init(void)
......
...@@ -584,6 +584,7 @@ static int init_or_cleanup(int init) ...@@ -584,6 +584,7 @@ static int init_or_cleanup(int init)
return ret; return ret;
} }
MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
......
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
* 26 Jan 2006: Harald Welte <laforge@netfilter.org> * 26 Jan 2006: Harald Welte <laforge@netfilter.org>
* - restructure nf_conn (introduce nf_conn_help) * - restructure nf_conn (introduce nf_conn_help)
* - redesign 'features' how they were originally intended * - redesign 'features' how they were originally intended
* 26 Feb 2006: Pablo Neira Ayuso <pablo@eurodev.net>
* - add support for L3 protocol module load on demand.
* *
* Derived from net/ipv4/netfilter/ip_conntrack_core.c * Derived from net/ipv4/netfilter/ip_conntrack_core.c
*/ */
...@@ -241,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p) ...@@ -241,6 +243,35 @@ void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p)
module_put(p->me); module_put(p->me);
} }
int
nf_ct_l3proto_try_module_get(unsigned short l3proto)
{
int ret;
struct nf_conntrack_l3proto *p;
retry: p = nf_ct_l3proto_find_get(l3proto);
if (p == &nf_conntrack_generic_l3proto) {
ret = request_module("nf_conntrack-%d", l3proto);
if (!ret)
goto retry;
return -EPROTOTYPE;
}
return 0;
}
void nf_ct_l3proto_module_put(unsigned short l3proto)
{
struct nf_conntrack_l3proto *p;
preempt_disable();
p = __nf_ct_l3proto_find(l3proto);
preempt_enable();
module_put(p->me);
}
static int nf_conntrack_hash_rnd_initted; static int nf_conntrack_hash_rnd_initted;
static unsigned int nf_conntrack_hash_rnd; static unsigned int nf_conntrack_hash_rnd;
......
...@@ -834,6 +834,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init); ...@@ -834,6 +834,8 @@ EXPORT_SYMBOL_GPL(__nf_ct_event_cache_init);
EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache); EXPORT_PER_CPU_SYMBOL_GPL(nf_conntrack_ecache);
EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events); EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
#endif #endif
EXPORT_SYMBOL(nf_ct_l3proto_try_module_get);
EXPORT_SYMBOL(nf_ct_l3proto_module_put);
EXPORT_SYMBOL(nf_conntrack_l3proto_register); EXPORT_SYMBOL(nf_conntrack_l3proto_register);
EXPORT_SYMBOL(nf_conntrack_l3proto_unregister); EXPORT_SYMBOL(nf_conntrack_l3proto_unregister);
EXPORT_SYMBOL(nf_conntrack_protocol_register); EXPORT_SYMBOL(nf_conntrack_protocol_register);
......
...@@ -64,14 +64,30 @@ checkentry(const char *tablename, ...@@ -64,14 +64,30 @@ checkentry(const char *tablename,
printk(KERN_WARNING "connmark: only support 32bit mark\n"); printk(KERN_WARNING "connmark: only support 32bit mark\n");
return 0; return 0;
} }
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load nf_conntrack support for "
"proto=%d\n", match->family);
return 0;
}
#endif
return 1; return 1;
} }
static void
destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
static struct xt_match connmark_match = { static struct xt_match connmark_match = {
.name = "connmark", .name = "connmark",
.match = match, .match = match,
.matchsize = sizeof(struct xt_connmark_info), .matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry, .checkentry = checkentry,
.destroy = destroy,
.family = AF_INET, .family = AF_INET,
.me = THIS_MODULE .me = THIS_MODULE
}; };
...@@ -81,6 +97,7 @@ static struct xt_match connmark6_match = { ...@@ -81,6 +97,7 @@ static struct xt_match connmark6_match = {
.match = match, .match = match,
.matchsize = sizeof(struct xt_connmark_info), .matchsize = sizeof(struct xt_connmark_info),
.checkentry = checkentry, .checkentry = checkentry,
.destroy = destroy,
.family = AF_INET6, .family = AF_INET6,
.me = THIS_MODULE .me = THIS_MODULE
}; };
......
...@@ -203,9 +203,37 @@ match(const struct sk_buff *skb, ...@@ -203,9 +203,37 @@ match(const struct sk_buff *skb,
#endif /* CONFIG_NF_IP_CONNTRACK */ #endif /* CONFIG_NF_IP_CONNTRACK */
static int
checkentry(const char *tablename,
const void *ip,
const struct xt_match *match,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load nf_conntrack support for "
"proto=%d\n", match->family);
return 0;
}
#endif
return 1;
}
static void
destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
static struct xt_match conntrack_match = { static struct xt_match conntrack_match = {
.name = "conntrack", .name = "conntrack",
.match = match, .match = match,
.checkentry = checkentry,
.destroy = destroy,
.matchsize = sizeof(struct xt_conntrack_info), .matchsize = sizeof(struct xt_conntrack_info),
.family = AF_INET, .family = AF_INET,
.me = THIS_MODULE, .me = THIS_MODULE,
......
...@@ -144,15 +144,31 @@ static int check(const char *tablename, ...@@ -144,15 +144,31 @@ static int check(const char *tablename,
{ {
struct xt_helper_info *info = matchinfo; struct xt_helper_info *info = matchinfo;
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load nf_conntrack support for "
"proto=%d\n", match->family);
return 0;
}
#endif
info->name[29] = '\0'; info->name[29] = '\0';
return 1; return 1;
} }
static void
destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
static struct xt_match helper_match = { static struct xt_match helper_match = {
.name = "helper", .name = "helper",
.match = match, .match = match,
.matchsize = sizeof(struct xt_helper_info), .matchsize = sizeof(struct xt_helper_info),
.checkentry = check, .checkentry = check,
.destroy = destroy,
.family = AF_INET, .family = AF_INET,
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
...@@ -161,6 +177,7 @@ static struct xt_match helper6_match = { ...@@ -161,6 +177,7 @@ static struct xt_match helper6_match = {
.match = match, .match = match,
.matchsize = sizeof(struct xt_helper_info), .matchsize = sizeof(struct xt_helper_info),
.checkentry = check, .checkentry = check,
.destroy = destroy,
.family = AF_INET6, .family = AF_INET6,
.me = THIS_MODULE, .me = THIS_MODULE,
}; };
......
...@@ -44,9 +44,36 @@ match(const struct sk_buff *skb, ...@@ -44,9 +44,36 @@ match(const struct sk_buff *skb,
return (sinfo->statemask & statebit); return (sinfo->statemask & statebit);
} }
static int check(const char *tablename,
const void *inf,
const struct xt_match *match,
void *matchinfo,
unsigned int matchsize,
unsigned int hook_mask)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
if (nf_ct_l3proto_try_module_get(match->family) < 0) {
printk(KERN_WARNING "can't load nf_conntrack support for "
"proto=%d\n", match->family);
return 0;
}
#endif
return 1;
}
static void
destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
{
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
nf_ct_l3proto_module_put(match->family);
#endif
}
static struct xt_match state_match = { static struct xt_match state_match = {
.name = "state", .name = "state",
.match = match, .match = match,
.checkentry = check,
.destroy = destroy,
.matchsize = sizeof(struct xt_state_info), .matchsize = sizeof(struct xt_state_info),
.family = AF_INET, .family = AF_INET,
.me = THIS_MODULE, .me = THIS_MODULE,
...@@ -55,6 +82,8 @@ static struct xt_match state_match = { ...@@ -55,6 +82,8 @@ static struct xt_match state_match = {
static struct xt_match state6_match = { static struct xt_match state6_match = {
.name = "state", .name = "state",
.match = match, .match = match,
.checkentry = check,
.destroy = destroy,
.matchsize = sizeof(struct xt_state_info), .matchsize = sizeof(struct xt_state_info),
.family = AF_INET6, .family = AF_INET6,
.me = THIS_MODULE, .me = THIS_MODULE,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment