vti[6]: fix packet tx through bpf_redirect() in XinY cases
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Tue, 4 Feb 2020 16:00:27 +0000 (17:00 +0100)
committerCosmin Tanislav <demonsingur@gmail.com>
Thu, 16 May 2024 07:58:23 +0000 (10:58 +0300)
commit f1ed10264ed6b66b9cd5e8461cffce69be482356 upstream.

I forgot the 4in6/6in4 cases in my previous patch. Let's fix them.

Fixes: 95224166a903 ("vti[6]: fix packet tx through bpf_redirect()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/ipv4/Kconfig
net/ipv4/ip_vti.c
net/ipv6/ip6_vti.c

index f48fe6fc7e8c413d7d7e4d7d37d1d859a566e8fb..4abc4ba733bf0312cc95b4dfbcd6756d6f06dcab 100644 (file)
@@ -297,6 +297,7 @@ config SYN_COOKIES
 
 config NET_IPVTI
        tristate "Virtual (secure) IP: tunneling"
+       depends on IPV6 || IPV6=n
        select INET_TUNNEL
        select NET_IP_TUNNEL
        depends on INET_XFRM_MODE_TUNNEL
index 36d9941a99d0267ce16d4e88d3ee03b379c3dbdc..ceaeb65b079b6aa39bca024ddc501dd17585f0c7 100644 (file)
@@ -208,17 +208,39 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
        int mtu;
 
        if (!dst) {
-               struct rtable *rt;
-
-               fl->u.ip4.flowi4_oif = dev->ifindex;
-               fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
-               rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
-               if (IS_ERR(rt)) {
+               switch (skb->protocol) {
+               case htons(ETH_P_IP): {
+                       struct rtable *rt;
+
+                       fl->u.ip4.flowi4_oif = dev->ifindex;
+                       fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+                       rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
+                       if (IS_ERR(rt)) {
+                               dev->stats.tx_carrier_errors++;
+                               goto tx_error_icmp;
+                       }
+                       dst = &rt->dst;
+                       skb_dst_set(skb, dst);
+                       break;
+               }
+#if IS_ENABLED(CONFIG_IPV6)
+               case htons(ETH_P_IPV6):
+                       fl->u.ip6.flowi6_oif = dev->ifindex;
+                       fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+                       dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
+                       if (dst->error) {
+                               dst_release(dst);
+                               dst = NULL;
+                               dev->stats.tx_carrier_errors++;
+                               goto tx_error_icmp;
+                       }
+                       skb_dst_set(skb, dst);
+                       break;
+#endif
+               default:
                        dev->stats.tx_carrier_errors++;
                        goto tx_error_icmp;
                }
-               dst = &rt->dst;
-               skb_dst_set(skb, dst);
        }
 
        dst_hold(dst);
index 81a5ad08d49ad28aefb843279a5921c25098556e..8baae7abca8a586e99b18a017d61b42021cf1964 100644 (file)
@@ -454,15 +454,33 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        int mtu;
 
        if (!dst) {
-               fl->u.ip6.flowi6_oif = dev->ifindex;
-               fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
-               dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
-               if (dst->error) {
-                       dst_release(dst);
-                       dst = NULL;
+               switch (skb->protocol) {
+               case htons(ETH_P_IP): {
+                       struct rtable *rt;
+
+                       fl->u.ip4.flowi4_oif = dev->ifindex;
+                       fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+                       rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4);
+                       if (IS_ERR(rt))
+                               goto tx_err_link_failure;
+                       dst = &rt->dst;
+                       skb_dst_set(skb, dst);
+                       break;
+               }
+               case htons(ETH_P_IPV6):
+                       fl->u.ip6.flowi6_oif = dev->ifindex;
+                       fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC;
+                       dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6);
+                       if (dst->error) {
+                               dst_release(dst);
+                               dst = NULL;
+                               goto tx_err_link_failure;
+                       }
+                       skb_dst_set(skb, dst);
+                       break;
+               default:
                        goto tx_err_link_failure;
                }
-               skb_dst_set(skb, dst);
        }
 
        dst_hold(dst);