From: Patrick McHardy Date: Mon, 20 Feb 2006 06:26:40 +0000 (-0800) Subject: [NETFILTER]: Fix NAT PMTUD problems X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=bc6e14b6f0b06fe93d809d22e257ddd275feeda9;p=openwrt%2Fstaging%2Fblogic.git [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 --- diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index c1a61462507f..1741d555ad0d 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;