ipv6: Fix handling of LLA with VRF and sockets bound to VRF
authorDavid Ahern <dsahern@gmail.com>
Wed, 12 Dec 2018 23:27:38 +0000 (15:27 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 15 Dec 2018 19:36:14 +0000 (11:36 -0800)
A recent commit allows sockets bound to a VRF to receive ipv6 link local
packets. However, it only works for UDP and worse TCP connection attempts
to the LLA with the only listener bound to the VRF just hang where as
before the client gets a reset and connection refused. Fix by adjusting
ir_iif for LL addresses and packets received through a device enslaved
to a VRF.

Fixes: 6f12fa775530 ("vrf: mark skb for multicast or link-local as enslaved to VRF")
Reported-by: Donald Sharp <sharpd@cumulusnetworks.com>
Cc: Mike Manning <mmanning@vyatta.att-mail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/tcp_ipv6.c

index a3f559162521543f948894bd6905342ff2401d6c..b81eb7cb815edfaf9b0a09f2a677a5a2227adf1e 100644 (file)
@@ -737,6 +737,7 @@ static void tcp_v6_init_req(struct request_sock *req,
                            const struct sock *sk_listener,
                            struct sk_buff *skb)
 {
+       bool l3_slave = ipv6_l3mdev_skb(TCP_SKB_CB(skb)->header.h6.flags);
        struct inet_request_sock *ireq = inet_rsk(req);
        const struct ipv6_pinfo *np = inet6_sk(sk_listener);
 
@@ -744,7 +745,7 @@ static void tcp_v6_init_req(struct request_sock *req,
        ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
 
        /* So that link locals have meaning */
-       if (!sk_listener->sk_bound_dev_if &&
+       if ((!sk_listener->sk_bound_dev_if || l3_slave) &&
            ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
                ireq->ir_iif = tcp_v6_iif(skb);