LVS
lvs-devel
Google
 
Web LinuxVirtualServer.org

[PATCH] ipvs does not decrement IP ttl

To: lvs-devel@xxxxxxxxxxxxxxx
Subject: [PATCH] ipvs does not decrement IP ttl
Cc: dwip@xxxxxxxxxxxxxxxxxx
From: Dwip Banerjee <dwip@xxxxxxxxxxxxxxxxxx>
Date: Mon, 24 Oct 2016 12:17:58 -0500
We decrement the IP ttl in all the modes in order to prevent infinite
route loops. The changes were done based on Julian Anastasov's
suggestions in a prior thread.

The ttl based check/discard and the actual decrement are done in
__ip_vs_get_out_rt() and in __ip_vs_get_out_rt_v6(), for the IPv6
case. decrement_ttl() implements the actual functionality for the
two cases.


Signed-off-by: Dwip Banerjee <dwip@xxxxxxxxxxxxxxxxxx>
---
 net/netfilter/ipvs/ip_vs_xmit.c |   55 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 01d3d89..8b11e92 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -254,6 +254,55 @@ static inline bool ensure_mtu_is_adequate(struct 
netns_ipvs *ipvs, int skb_af,
        return true;
 }
 
+static inline bool decrement_ttl(int skb_af, struct sk_buff *skb)
+{
+#ifdef CONFIG_IP_VS_IPV6
+       if (skb_af == AF_INET6) {
+               struct ipv6hdr *hdr = ipv6_hdr(skb);
+               struct dst_entry *dst = skb_dst(skb);
+               struct net *net = dev_net(dst->dev);
+
+               /* check and decrement ttl */
+               if (hdr->hop_limit <= 1) {
+                       /* Force OUTPUT device used as source address */
+                       skb->dev = dst->dev;
+                       icmpv6_send(skb, ICMPV6_TIME_EXCEED,
+                                        ICMPV6_EXC_HOPLIMIT, 0);
+                       __IP6_INC_STATS(net, ip6_dst_idev(dst),
+                                       IPSTATS_MIB_INHDRERRORS);
+
+                       return false;
+               }
+
+               /* don't propagate ttl change to cloned packets */
+               if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
+                       return false;
+
+               hdr->hop_limit--;
+       } else
+#endif
+       {
+               struct iphdr  *iph = ip_hdr(skb);
+
+               if (iph->ttl <= 1) {
+                       /* Tell the sender its packet died... */
+                       __IP_INC_STATS(dev_net(skb_dst(skb)->dev),
+                                      IPSTATS_MIB_INHDRERRORS);
+                       icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
+                       return false;
+               }
+
+               /* don't propagate ttl change to cloned packets */
+               if (!skb_make_writable(skb, sizeof(struct iphdr)))
+                       return false;
+
+               /* Decrease ttl */
+               ip_decrease_ttl(iph);
+       }
+
+       return true;
+}
+
 /* Get route to destination or remote server */
 static int
 __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
@@ -326,6 +375,9 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, 
struct sk_buff *skb,
                return local;
        }
 
+       if (!decrement_ttl(skb_af, skb))
+               goto err_put;
+
        if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
                mtu = dst_mtu(&rt->dst);
        } else {
@@ -473,6 +525,9 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, 
struct sk_buff *skb,
                return local;
        }
 
+       if (!decrement_ttl(skb_af, skb))
+               goto err_put;
+
        /* MTU checking */
        if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
                mtu = dst_mtu(&rt->dst);
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

<Prev in Thread] Current Thread [Next in Thread>