diff options
Diffstat (limited to 'net/netfilter/xt_helper.c')
| -rw-r--r-- | net/netfilter/xt_helper.c | 183 |
1 files changed, 47 insertions, 136 deletions
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 38b6715e1db..9f4ab00c805 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c @@ -5,184 +5,95 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * 19 Mar 2002 Harald Welte <laforge@gnumonks.org>: - * - Port to newnat infrastructure */ - +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> #include <linux/skbuff.h> #include <linux/netfilter.h> -#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) -#include <linux/netfilter_ipv4/ip_conntrack.h> -#include <linux/netfilter_ipv4/ip_conntrack_core.h> -#include <linux/netfilter_ipv4/ip_conntrack_helper.h> -#else #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_helper.h> -#endif #include <linux/netfilter/x_tables.h> #include <linux/netfilter/xt_helper.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); -MODULE_DESCRIPTION("iptables helper match module"); +MODULE_DESCRIPTION("Xtables: Related connection matching"); MODULE_ALIAS("ipt_helper"); MODULE_ALIAS("ip6t_helper"); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif -#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) +static bool +helper_mt(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_helper_info *info = matchinfo; - struct ip_conntrack *ct; + const struct xt_helper_info *info = par->matchinfo; + const struct nf_conn *ct; + const struct nf_conn_help *master_help; + const struct nf_conntrack_helper *helper; enum ip_conntrack_info ctinfo; - int ret = info->invert; - - ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); - if (!ct) { - DEBUGP("xt_helper: Eek! invalid conntrack?\n"); - return ret; - } + bool ret = info->invert; - if (!ct->master) { - DEBUGP("xt_helper: conntrack %p has no master\n", ct); + ct = nf_ct_get(skb, &ctinfo); + if (!ct || !ct->master) return ret; - } - read_lock_bh(&ip_conntrack_lock); - if (!ct->master->helper) { - DEBUGP("xt_helper: master ct %p has no helper\n", - exp->expectant); - goto out_unlock; - } + master_help = nfct_help(ct->master); + if (!master_help) + return ret; - DEBUGP("master's name = %s , info->name = %s\n", - ct->master->helper->name, info->name); + /* rcu_read_lock()ed by nf_hook_slow */ + helper = rcu_dereference(master_help->helper); + if (!helper) + return ret; if (info->name[0] == '\0') - ret ^= 1; + ret = !ret; else - ret ^= !strncmp(ct->master->helper->name, info->name, - strlen(ct->master->helper->name)); -out_unlock: - read_unlock_bh(&ip_conntrack_lock); + ret ^= !strncmp(helper->name, info->name, + strlen(helper->name)); return ret; } -#else /* CONFIG_IP_NF_CONNTRACK */ - -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) +static int helper_mt_check(const struct xt_mtchk_param *par) { - const struct xt_helper_info *info = matchinfo; - struct nf_conn *ct; - enum ip_conntrack_info ctinfo; - int ret = info->invert; - - ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); - if (!ct) { - DEBUGP("xt_helper: Eek! invalid conntrack?\n"); - return ret; - } + struct xt_helper_info *info = par->matchinfo; + int ret; - if (!ct->master) { - DEBUGP("xt_helper: conntrack %p has no master\n", ct); + ret = nf_ct_l3proto_try_module_get(par->family); + if (ret < 0) { + pr_info("cannot load conntrack support for proto=%u\n", + par->family); return ret; } - - read_lock_bh(&nf_conntrack_lock); - if (!ct->master->helper) { - DEBUGP("xt_helper: master ct %p has no helper\n", - exp->expectant); - goto out_unlock; - } - - DEBUGP("master's name = %s , info->name = %s\n", - ct->master->helper->name, info->name); - - if (info->name[0] == '\0') - ret ^= 1; - else - ret ^= !strncmp(ct->master->helper->name, info->name, - strlen(ct->master->helper->name)); -out_unlock: - read_unlock_bh(&nf_conntrack_lock); - return ret; + info->name[29] = '\0'; + return 0; } -#endif -static int check(const char *tablename, - const void *inf, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) +static void helper_mt_destroy(const struct xt_mtdtor_param *par) { - struct xt_helper_info *info = matchinfo; - - info->name[29] = '\0'; - - /* verify size */ - if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) - return 0; - - return 1; + nf_ct_l3proto_module_put(par->family); } -static struct xt_match helper_match = { - .name = "helper", - .match = &match, - .checkentry = &check, - .me = THIS_MODULE, -}; -static struct xt_match helper6_match = { - .name = "helper", - .match = &match, - .checkentry = &check, - .me = THIS_MODULE, +static struct xt_match helper_mt_reg __read_mostly = { + .name = "helper", + .revision = 0, + .family = NFPROTO_UNSPEC, + .checkentry = helper_mt_check, + .match = helper_mt, + .destroy = helper_mt_destroy, + .matchsize = sizeof(struct xt_helper_info), + .me = THIS_MODULE, }; -static int __init init(void) +static int __init helper_mt_init(void) { - int ret; - need_conntrack(); - - ret = xt_register_match(AF_INET, &helper_match); - if (ret < 0) - return ret; - - ret = xt_register_match(AF_INET6, &helper6_match); - if (ret < 0) - xt_unregister_match(AF_INET, &helper_match); - - return ret; + return xt_register_match(&helper_mt_reg); } -static void __exit fini(void) +static void __exit helper_mt_exit(void) { - xt_unregister_match(AF_INET, &helper_match); - xt_unregister_match(AF_INET6, &helper6_match); + xt_unregister_match(&helper_mt_reg); } -module_init(init); -module_exit(fini); - +module_init(helper_mt_init); +module_exit(helper_mt_exit); |
