X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fnetfilter%2Fxt_helper.c;h=64fc7f277221b67c9e77ac0dd2addc2004192863;hb=13ccdfc2af03e09e60791f7d4bc4ccf53398af7c;hp=0ddb32363d062f115a347917c87799b0b9f4feff;hpb=dc808fe28db59fadf4ec32d53f62477fa28f3be8;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c index 0ddb323..64fc7f2 100644 --- a/net/netfilter/xt_helper.c +++ b/net/netfilter/xt_helper.c @@ -5,186 +5,93 @@ * 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 : - * - Port to newnat infrastructure */ #include #include #include -#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) -#include -#include -#include -#else #include #include #include -#endif #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Martin Josefsson "); -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, const struct xt_match_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; - } - - 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(&ip_conntrack_lock); - 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) -{ - const struct xt_helper_info *info = matchinfo; - struct nf_conn *ct; - struct nf_conn_help *master_help; - 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"); + master_help = nfct_help(ct->master); + if (!master_help) return ret; - } - if (!ct->master) { - DEBUGP("xt_helper: conntrack %p has no master\n", ct); + /* rcu_read_lock()ed by nf_hook_slow */ + helper = rcu_dereference(master_help->helper); + if (!helper) return ret; - } - - read_lock_bh(&nf_conntrack_lock); - master_help = nfct_help(ct->master); - if (!master_help || !master_help->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; + ret = !ret; else - ret ^= !strncmp(master_help->helper->name, info->name, - strlen(master_help->helper->name)); -out_unlock: - read_unlock_bh(&nf_conntrack_lock); + ret ^= !strncmp(helper->name, info->name, + strlen(helper->name)); return ret; } -#endif -static int check(const char *tablename, - const void *inf, - void *matchinfo, - unsigned int matchsize, - unsigned int hook_mask) +static bool helper_mt_check(const struct xt_mtchk_param *par) { - struct xt_helper_info *info = matchinfo; + struct xt_helper_info *info = par->matchinfo; + if (nf_ct_l3proto_try_module_get(par->family) < 0) { + printk(KERN_WARNING "can't load conntrack support for " + "proto=%u\n", par->family); + return false; + } info->name[29] = '\0'; + return true; +} - /* verify size */ - if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) - return 0; - - return 1; +static void helper_mt_destroy(const struct xt_mtdtor_param *par) +{ + 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);