[NETFILTER]: Fix xfrm lookup in ip_route_me_harder/ip6_route_me_harder
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / netfilter.c
index ae0779d82c5d2191744da417b277fdd3c8fbbda6..4c637a1cbd23466934b0c4253b84325bce2eba56 100644 (file)
@@ -7,11 +7,13 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 
+#include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/icmp.h>
 #include <net/route.h>
-#include <linux/ip.h>
+#include <net/xfrm.h>
+#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)
@@ -33,7 +35,6 @@ int ip_route_me_harder(struct sk_buff **pskb)
 #ifdef CONFIG_IP_ROUTE_FWMARK
                fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-               fl.proto = iph->protocol;
                if (ip_route_output_key(&rt, &fl) != 0)
                        return -1;
 
@@ -60,6 +61,13 @@ int ip_route_me_harder(struct sk_buff **pskb)
        if ((*pskb)->dst->error)
                return -1;
 
+#ifdef CONFIG_XFRM
+       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+           xfrm_decode_session(*pskb, &fl, AF_INET) == 0)
+               if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
+                       return -1;
+#endif
+
        /* Change in oif may mean change in hh_len. */
        hh_len = (*pskb)->dst->dev->hard_header_len;
        if (skb_headroom(*pskb) < hh_len) {