X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fnetfilter%2Fip_nat_rule.c;h=581f097f5a247b43504c1290d71e75008434dd8a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=8ee96d10449aa5071644d81f3f89742bbc3758e8;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index 8ee96d104..581f097f5 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) @@ -35,25 +36,6 @@ #define NAT_VALID_HOOKS ((1<range[0], hooknum); +} + +/* Before 2.6.11 we did implicit source NAT if required. Warn about change. */ +static void warn_if_extra_mangle(u32 dstip, u32 srcip) +{ + static int warned = 0; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } }; + struct rtable *rt; + + if (ip_route_output_key(&rt, &fl) != 0) + return; + + if (rt->rt_src != srcip && !warned) { + printk("NAT: no longer support implicit source local NAT\n"); + printk("NAT: packet src %u.%u.%u.%u -> dst %u.%u.%u.%u\n", + NIPQUAD(srcip), NIPQUAD(dstip)); + warned = 1; + } + ip_rt_put(rt); } static unsigned int ipt_dnat_target(struct sk_buff **pskb, @@ -148,20 +149,22 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; + const struct ip_nat_multi_range_compat *mr = targinfo; -#ifdef CONFIG_IP_NF_NAT_LOCAL IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT); -#else - IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING); -#endif ct = ip_conntrack_get(*pskb, &ctinfo); /* Connection must be valid and new. */ IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); - return ip_nat_setup_info(ct, targinfo, hooknum); + if (hooknum == NF_IP_LOCAL_OUT + && mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) + warn_if_extra_mangle((*pskb)->nh.iph->daddr, + mr->range[0].min_ip); + + return ip_nat_setup_info(ct, &mr->range[0], hooknum); } static int ipt_snat_checkentry(const char *tablename, @@ -170,17 +173,15 @@ static int ipt_snat_checkentry(const char *tablename, unsigned int targinfosize, unsigned int hook_mask) { - struct ip_nat_multi_range *mr = targinfo; + struct ip_nat_multi_range_compat *mr = targinfo; /* Must be a valid range */ - if (targinfosize < sizeof(struct ip_nat_multi_range)) { - DEBUGP("SNAT: Target size %u too small\n", targinfosize); + if (mr->rangesize != 1) { + printk("SNAT: multiple ranges no longer supported\n"); return 0; } - if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range) - + (sizeof(struct ip_nat_range) - * (mr->rangesize - 1))))) { + if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) { DEBUGP("SNAT: Target size %u wrong for %u ranges\n", targinfosize, mr->rangesize); return 0; @@ -205,17 +206,15 @@ static int ipt_dnat_checkentry(const char *tablename, unsigned int targinfosize, unsigned int hook_mask) { - struct ip_nat_multi_range *mr = targinfo; + struct ip_nat_multi_range_compat *mr = targinfo; /* Must be a valid range */ - if (targinfosize < sizeof(struct ip_nat_multi_range)) { - DEBUGP("DNAT: Target size %u too small\n", targinfosize); + if (mr->rangesize != 1) { + printk("DNAT: multiple ranges no longer supported\n"); return 0; } - if (targinfosize != IPT_ALIGN((sizeof(struct ip_nat_multi_range) - + (sizeof(struct ip_nat_range) - * (mr->rangesize - 1))))) { + if (targinfosize != IPT_ALIGN(sizeof(struct ip_nat_multi_range_compat))) { DEBUGP("DNAT: Target size %u wrong for %u ranges\n", targinfosize, mr->rangesize); return 0; @@ -232,13 +231,6 @@ static int ipt_dnat_checkentry(const char *tablename, return 0; } -#ifndef CONFIG_IP_NF_NAT_LOCAL - if (hook_mask & (1 << NF_IP_LOCAL_OUT)) { - DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n"); - return 0; - } -#endif - return 1; } @@ -255,12 +247,12 @@ alloc_null_binding(struct ip_conntrack *conntrack, = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); - struct ip_nat_multi_range mr - = { 1, { { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } } } }; + struct ip_nat_range range + = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } }; DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", conntrack, NIPQUAD(ip)); - return ip_nat_setup_info(conntrack, &mr, hooknum); + return ip_nat_setup_info(conntrack, &range, hooknum); } int ip_nat_rule_find(struct sk_buff **pskb, @@ -275,7 +267,7 @@ int ip_nat_rule_find(struct sk_buff **pskb, ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL); if (ret == NF_ACCEPT) { - if (!(info->initialized & (1 << HOOK2MANIP(hooknum)))) + if (!ip_nat_initialized(ct, HOOK2MANIP(hooknum))) /* NUL mapping */ ret = alloc_null_binding(ct, info, hooknum); } @@ -298,7 +290,7 @@ int __init ip_nat_rule_init(void) { int ret; - ret = ipt_register_table(&nat_table); + ret = ipt_register_table(&nat_table, &nat_initial_table.repl); if (ret != 0) return ret; ret = ipt_register_target(&ipt_snat_reg);