From bc6e14b6f0b06fe93d809d22e257ddd275feeda9 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 19 Feb 2006 22:26:40 -0800 Subject: [NETFILTER]: Fix NAT PMTUD problems ICMP errors are only SNATed when their source matches the source of the connection they are related to, otherwise the source address is not changed. This creates problems with ICMP frag. required messages originating from a router behind the NAT, if private IPs are used the packet has a good change of getting dropped on the path to its destination. Always NAT ICMP errors similar to the original connection. Based on report by Al Viro. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_core.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c1a6146250..1741d555ad 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -434,6 +434,7 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, } *inside; struct ip_conntrack_tuple inner, target; int hdrlen = (*pskb)->nh.iph->ihl * 4; + unsigned long statusbit; if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) return 0; @@ -495,17 +496,16 @@ int ip_nat_icmp_reply_translation(struct sk_buff **pskb, /* Change outer to look the reply to an incoming packet * (proto 0 means don't invert per-proto part). */ + if (manip == IP_NAT_MANIP_SRC) + statusbit = IPS_SRC_NAT; + else + statusbit = IPS_DST_NAT; - /* Obviously, we need to NAT destination IP, but source IP - should be NAT'ed only if it is from a NAT'd host. + /* Invert if this is reply dir. */ + if (dir == IP_CT_DIR_REPLY) + statusbit ^= IPS_NAT_MASK; - Explanation: some people use NAT for anonymizing. Also, - CERT recommends dropping all packets from private IP - addresses (although ICMP errors from internal links with - such addresses are not too uncommon, as Alan Cox points - out) */ - if (manip != IP_NAT_MANIP_SRC - || ((*pskb)->nh.iph->saddr == ct->tuplehash[dir].tuple.src.ip)) { + if (ct->status & statusbit) { invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); if (!manip_pkt(0, pskb, 0, &target, manip)) return 0; -- cgit v1.2.2 From 8e249f088131cde5f77fd073bf0b0e8b3e9ea4ac Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 19 Feb 2006 22:29:47 -0800 Subject: [NETFILTER]: Fix outgoing redirects to loopback When redirecting an outgoing packet to loopback, it keeps the original conntrack reference and information from the outgoing path, which falsely triggers the check for DNAT on input and the dst_entry is released to trigger rerouting. ip_route_input refuses to route the packet because it has a local source address and it is dropped. Look at the packet itself to dermine if it was NATed. Also fix a missing inversion that causes unneccesary xfrm lookups. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_standalone.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'net/ipv4') diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 7c3f7d3802..ab1f88fa21 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -200,20 +200,14 @@ ip_nat_in(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - struct ip_conntrack *ct; - enum ip_conntrack_info ctinfo; unsigned int ret; + u_int32_t daddr = (*pskb)->nh.iph->daddr; ret = ip_nat_fn(hooknum, pskb, in, out, okfn); if (ret != NF_DROP && ret != NF_STOLEN - && (ct = ip_conntrack_get(*pskb, &ctinfo)) != NULL) { - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - - if (ct->tuplehash[dir].tuple.dst.ip != - ct->tuplehash[!dir].tuple.src.ip) { - dst_release((*pskb)->dst); - (*pskb)->dst = NULL; - } + && daddr != (*pskb)->nh.iph->daddr) { + dst_release((*pskb)->dst); + (*pskb)->dst = NULL; } return ret; } @@ -276,7 +270,7 @@ ip_nat_local_fn(unsigned int hooknum, ct->tuplehash[!dir].tuple.src.ip #ifdef CONFIG_XFRM || ct->tuplehash[dir].tuple.dst.u.all != - ct->tuplehash[dir].tuple.src.u.all + ct->tuplehash[!dir].tuple.src.u.all #endif ) return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; -- cgit v1.2.2 From 85259878499d6c428cba191bb4e415a250dcd75a Mon Sep 17 00:00:00 2001 From: Suresh Bhogavilli Date: Tue, 21 Feb 2006 13:42:22 -0800 Subject: [IPV4]: Fix garbage collection of multipath route entries When garbage collecting route cache entries of multipath routes in rt_garbage_collect(), entries were deleted from the hash bucket 'i' while holding a spin lock on bucket 'k' resulting in a system hang. Delete entries, if any, from bucket 'k' instead. Signed-off-by: Suresh Bhogavilli Signed-off-by: David S. Miller --- net/ipv4/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv4') diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d82c242ea7..fca5fe0cf9 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -835,7 +835,7 @@ static int rt_garbage_collect(void) int r; rthp = rt_remove_balanced_route( - &rt_hash_table[i].chain, + &rt_hash_table[k].chain, rth, &r); goal -= r; -- cgit v1.2.2 From 4da3089f2b582b21e1374ccc6df722d4361eb915 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 23 Feb 2006 16:19:26 -0800 Subject: [IPSEC]: Use TOS when doing tunnel lookups We should use the TOS because it's one of the routing keys. It also means that we update the correct routing cache entry when PMTU occurs. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/xfrm4_policy.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/ipv4') diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 45f7ae58f2..f285bbf296 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -35,6 +35,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) if (xdst->u.rt.fl.oif == fl->oif && /*XXX*/ xdst->u.rt.fl.fl4_dst == fl->fl4_dst && xdst->u.rt.fl.fl4_src == fl->fl4_src && + xdst->u.rt.fl.fl4_tos == fl->fl4_tos && xfrm_bundle_ok(xdst, fl, AF_INET)) { dst_clone(dst); break; @@ -61,7 +62,8 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int .nl_u = { .ip4_u = { .saddr = local, - .daddr = remote + .daddr = remote, + .tos = fl->fl4_tos } } }; @@ -230,6 +232,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) fl->proto = iph->protocol; fl->fl4_dst = iph->daddr; fl->fl4_src = iph->saddr; + fl->fl4_tos = iph->tos; } static inline int xfrm4_garbage_collect(void) -- cgit v1.2.2