net: allow traceroute with a specified interface in a vrf
authorMike Manning <mmanning@vyatta.att-mail.com>
Fri, 26 Oct 2018 11:24:35 +0000 (12:24 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 26 Oct 2018 23:03:08 +0000 (16:03 -0700)
Traceroute executed in a vrf succeeds if no device is given or if the
vrf is given as the device, but fails if the interface is given as the
device. This is for default UDP probes, it succeeds for TCP SYN or ICMP
ECHO probes. As the skb bound dev is the interface and the sk dev is
the vrf, sk lookup fails for ICMP_DEST_UNREACH and ICMP_TIME_EXCEEDED
messages. The solution is for the secondary dev to be passed so that
the interface is available for the device match to succeed, in the same
way as is already done for non-error cases.

Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/udp.c
net/ipv6/udp.c

index 7e048288fcabb1794eb04732e5154a5b7af0c92e..ca3ed931f2a91479940d1c2dbe55870aef2df96f 100644 (file)
@@ -609,8 +609,8 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        struct net *net = dev_net(skb->dev);
 
        sk = __udp4_lib_lookup(net, iph->daddr, uh->dest,
-                              iph->saddr, uh->source, skb->dev->ifindex, 0,
-                              udptable, NULL);
+                              iph->saddr, uh->source, skb->dev->ifindex,
+                              inet_sdif(skb), udptable, NULL);
        if (!sk) {
                __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
                return; /* No socket for error */
index 06d17ff3562f012e0a61594a1e9c69cd92d4459c..d2d97d07ef27a4e75f236e6a530894c0b3609a58 100644 (file)
@@ -478,7 +478,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct net *net = dev_net(skb->dev);
 
        sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
-                              inet6_iif(skb), 0, udptable, skb);
+                              inet6_iif(skb), inet6_sdif(skb), udptable, skb);
        if (!sk) {
                __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
                                  ICMP6_MIB_INERRORS);