aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2005-01-04 04:12:51 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-04 04:12:51 -0800
commit17aa18a7a2a0959f590960683ee245aef12158f0 (patch)
tree9f499553d33f7801894740fa22ce973c385cfa9b /net
parent858bd546910f4c0585bbada181bc32e1b3e11e9e (diff)
downloadhistory-17aa18a7a2a0959f590960683ee245aef12158f0.tar.gz
[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: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c96
1 files changed, 23 insertions, 73 deletions
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index b38c07ad40648f..469297661fcbb1 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -179,25 +179,6 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
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. */
static inline int fake_cmp(const struct ip_conntrack *ct,
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,
{
unsigned int best_score = 0xFFFFFFFF;
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;
/* Host order */
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;
- saved_ip = tuple->dst.ip;
- other_ipp = &tuple->dst.ip;
- } else {
+ else
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);
- maxip = ntohl(range->max_ip);
- } else
- minip = maxip = ntohl(*var_ipp);
+ minip = ntohl(range->min_ip);
+ maxip = ntohl(range->max_ip);
+ /* FIXME: use hash of ips like ipt_SAME, not randomness.
+ This way same pairs get same IP: think Internet Banking.
+ */
randomness++;
for (j = 0; j < maxip - minip + 1; j++) {
unsigned int score;
@@ -275,14 +258,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple,
*var_ipp = htonl(minip + (randomness + j)
% (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. */
score = count_maps(tuple->src.ip, tuple->dst.ip,
tuple->dst.protonum, conntrack);
@@ -299,36 +274,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *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,
* 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
@@ -363,7 +308,7 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple,
/* 2) Select the least-used IP/proto combination in the given
range. */
*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
the range to make a unique tuple. */
@@ -462,6 +407,9 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* Has source changed?. */
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. */
info->manips[info->num_manips++] =
((struct ip_nat_info_manip)
@@ -480,6 +428,8 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
/* Has destination changed? */
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 */
info->manips[info->num_manips++] =
((struct ip_nat_info_manip)