Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vti[6]: fix packet tx through bpf_redirect() in XinY cases

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>

authored by

Nicolas Dichtel and committed by
Steffen Klassert
f1ed1026 03891f82

+55 -14
+1
net/ipv4/Kconfig
··· 303 303 304 304 config NET_IPVTI 305 305 tristate "Virtual (secure) IP: tunneling" 306 + depends on IPV6 || IPV6=n 306 307 select INET_TUNNEL 307 308 select NET_IP_TUNNEL 308 309 select XFRM
+29 -7
net/ipv4/ip_vti.c
··· 187 187 int mtu; 188 188 189 189 if (!dst) { 190 - struct rtable *rt; 190 + switch (skb->protocol) { 191 + case htons(ETH_P_IP): { 192 + struct rtable *rt; 191 193 192 - fl->u.ip4.flowi4_oif = dev->ifindex; 193 - fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; 194 - rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); 195 - if (IS_ERR(rt)) { 194 + fl->u.ip4.flowi4_oif = dev->ifindex; 195 + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; 196 + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); 197 + if (IS_ERR(rt)) { 198 + dev->stats.tx_carrier_errors++; 199 + goto tx_error_icmp; 200 + } 201 + dst = &rt->dst; 202 + skb_dst_set(skb, dst); 203 + break; 204 + } 205 + #if IS_ENABLED(CONFIG_IPV6) 206 + case htons(ETH_P_IPV6): 207 + fl->u.ip6.flowi6_oif = dev->ifindex; 208 + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; 209 + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); 210 + if (dst->error) { 211 + dst_release(dst); 212 + dst = NULL; 213 + dev->stats.tx_carrier_errors++; 214 + goto tx_error_icmp; 215 + } 216 + skb_dst_set(skb, dst); 217 + break; 218 + #endif 219 + default: 196 220 dev->stats.tx_carrier_errors++; 197 221 goto tx_error_icmp; 198 222 } 199 - dst = &rt->dst; 200 - skb_dst_set(skb, dst); 201 223 } 202 224 203 225 dst_hold(dst);
+25 -7
net/ipv6/ip6_vti.c
··· 450 450 int mtu; 451 451 452 452 if (!dst) { 453 - fl->u.ip6.flowi6_oif = dev->ifindex; 454 - fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; 455 - dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); 456 - if (dst->error) { 457 - dst_release(dst); 458 - dst = NULL; 453 + switch (skb->protocol) { 454 + case htons(ETH_P_IP): { 455 + struct rtable *rt; 456 + 457 + fl->u.ip4.flowi4_oif = dev->ifindex; 458 + fl->u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; 459 + rt = __ip_route_output_key(dev_net(dev), &fl->u.ip4); 460 + if (IS_ERR(rt)) 461 + goto tx_err_link_failure; 462 + dst = &rt->dst; 463 + skb_dst_set(skb, dst); 464 + break; 465 + } 466 + case htons(ETH_P_IPV6): 467 + fl->u.ip6.flowi6_oif = dev->ifindex; 468 + fl->u.ip6.flowi6_flags |= FLOWI_FLAG_ANYSRC; 469 + dst = ip6_route_output(dev_net(dev), NULL, &fl->u.ip6); 470 + if (dst->error) { 471 + dst_release(dst); 472 + dst = NULL; 473 + goto tx_err_link_failure; 474 + } 475 + skb_dst_set(skb, dst); 476 + break; 477 + default: 459 478 goto tx_err_link_failure; 460 479 } 461 - skb_dst_set(skb, dst); 462 480 } 463 481 464 482 dst_hold(dst);