X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_nat_tftp.c;h=604793536fc13cce0f43320b6ef212bfb9f3012a;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=4b557e20ebbb82a3ed7fff072971cedb36c94eab;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c index 4b557e20e..604793536 100644 --- a/net/ipv4/netfilter/ip_nat_tftp.c +++ b/net/ipv4/netfilter/ip_nat_tftp.c @@ -32,174 +32,39 @@ #include #include #include +#include MODULE_AUTHOR("Magnus Boden "); MODULE_DESCRIPTION("tftp NAT helper"); MODULE_LICENSE("GPL"); -#define MAX_PORTS 8 - -static int ports[MAX_PORTS]; -static int ports_c = 0; -#ifdef MODULE_PARM -MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i"); -MODULE_PARM_DESC(ports, "port numbers of tftp servers"); -#endif - -#if 0 -#define DEBUGP(format, args...) printk("%s:%s:" format, \ - __FILE__, __FUNCTION__ , ## args) -#else -#define DEBUGP(format, args...) -#endif -static unsigned int -tftp_nat_help(struct ip_conntrack *ct, - struct ip_conntrack_expect *exp, - struct ip_nat_info *info, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - struct sk_buff **pskb) +static unsigned int help(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *exp) { - int dir = CTINFO2DIR(ctinfo); - struct tftphdr tftph; - struct ip_conntrack_tuple repl; - - if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) - || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) - return NF_ACCEPT; + struct ip_conntrack *ct = exp->master; - if (!exp) { - DEBUGP("no conntrack expectation to modify\n"); - return NF_ACCEPT; - } - - if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), - &tftph, sizeof(tftph)) != 0) + exp->saved_proto.udp.port + = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port; + exp->dir = IP_CT_DIR_REPLY; + exp->expectfn = ip_nat_follow_master; + if (ip_conntrack_expect_related(exp) != 0) return NF_DROP; - - switch (ntohs(tftph.opcode)) { - /* RRQ and WRQ works the same way */ - case TFTP_OPCODE_READ: - case TFTP_OPCODE_WRITE: - repl = ct->tuplehash[IP_CT_DIR_REPLY].tuple; - DEBUGP(""); - DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); - DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); - DEBUGP("expecting: "); - DUMP_TUPLE(&repl); - DUMP_TUPLE(&exp->mask); - ip_conntrack_change_expect(exp, &repl); - break; - default: - DEBUGP("Unknown opcode\n"); - } - return NF_ACCEPT; } -static unsigned int -tftp_nat_expected(struct sk_buff **pskb, - unsigned int hooknum, - struct ip_conntrack *ct, - struct ip_nat_info *info) +static void __exit ip_nat_tftp_fini(void) { - const struct ip_conntrack *master = ct->master->expectant; - const struct ip_conntrack_tuple *orig = - &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple; - struct ip_nat_multi_range mr; -#if 0 - const struct ip_conntrack_tuple *repl = - &master->tuplehash[IP_CT_DIR_REPLY].tuple; - struct udphdr udph; - - if (skb_copy_bits(*pskb,(*pskb)->nh.iph->ihl*4,&udph,sizeof(udph))!=0) - return NF_DROP; -#endif - - IP_NF_ASSERT(info); - IP_NF_ASSERT(master); - IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum)))); - - mr.rangesize = 1; - mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; - - if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) { - mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; - DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u " - "newsrc: %u.%u.%u.%u\n", - NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source), - NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest), - NIPQUAD(orig->dst.ip)); - } else { - mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip; - mr.range[0].min.udp.port = mr.range[0].max.udp.port = - orig->src.u.udp.port; - mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED; - - DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u " - "newdst: %u.%u.%u.%u:%u\n", - NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source), - NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest), - NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port)); - } - - return ip_nat_setup_info(ct,&mr,hooknum); -} - -static struct ip_nat_helper tftp[MAX_PORTS]; -static char tftp_names[MAX_PORTS][10]; - -static void fini(void) -{ - int i; - - for (i = 0 ; i < ports_c; i++) { - DEBUGP("unregistering helper for port %d\n", ports[i]); - ip_nat_helper_unregister(&tftp[i]); - } + rcu_assign_pointer(ip_nat_tftp_hook, NULL); + synchronize_rcu(); } -static int __init init(void) +static int __init ip_nat_tftp_init(void) { - int i, ret = 0; - char *tmpname; - - if (!ports[0]) - ports[0] = TFTP_PORT; - - for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) { - memset(&tftp[i], 0, sizeof(struct ip_nat_helper)); - - tftp[i].tuple.dst.protonum = IPPROTO_UDP; - tftp[i].tuple.src.u.udp.port = htons(ports[i]); - tftp[i].mask.dst.protonum = 0xFFFF; - tftp[i].mask.src.u.udp.port = 0xFFFF; - tftp[i].help = tftp_nat_help; - tftp[i].flags = 0; - tftp[i].me = THIS_MODULE; - tftp[i].expect = tftp_nat_expected; - - tmpname = &tftp_names[i][0]; - if (ports[i] == TFTP_PORT) - sprintf(tmpname, "tftp"); - else - sprintf(tmpname, "tftp-%d", i); - tftp[i].name = tmpname; - - DEBUGP("ip_nat_tftp: registering for port %d: name %s\n", - ports[i], tftp[i].name); - ret = ip_nat_helper_register(&tftp[i]); - - if (ret) { - printk("ip_nat_tftp: unable to register for port %d\n", - ports[i]); - fini(); - return ret; - } - ports_c++; - } - return ret; + BUG_ON(rcu_dereference(ip_nat_tftp_hook)); + rcu_assign_pointer(ip_nat_tftp_hook, help); + return 0; } -module_init(init); -module_exit(fini); +module_init(ip_nat_tftp_init); +module_exit(ip_nat_tftp_fini);