Hello,

I've noticed that when running ping or traceroute with the -V option
the DNS lookup still occurs in routing table 0. When ping or traceroute
are run via route -Tx exec then the DNS lookup will happen in that
respective routing table.

This is somewhat similar to the arp/ndp message sent by Pierre Emeriaudi
a few days ago: http://marc.info/?l=openbsd-bugs&m=149211684314243&w=2

In the case of ping and traceroute it's due to the fact that the -V
option sets the route table via a setsockopt SO_RTABLE call and the DNS
lookup occurs using different sockets.

To me this behavior is counter-intuitive as I expect all traffic
generated by the process to be in the same routing table. In some cases
(VPNs) the names might not even be resolvable in routing table 0. I
realize that forcing the DNS lookups to occur in the same routing table
means that the name server address must be reachable in that routing
table as well. 

I propose to add a setrtable(2) to the -V option handling. The
setsockopt SO_RTABLE call is still required since the socket is created
before. The diff is at the end of this e-mail.

Thank you and best regards,
Andrei.

------> Here is the ping -V20 example where the DNS lookup occurs in
routing table 0:

user@laptop ~ $ ifconfig em0
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 2b:23:a9:31:f2:99
        index 1 priority 0 llprio 3
        groups: egress
        media: Ethernet autoselect (1000baseT full-duplex,rxpause,txpause)
        status: active
        inet 192.168.100.80 netmask 0xffffffe0 broadcast 192.168.100.95

user@laptop ~ $ ifconfig tun0
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> rdomain 20 mtu 1500
        description: OpenVPN tunnel
        index 15 priority 0 llprio 3
        groups: tun
        status: active
        inet 10.9.8.2 --> 10.9.8.1 netmask 0xffffffe0

user@laptop ~ $ ping -V20 -c 1 firefox.com 
PING firefox.com (63.245.213.17): 56 data bytes
64 bytes from 63.245.213.17: icmp_seq=0 ttl=53 time=200.590 ms

--- firefox.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 200.590/200.590/200.590/0.000 ms

user@laptop ~ $ doas tcpdump -s 2000 -nvi em0 '(udp and port 53) or icmp'
tcpdump: listening on em0, link-type EN10MB
15:30:34.400591 192.168.100.80.2174 > 192.168.100.255.53: [bad udp cksum 55ed! 
-> 861b] 24470+ A? firefox.com. (29) (ttl 64, id 3640, len 57)
15:30:34.401595 192.168.100.255.53 > 192.168.100.80.2174: [udp sum ok] 24470 
1/0/0 firefox.com. A 63.245.213.17 (45) (ttl 64, id 33685, len 73)
^C
5 packets received by filter
0 packets dropped by kernel

user@laptop ~ $ doas tcpdump -s 2000 -nvi tun0 '(udp and port 53) or icmp'
tcpdump: listening on tun0, link-type LOOP
15:30:34.401968 10.9.8.2 > 63.245.213.17: icmp: echo request (id:1f2d seq:0) 
[icmp cksum ok] (ttl 255, id 7719, len 84)
15:30:34.602476 63.245.213.17 > 10.9.8.2: icmp: echo reply (id:1f2d seq:0) 
[icmp cksum ok] (ttl 53, id 10522, len 84)
^C
2 packets received by filter
0 packets dropped by kernel

------> And here is the route -T20 exec example where the DNS lookup
occurs in routing table 20:

user@laptop ~ $ route -T20 exec ping -c 1 firefox.com
PING firefox.com (63.245.213.17): 56 data bytes
64 bytes from 63.245.213.17: icmp_seq=0 ttl=53 time=200.708 ms

--- firefox.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 200.708/200.708/200.708/0.000 ms

user@laptop ~ $ doas tcpdump -s 2000 -nvi em0 '(udp and port 53) or icmp'
tcpdump: listening on em0, link-type EN10MB
^C
6 packets received by filter
0 packets dropped by kernel

user@laptop ~ $ doas tcpdump -s 2000 -nvi tun0 '(udp and port 53) or icmp'
tcpdump: listening on tun0, link-type LOOP
15:32:00.173028 10.9.8.2.18641 > 192.168.100.255.53: [udp sum ok] 50385+ A? 
firefox.com. (29) (ttl 64, id 22691, len 57)
15:32:00.283214 192.168.100.255.53 > 10.9.8.2.18641: [udp sum ok] 50385 1/0/0 
firefox.com. A 63.245.213.17 (45) (ttl 64, id 10940, len 73)
15:32:00.283510 10.9.8.2 > 63.245.213.17: icmp: echo request (id:4961 seq:0) 
[icmp cksum ok] (ttl 255, id 28996, len 84)
15:32:00.484135 63.245.213.17 > 10.9.8.2: icmp: echo reply (id:4961 seq:0) 
[icmp cksum ok] (ttl 53, id 33835, len 84)
^C
4 packets received by filter
0 packets dropped by kernel

------> Here is ping -V20 behavior with the added setrtable(2) call:

user@laptop ~ $ ping -V20 -c 1 firefox.com
PING firefox.com (63.245.213.17): 56 data bytes
64 bytes from 63.245.213.17: icmp_seq=0 ttl=53 time=200.408 ms

--- firefox.com ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 200.408/200.408/200.408/0.000 ms

user@laptop ~ $ doas tcpdump -s 2000 -nvi em0 '(udp and port 53) or icmp'
tcpdump: listening on em0, link-type EN10MB
^C
6 packets received by filter
0 packets dropped by kernel

user@laptop ~ $ doas tcpdump -s 2000 -nvi tun0 '(udp and port 53) or icmp'
tcpdump: listening on tun0, link-type LOOP
15:54:41.747041 10.9.8.2.10544 > 192.168.100.255.53: [udp sum ok] 34257+ A? 
firefox.com. (29) (ttl 64, id 52528, len 57)
15:54:41.772777 192.168.100.255.53 > 10.9.8.2.10544: [udp sum ok] 34257 1/0/0 
firefox.com. A 63.245.213.17 (45) (ttl 64, id 39456, len 73)
15:54:41.773452 10.9.8.2 > 63.245.213.17: icmp: echo request (id:f0af seq:0) 
[icmp cksum ok] (ttl 255, id 17343, len 84)
15:54:41.973719 63.245.213.17 > 10.9.8.2: icmp: echo reply (id:f0af seq:0) 
[icmp cksum ok] (ttl 53, id 65509, len 84)
^C
4 packets received by filter
0 packets dropped by kernel

------> And the diff:

diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index 36c3a8237d8..fbccfed10fa 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -240,7 +240,8 @@ or a number in either hex or decimal.
 .Pq IPv4 only
 Use the specified time-to-live.
 .It Fl V Ar rtable
-Set the routing table to be used for outgoing packets.
+Set the routing table to be used for outgoing packets. Any required DNS
+lookups will also occur in the specified routing table.
 .It Fl v
 Verbose output.
 ICMP packets other than
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 8592d7d539f..457a01b8b70 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -413,6 +413,8 @@ main(int argc, char *argv[])
                        if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
                            sizeof(rtableid)) == -1)
                                err(1, "setsockopt SO_RTABLE");
+                       if (setrtable(rtableid) == -1)
+                               err(1, "setrtable");
                        break;
                case 'v':
                        options |= F_VERBOSE;
diff --git a/usr.sbin/traceroute/traceroute.8 b/usr.sbin/traceroute/traceroute.8
index 4422a2d7c0a..771027b3d99 100644
--- a/usr.sbin/traceroute/traceroute.8
+++ b/usr.sbin/traceroute/traceroute.8
@@ -198,7 +198,8 @@ and
 .Cm throughput .
 This option is not available for IPv6.
 .It Fl V Ar rtable
-Set the routing table to be used.
+Set the routing table to be used. Any required DNS lookups will also
+occur in the specified routing table.
 .It Fl v
 Verbose output.
 Received ICMP packets other than
diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c
index 6b0909fbd71..d08efae9e36 100644
--- a/usr.sbin/traceroute/traceroute.c
+++ b/usr.sbin/traceroute/traceroute.c
@@ -530,6 +530,8 @@ main(int argc, char *argv[])
                        if (setsockopt(rcvsock, SOL_SOCKET, SO_RTABLE,
                            &rtableid, sizeof(rtableid)) == -1)
                                err(1, "setsockopt SO_RTABLE");
+                       if (setrtable(rtableid) == -1)
+                               err(1, "setrtable");
                        break;
                case 'w':
                        waittime = strtonum(optarg, 2, INT_MAX, &errstr);
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index 36c3a8237d8..fbccfed10fa 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -240,7 +240,8 @@ or a number in either hex or decimal.
 .Pq IPv4 only
 Use the specified time-to-live.
 .It Fl V Ar rtable
-Set the routing table to be used for outgoing packets.
+Set the routing table to be used for outgoing packets. Any required DNS
+lookups will also occur in the specified routing table.
 .It Fl v
 Verbose output.
 ICMP packets other than
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 8592d7d539f..457a01b8b70 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -413,6 +413,8 @@ main(int argc, char *argv[])
                        if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
                            sizeof(rtableid)) == -1)
                                err(1, "setsockopt SO_RTABLE");
+                       if (setrtable(rtableid) == -1)
+                               err(1, "setrtable");
                        break;
                case 'v':
                        options |= F_VERBOSE;
diff --git a/usr.sbin/traceroute/traceroute.8 b/usr.sbin/traceroute/traceroute.8
index 4422a2d7c0a..771027b3d99 100644
--- a/usr.sbin/traceroute/traceroute.8
+++ b/usr.sbin/traceroute/traceroute.8
@@ -198,7 +198,8 @@ and
 .Cm throughput .
 This option is not available for IPv6.
 .It Fl V Ar rtable
-Set the routing table to be used.
+Set the routing table to be used. Any required DNS lookups will also
+occur in the specified routing table.
 .It Fl v
 Verbose output.
 Received ICMP packets other than
diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c
index 6b0909fbd71..d08efae9e36 100644
--- a/usr.sbin/traceroute/traceroute.c
+++ b/usr.sbin/traceroute/traceroute.c
@@ -530,6 +530,8 @@ main(int argc, char *argv[])
                        if (setsockopt(rcvsock, SOL_SOCKET, SO_RTABLE,
                            &rtableid, sizeof(rtableid)) == -1)
                                err(1, "setsockopt SO_RTABLE");
+                       if (setrtable(rtableid) == -1)
+                               err(1, "setrtable");
                        break;
                case 'w':
                        waittime = strtonum(optarg, 2, INT_MAX, &errstr);

Reply via email to