From 1ac7931b5afa6b3c521d23f1847476ab6384eb10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adam=20Ciarcin=CC=81ski?= <adam@netbsd.org>
Date: Thu, 2 Aug 2018 16:17:56 +0200
Subject: [PATCH] Fix subnet topology on NetBSD.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Adam Ciarciński <adam@netbsd.org>
---
 src/openvpn/tun.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index 1c7e51d9..7fe4a062 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -845,7 +845,7 @@ delete_route_connected_v6_net(struct tuntap *tt,
 #endif /* if defined(_WIN32) || defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD) */
 
 #if defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)  \
-    || defined(TARGET_OPENBSD)
+    || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD)
 /* we can't use true subnet mode on tun on all platforms, as that
  * conflicts with IPv6 (wants to use ND then, which we don't do),
  * but the OSes want "a remote address that is different from ours"
@@ -1233,6 +1233,7 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
     }
 
 #elif defined(TARGET_NETBSD)
+    in_addr_t remote_end;           /* for "virtual" subnet topology */
 
     if (tun)
     {
@@ -1243,8 +1244,8 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
     else if (tt->topology == TOP_SUBNET)
     {
         argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up", IFCONFIG_PATH,
-                    ifname, ifconfig_local, ifconfig_local, tun_mtu,
-                    ifconfig_remote_netmask);
+                    ifname, ifconfig_local, print_in_addr_t(remote_end, 0, &gc),
+                    tun_mtu, ifconfig_remote_netmask);
     }
     else
     {
@@ -1260,6 +1261,18 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
     argv_msg(M_INFO, &argv);
     openvpn_execve_check(&argv, es, S_FATAL, "NetBSD ifconfig failed");
 
+    /* Add a network route for the local tun interface */
+    if (!tun && tt->topology == TOP_SUBNET)
+    {
+        struct route_ipv4 r;
+        CLEAR(r);
+        r.flags = RT_DEFINED;
+        r.network = tt->local & tt->remote_netmask;
+        r.netmask = tt->remote_netmask;
+        r.gateway = remote_end;
+        add_route(&r, tt, 0, NULL, es);
+    }
+
 #elif defined(TARGET_DARWIN)
     /*
      * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD...
-- 
2.18.0

