X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_nat_standalone.c;h=dec4a74212cd51cea0ca9b5af1a0b471add844fe;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=e4e961225c5f6902e2bd0aa948017f7764ee98a6;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index e4e961225..dec4a7421 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -55,15 +55,6 @@ : ((hooknum) == NF_IP_LOCAL_IN ? "LOCAL_IN" \ : "*ERROR*"))) -static inline int call_expect(struct ip_conntrack *master, - struct sk_buff **pskb, - unsigned int hooknum, - struct ip_conntrack *ct, - struct ip_nat_info *info) -{ - return master->nat.info.helper->expect(pskb, hooknum, ct, info); -} - static unsigned int ip_nat_fn(unsigned int hooknum, struct sk_buff **pskb, @@ -86,7 +77,7 @@ ip_nat_fn(unsigned int hooknum, /* If we had a hardware checksum before, it's now invalid */ if ((*pskb)->ip_summed == CHECKSUM_HW) - if (skb_checksum_help(pskb, (out == NULL))) + if (skb_checksum_help(*pskb, (out == NULL))) return NF_DROP; ct = ip_conntrack_get(*pskb, &ctinfo); @@ -115,7 +106,7 @@ ip_nat_fn(unsigned int hooknum, case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - if (!icmp_reply_translation(pskb, ct, hooknum, + if (!icmp_reply_translation(pskb, ct, maniptype, CTINFO2DIR(ctinfo))) return NF_DROP; else @@ -125,47 +116,26 @@ ip_nat_fn(unsigned int hooknum, case IP_CT_NEW: info = &ct->nat.info; - WRITE_LOCK(&ip_nat_lock); /* Seen it before? This can happen for loopback, retrans, or local packets.. */ - if (!(info->initialized & (1 << maniptype)) -#ifndef CONFIG_IP_NF_NAT_LOCAL - /* If this session has already been confirmed we must not - * touch it again even if there is no mapping set up. - * Can only happen on local->local traffic with - * CONFIG_IP_NF_NAT_LOCAL disabled. - */ - && !(ct->status & IPS_CONFIRMED) -#endif - ) { + if (!ip_nat_initialized(ct, maniptype)) { unsigned int ret; - if (ct->master - && master_ct(ct)->nat.info.helper - && master_ct(ct)->nat.info.helper->expect) { - ret = call_expect(master_ct(ct), pskb, - hooknum, ct, info); - } else { -#ifdef CONFIG_IP_NF_NAT_LOCAL - /* LOCAL_IN hook doesn't have a chain! */ - if (hooknum == NF_IP_LOCAL_IN) - ret = alloc_null_binding(ct, info, - hooknum); - else -#endif - ret = ip_nat_rule_find(pskb, hooknum, in, out, - ct, info); - } + /* LOCAL_IN hook doesn't have a chain! */ + if (hooknum == NF_IP_LOCAL_IN) + ret = alloc_null_binding(ct, info, hooknum); + else + ret = ip_nat_rule_find(pskb, hooknum, + in, out, ct, + info); if (ret != NF_ACCEPT) { - WRITE_UNLOCK(&ip_nat_lock); return ret; } } else DEBUGP("Already setup manip %s for ct %p\n", maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", ct); - WRITE_UNLOCK(&ip_nat_lock); break; default: @@ -176,7 +146,30 @@ ip_nat_fn(unsigned int hooknum, } IP_NF_ASSERT(info); - return do_bindings(ct, ctinfo, info, hooknum, pskb); + return nat_packet(ct, ctinfo, hooknum, pskb); +} + +static unsigned int +ip_nat_in(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + u_int32_t saddr, daddr; + unsigned int ret; + + saddr = (*pskb)->nh.iph->saddr; + daddr = (*pskb)->nh.iph->daddr; + + ret = ip_nat_fn(hooknum, pskb, in, out, okfn); + if (ret != NF_DROP && ret != NF_STOLEN + && ((*pskb)->nh.iph->saddr != saddr + || (*pskb)->nh.iph->daddr != daddr)) { + dst_release((*pskb)->dst); + (*pskb)->dst = NULL; + } + return ret; } static unsigned int @@ -202,7 +195,7 @@ ip_nat_out(unsigned int hooknum, I'm starting to have nightmares about fragments. */ if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { - *pskb = ip_ct_gather_frags(*pskb); + *pskb = ip_ct_gather_frags(*pskb, IP_DEFRAG_NAT_OUT); if (!*pskb) return NF_STOLEN; @@ -211,7 +204,6 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } -#ifdef CONFIG_IP_NF_NAT_LOCAL static unsigned int ip_nat_local_fn(unsigned int hooknum, struct sk_buff **pskb, @@ -237,13 +229,12 @@ ip_nat_local_fn(unsigned int hooknum, return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; return ret; } -#endif /* We must be after connection tracking and before packet filtering. */ /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_in_ops = { - .hook = ip_nat_fn, + .hook = ip_nat_in, .owner = THIS_MODULE, .pf = PF_INET, .hooknum = NF_IP_PRE_ROUTING, @@ -259,7 +250,6 @@ static struct nf_hook_ops ip_nat_out_ops = { .priority = NF_IP_PRI_NAT_SRC, }; -#ifdef CONFIG_IP_NF_NAT_LOCAL /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops = { .hook = ip_nat_local_fn, @@ -277,34 +267,6 @@ static struct nf_hook_ops ip_nat_local_in_ops = { .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, }; -#endif - -/* Protocol registration. */ -int ip_nat_protocol_register(struct ip_nat_protocol *proto) -{ - int ret = 0; - - WRITE_LOCK(&ip_nat_lock); - if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) { - ret = -EBUSY; - goto out; - } - ip_nat_protos[proto->protonum] = proto; - out: - WRITE_UNLOCK(&ip_nat_lock); - return ret; -} - -/* Noone stores the protocol anywhere; simply delete it. */ -void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) -{ - WRITE_LOCK(&ip_nat_lock); - ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol; - WRITE_UNLOCK(&ip_nat_lock); - - /* Someone could be still looking at the proto in a bh. */ - synchronize_net(); -} static int init_or_cleanup(int init) { @@ -334,7 +296,6 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register out hook.\n"); goto cleanup_inops; } -#ifdef CONFIG_IP_NF_NAT_LOCAL ret = nf_register_hook(&ip_nat_local_out_ops); if (ret < 0) { printk("ip_nat_init: can't register local out hook.\n"); @@ -345,16 +306,13 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register local in hook.\n"); goto cleanup_localoutops; } -#endif return ret; cleanup: -#ifdef CONFIG_IP_NF_NAT_LOCAL nf_unregister_hook(&ip_nat_local_in_ops); cleanup_localoutops: nf_unregister_hook(&ip_nat_local_out_ops); cleanup_outops: -#endif nf_unregister_hook(&ip_nat_out_ops); cleanup_inops: nf_unregister_hook(&ip_nat_in_ops); @@ -383,12 +341,9 @@ module_exit(fini); EXPORT_SYMBOL(ip_nat_setup_info); EXPORT_SYMBOL(ip_nat_protocol_register); EXPORT_SYMBOL(ip_nat_protocol_unregister); -EXPORT_SYMBOL(ip_nat_helper_register); -EXPORT_SYMBOL(ip_nat_helper_unregister); EXPORT_SYMBOL(ip_nat_cheat_check); EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); EXPORT_SYMBOL(ip_nat_mangle_udp_packet); EXPORT_SYMBOL(ip_nat_used_tuple); -EXPORT_SYMBOL(ip_nat_find_helper); -EXPORT_SYMBOL(__ip_nat_find_helper); +EXPORT_SYMBOL(ip_nat_follow_master); MODULE_LICENSE("GPL");