Commit 17aa18a7 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Remove do_extra_mangle: double NAT on LOCAL_OUT

On NF_IP_LOCAL_OUT, when destination NAT changes the destination
interface, we also change the source address, so the packet is the
same as if it were generated to go that way in the first place.  This
is not strictly necessary, I believe.

This patch rips that code out to see what breaks.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 858bd546
...@@ -179,25 +179,6 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, ...@@ -179,25 +179,6 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
return 0; return 0;
} }
/* If it's really a local destination manip, it may need to do a
source manip too. */
static void
do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = var_ip } } };
struct rtable *rt;
/* FIXME: IPTOS_TOS(iph->tos) --RR */
if (ip_route_output_key(&rt, &fl) != 0) {
DEBUGP("do_extra_mangle: Can't get route to %u.%u.%u.%u\n",
NIPQUAD(var_ip));
return;
}
*other_ipp = rt->rt_src;
ip_rt_put(rt);
}
/* Simple way to iterate through all. */ /* Simple way to iterate through all. */
static inline int fake_cmp(const struct ip_conntrack *ct, static inline int fake_cmp(const struct ip_conntrack *ct,
u_int32_t src, u_int32_t dst, u_int16_t protonum, u_int32_t src, u_int32_t dst, u_int16_t protonum,
...@@ -244,30 +225,32 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple, ...@@ -244,30 +225,32 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
{ {
unsigned int best_score = 0xFFFFFFFF; unsigned int best_score = 0xFFFFFFFF;
struct ip_conntrack_tuple best_tuple = *tuple; struct ip_conntrack_tuple best_tuple = *tuple;
u_int32_t *var_ipp, *other_ipp, saved_ip, orig_dstip; u_int32_t *var_ipp;
static unsigned int randomness; static unsigned int randomness;
/* Host order */ /* Host order */
u_int32_t minip, maxip, j; u_int32_t minip, maxip, j;
if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) { /* No IP mapping? Do nothing. */
if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
return;
if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
var_ipp = &tuple->src.ip; var_ipp = &tuple->src.ip;
saved_ip = tuple->dst.ip; else
other_ipp = &tuple->dst.ip;
} else {
var_ipp = &tuple->dst.ip; var_ipp = &tuple->dst.ip;
saved_ip = tuple->src.ip;
other_ipp = &tuple->src.ip; /* Fast path: only one choice. */
if (range->min_ip == range->max_ip) {
*var_ipp = range->min_ip;
return;
} }
/* Don't do do_extra_mangle unless necessary (overrides
explicit socket bindings, for example) */
orig_dstip = tuple->dst.ip;
if (range->flags & IP_NAT_RANGE_MAP_IPS) { minip = ntohl(range->min_ip);
minip = ntohl(range->min_ip); maxip = ntohl(range->max_ip);
maxip = ntohl(range->max_ip);
} else
minip = maxip = ntohl(*var_ipp);
/* FIXME: use hash of ips like ipt_SAME, not randomness.
This way same pairs get same IP: think Internet Banking.
*/
randomness++; randomness++;
for (j = 0; j < maxip - minip + 1; j++) { for (j = 0; j < maxip - minip + 1; j++) {
unsigned int score; unsigned int score;
...@@ -275,14 +258,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple, ...@@ -275,14 +258,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
*var_ipp = htonl(minip + (randomness + j) *var_ipp = htonl(minip + (randomness + j)
% (maxip - minip + 1)); % (maxip - minip + 1));
/* Reset the other ip in case it was mangled by
* do_extra_mangle last time. */
*other_ipp = saved_ip;
if (hooknum == NF_IP_LOCAL_OUT
&& *var_ipp != orig_dstip)
do_extra_mangle(*var_ipp, other_ipp);
/* Count how many others map onto this. */ /* Count how many others map onto this. */
score = count_maps(tuple->src.ip, tuple->dst.ip, score = count_maps(tuple->src.ip, tuple->dst.ip,
tuple->dst.protonum, conntrack); tuple->dst.protonum, conntrack);
...@@ -299,36 +274,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple, ...@@ -299,36 +274,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
*tuple = best_tuple; *tuple = best_tuple;
} }
/* Fast version doesn't iterate through hash chains, but only handles
common case of single IP address (null NAT, masquerade) */
static void
find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple,
const struct ip_nat_range *range,
const struct ip_conntrack *conntrack,
unsigned int hooknum)
{
/* Leave IP address alone if we're not to map IP addresses. */
if (!(range->flags & IP_NAT_RANGE_MAP_IPS))
return;
if (range->min_ip != range->max_ip) {
find_best_ips_proto(tuple, range, conntrack, hooknum);
return;
}
if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
tuple->src.ip = range->min_ip;
else {
/* Only do extra mangle when required (breaks socket
binding) */
if (tuple->dst.ip != range->min_ip
&& hooknum == NF_IP_LOCAL_OUT)
do_extra_mangle(range->min_ip, &tuple->src.ip);
else
tuple->dst.ip = range->min_ip;
}
}
/* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING, /* Manipulate the tuple into the range given. For NF_IP_POST_ROUTING,
* we change the source to map into the range. For NF_IP_PRE_ROUTING * we change the source to map into the range. For NF_IP_PRE_ROUTING
* and NF_IP_LOCAL_OUT, we change the destination to map into the * and NF_IP_LOCAL_OUT, we change the destination to map into the
...@@ -363,7 +308,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, ...@@ -363,7 +308,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
/* 2) Select the least-used IP/proto combination in the given /* 2) Select the least-used IP/proto combination in the given
range. */ range. */
*tuple = *orig_tuple; *tuple = *orig_tuple;
find_best_ips_proto_fast(tuple, range, conntrack, hooknum); find_best_ips_proto(tuple, range, conntrack, hooknum);
/* 3) The per-protocol part of the manip is made to map into /* 3) The per-protocol part of the manip is made to map into
the range to make a unique tuple. */ the range to make a unique tuple. */
...@@ -462,6 +407,9 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, ...@@ -462,6 +407,9 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* Has source changed?. */ /* Has source changed?. */
if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) { if (!ip_ct_tuple_src_equal(&new_tuple, &orig_tp)) {
IP_NF_ASSERT(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC);
IP_NF_ASSERT(ip_ct_tuple_dst_equal(&new_tuple, &orig_tp));
/* In this direction, a source manip. */ /* In this direction, a source manip. */
info->manips[info->num_manips++] = info->manips[info->num_manips++] =
((struct ip_nat_info_manip) ((struct ip_nat_info_manip)
...@@ -480,6 +428,8 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, ...@@ -480,6 +428,8 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* Has destination changed? */ /* Has destination changed? */
if (!ip_ct_tuple_dst_equal(&new_tuple, &orig_tp)) { if (!ip_ct_tuple_dst_equal(&new_tuple, &orig_tp)) {
IP_NF_ASSERT(HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST);
/* In this direction, a destination manip */ /* In this direction, a destination manip */
info->manips[info->num_manips++] = info->manips[info->num_manips++] =
((struct ip_nat_info_manip) ((struct ip_nat_info_manip)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment