Browse code

Fix gateway detection with OpenBSD routing domains

When OpenVPN is started using a non-default routing table on OpenBSD
(e.g., with 'route -T10 exec openvpn ...'), it hangs forever trying to
read its default gateway from a PF_ROUTE socket. This is because
rtm_tableid is not being initialised after bzeroing the rt_msghdr we
write to the socket, so we end up asking the kernel for the default
route in routing table 0.

By default, the OpenBSD kernel will not respond to requests for routing
table 0 from a process running in a different routing table, and even
if it did, it would give us the wrong default gateway.

The solution here is to set rtm_tableid to the value returned by
getrtable(2), which always succeeds and returns the calling process's
current routing table.

This patch makes the test suite (without a t_client.rc) pass when run
in a non-default routing table, where it would fail previously. It has
also been successfully tested in client mode against both git master
and OpenVPN 2.4.1 from ports on an OpenBSD -current system.

Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20170413173129.87367-1-steven@steven-mcdonald.id.au>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14461.html

Signed-off-by: Gert Doering <gert@greenie.muc.de>

Steven McDonald authored on 2017/04/14 02:31:29
Showing 1 changed files
... ...
@@ -3597,6 +3597,9 @@ get_default_gateway(struct route_gateway_info *rgi)
3597 3597
     rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
3598 3598
     rtm.rtm_version = RTM_VERSION;
3599 3599
     rtm.rtm_seq = ++seq;
3600
+#ifdef TARGET_OPENBSD
3601
+    rtm.rtm_tableid = getrtable();
3602
+#endif
3600 3603
     rtm.rtm_addrs = rtm_addrs;
3601 3604
 
3602 3605
     so_dst.sa_family = AF_INET;
... ...
@@ -3812,6 +3815,9 @@ get_default_gateway_ipv6(struct route_ipv6_gateway_info *rgi6,
3812 3812
     rtm.rtm_flags = RTF_UP;
3813 3813
     rtm.rtm_version = RTM_VERSION;
3814 3814
     rtm.rtm_seq = ++seq;
3815
+#ifdef TARGET_OPENBSD
3816
+    rtm.rtm_tableid = getrtable();
3817
+#endif
3815 3818
 
3816 3819
     so_dst.sin6_family = AF_INET6;
3817 3820
     so_mask.sin6_family = AF_INET6;