[NETFILTER]: nat: avoid rerouting packets if only XFRM policy key changed
authorPatrick McHardy <kaber@trash.net>
Thu, 22 Mar 2007 19:30:29 +0000 (12:30 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 22 Mar 2007 19:30:29 +0000 (12:30 -0700)
Currently NAT not only reroutes packets in the OUTPUT chain when the
routing key changed, but also if only the non-routing part of the
IPsec policy key changed. This breaks ping -I since it doesn't use
SO_BINDTODEVICE but IP_PKTINFO cmsg to specify the output device, and
this information is lost.

Only do full rerouting if the routing key changed, and just do a new
policy lookup with the old route if only the ports changed.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/nf_nat_standalone.c

index adf25f9f70e1316fe422e76015c1e23317c26fd2..6bcfdf6dfcc9b37726e38a0ce766eb2d056f6f36 100644 (file)
@@ -253,14 +253,17 @@ ip_nat_local_fn(unsigned int hooknum,
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.dst.ip !=
-                   ct->tuplehash[!dir].tuple.src.ip
-#ifdef CONFIG_XFRM
-                   || ct->tuplehash[dir].tuple.dst.u.all !=
-                      ct->tuplehash[!dir].tuple.src.u.all
-#endif
-                   )
+                   ct->tuplehash[!dir].tuple.src.ip) {
                        if (ip_route_me_harder(pskb, RTN_UNSPEC))
                                ret = NF_DROP;
+               }
+#ifdef CONFIG_XFRM
+               else if (ct->tuplehash[dir].tuple.dst.u.all !=
+                        ct->tuplehash[!dir].tuple.src.u.all)
+                       if (ip_xfrm_me_harder(pskb))
+                               ret = NF_DROP;
+#endif
+
        }
        return ret;
 }
index e4d3ef17d45b610768f37e8fa2d026ee4eac6ba7..15aa3db8cb339fe534097881c2c63b28f78cbc3b 100644 (file)
@@ -245,14 +245,16 @@ nf_nat_local_fn(unsigned int hooknum,
                enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 
                if (ct->tuplehash[dir].tuple.dst.u3.ip !=
-                   ct->tuplehash[!dir].tuple.src.u3.ip
-#ifdef CONFIG_XFRM
-                   || ct->tuplehash[dir].tuple.dst.u.all !=
-                      ct->tuplehash[!dir].tuple.src.u.all
-#endif
-                   )
+                   ct->tuplehash[!dir].tuple.src.u3.ip) {
                        if (ip_route_me_harder(pskb, RTN_UNSPEC))
                                ret = NF_DROP;
+               }
+#ifdef CONFIG_XFRM
+               else if (ct->tuplehash[dir].tuple.dst.u.all !=
+                        ct->tuplehash[!dir].tuple.src.u.all)
+                       if (ip_xfrm_me_harder(pskb))
+                               ret = NF_DROP;
+#endif
        }
        return ret;
 }