[PATCH] NETFILTER: Honour source routing for LVS-NAT
authorPatrick McHardy <kaber@trash.net>
Fri, 17 Nov 2006 05:35:48 +0000 (06:35 +0100)
committerChris Wright <chrisw@sous-sol.org>
Sat, 2 Dec 2006 00:12:35 +0000 (16:12 -0800)
For policy routing, packets originating from this machine itself may be
routed differently to packets passing through. We want this packet to be
routed as if it came from this machine itself. So re-compute the routing
information using ip_route_me_harder().

This patch is derived from work by Ken Brownfield

This patch (-stable version) also includes commit
b4c4ed175ff0ee816df48571cfa9b73f521964b6 ([NETFILTER]: add type parameter
to ip_route_me_harder), which is a precondition for the fix.

Cc: Ken Brownfield <krb@irridia.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
include/linux/netfilter_ipv4.h
net/ipv4/ipvs/ip_vs_core.c
net/ipv4/netfilter.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/iptable_mangle.c

index ce02c984f3bae354307b3a398c62c166dcc8d83b..5b63a231a76bb14bad1b17960c6da150bacd9e1b 100644 (file)
@@ -77,7 +77,7 @@ enum nf_ip_hook_priorities {
 #define SO_ORIGINAL_DST 80
 
 #ifdef __KERNEL__
-extern int ip_route_me_harder(struct sk_buff **pskb);
+extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type);
 extern int ip_xfrm_me_harder(struct sk_buff **pskb);
 extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
                                   unsigned int dataoff, u_int8_t protocol);
index 3f47ad8e1cad1c7f8165b6e5c003a3f919711e4a..f5946352cc86e3c085bd59106589384dc04571b0 100644 (file)
@@ -813,6 +813,16 @@ ip_vs_out(unsigned int hooknum, struct sk_buff **pskb,
        skb->nh.iph->saddr = cp->vaddr;
        ip_send_check(skb->nh.iph);
 
+       /* For policy routing, packets originating from this
+        * machine itself may be routed differently to packets
+        * passing through.  We want this packet to be routed as
+        * if it came from this machine itself.  So re-compute
+        * the routing information.
+        */
+       if (ip_route_me_harder(pskb, RTN_LOCAL) != 0)
+               goto drop;
+       skb = *pskb;
+
        IP_VS_DBG_PKT(10, pp, skb, 0, "After SNAT");
 
        ip_vs_out_stats(cp, skb);
index 6a9e34b794bc7d3c495566045ef2c38bad3a0c5d..327ba371863b31f1f29b0c564fce0ea2691f679d 100644 (file)
@@ -8,7 +8,7 @@
 #include <net/ip.h>
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
-int ip_route_me_harder(struct sk_buff **pskb)
+int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type)
 {
        struct iphdr *iph = (*pskb)->nh.iph;
        struct rtable *rt;
@@ -16,10 +16,13 @@ int ip_route_me_harder(struct sk_buff **pskb)
        struct dst_entry *odst;
        unsigned int hh_len;
 
+       if (addr_type == RTN_UNSPEC)
+               addr_type = inet_addr_type(iph->saddr);
+
        /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
         * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
         */
-       if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
+       if (addr_type == RTN_LOCAL) {
                fl.nl_u.ip4_u.daddr = iph->daddr;
                fl.nl_u.ip4_u.saddr = iph->saddr;
                fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
@@ -156,7 +159,7 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info)
                if (!(iph->tos == rt_info->tos
                      && iph->daddr == rt_info->daddr
                      && iph->saddr == rt_info->saddr))
-                       return ip_route_me_harder(pskb);
+                       return ip_route_me_harder(pskb, RTN_UNSPEC);
        }
        return 0;
 }
index 6db485f2cd54bd3e650f03627a8198f7505e31b7..c508544d7a725df201d758c81237ff7ce1d0d4c9 100644 (file)
@@ -275,7 +275,8 @@ ip_nat_local_fn(unsigned int hooknum,
                       ct->tuplehash[!dir].tuple.src.u.all
 #endif
                    )
-                       return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+                       if (ip_route_me_harder(pskb, RTN_UNSPEC))
+                               ret = NF_DROP;
        }
        return ret;
 }
index 4e7998beda635970bacb483dae78052180d649c8..f7b8906c30d3f06d6aba932a16ed5fa50243d35e 100644 (file)
@@ -157,7 +157,8 @@ ipt_local_hook(unsigned int hook,
                || (*pskb)->nfmark != nfmark
 #endif
                || (*pskb)->nh.iph->tos != tos))
-               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
+               if (ip_route_me_harder(pskb, RTN_UNSPEC))
+                       ret = NF_DROP;
 
        return ret;
 }