commit c8fe51f524b3098adff20bb79105bb6dfe4db8a4 Author: Patrick McHardy Date: Fri Feb 22 17:16:08 2008 +0100 [NETFILTER]: nf_nat: always select same SNAT source for same host We've removed the SAME target in 2.6.25-rc since it had 32/64 bit compat problems and the NAT core provides the same behaviour regarding IP selection. This turned out to be not entirely correct though, the NAT core only selects the same IP from a range for the same src,dst combination. Some people need the same IP for all destinations however. The easiest way to do this is to ignore the destination IP when doing SNAT. Since we're using jhash, we still get good distribution for multiple source IPs. Signed-off-by: Patrick McHardy diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 0d5fa3a..8e1cae2 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -188,15 +188,19 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, __be32 *var_ipp; /* Host order */ u_int32_t minip, maxip, j; + __be32 dst; /* No IP mapping? Do nothing. */ if (!(range->flags & IP_NAT_RANGE_MAP_IPS)) return; - if (maniptype == IP_NAT_MANIP_SRC) + if (maniptype == IP_NAT_MANIP_SRC) { var_ipp = &tuple->src.u3.ip; - else + dst = 0; + } else { var_ipp = &tuple->dst.u3.ip; + dst = tuple->dst.u3.ip; + } /* Fast path: only one choice. */ if (range->min_ip == range->max_ip) { @@ -212,8 +216,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, * like this), even across reboots. */ minip = ntohl(range->min_ip); maxip = ntohl(range->max_ip); - j = jhash_2words((__force u32)tuple->src.u3.ip, - (__force u32)tuple->dst.u3.ip, 0); + j = jhash_2words((__force u32)tuple->src.u3.ip, (__force u32)dst, 0); j = ((u64)j * (maxip - minip + 1)) >> 32; *var_ipp = htonl(minip + j); }