[Openvpn-devel,v2] Fix netbits setting (in TAP mode) for IPv6 on Windows.

Message ID 20200915094101.86470-1-gert@greenie.muc.de
State Accepted
Headers show
Series [Openvpn-devel,v2] Fix netbits setting (in TAP mode) for IPv6 on Windows. | expand

Commit Message

Gert Doering Sept. 14, 2020, 11:41 p.m. UTC
For TUN interfaces, the IPv6 address needs to be configured with
"address/128" and a local subnet route is needed, pointing to our
fake gateway fe80::8.  There is no ethernet headers or ND outside
the tun/tap interface, so anything but fe80::8 is not resolvable.

For TAP interfaces, the proper subnet mask (netbits) must be configured,
and no connected route to "our local host address" must be configured,
to make make IPv6 ND work inside the local subnet.

Our code was nicely consistent in doing the same thing in tun.c
("gui/openvpn running with admin privileges") and in the requests
to the interactive service ("gui running with user privs").  Fix in
both places.

On tun close, symmetric to addition, remove the on-link subnet route only
for "tun" interfaces.  Address removal works without specifying netbits.

While at it, extend do_address_service() to actually log both IPv4
and IPv6 addresses requested via it.

Tested on Win10/64.

v2:
  - change logging to use D_IFCONFIG
  - fix whitespace on "?" operator

Reported-By: Laurent Fasnacht <l@libres.ch>
Reported-By: Klara Mall <klara.mall@kit.edu>
Trac: #1054

Signed-off-by: Gert Doering <gert@greenie.muc.de>
---
 src/openvpn/errlevel.h |  1 +
 src/openvpn/tun.c      | 32 +++++++++++++++++++++++++-------
 2 files changed, 26 insertions(+), 7 deletions(-)

Comments

Lev Stipakov Sept. 15, 2020, 1:16 a.m. UTC | #1
Compiled with MSVC and ipv4/tun tested.

Code looks good and Gert is IPv6 master.

Acked-by: Lev Stipakov <lstipakov@gmail.com>
Gert Doering Sept. 15, 2020, 4:46 a.m. UTC | #2
Patch has been applied to the master and release/2.5 branch.

(Due to build pains I have not tested this on Win7 yet, but
will do so with the upcoming beta5 installer - I do not expect
any surprises, though)

commit 81b6a7e75b343e324a44b4476c89c596d7b6c74b (master)
commit 859952560aff6d4442cdfa0c41ced494e9dc397e (release/2.5)
Author: Gert Doering
Date:   Tue Sep 15 11:41:01 2020 +0200

     Fix netbits setting (in TAP mode) for IPv6 on Windows.

     Signed-off-by: Gert Doering <gert@greenie.muc.de>
     Acked-by: Lev Stipakov <lstipakov@gmail.com>
     Message-Id: <20200915094101.86470-1-gert@greenie.muc.de>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg21008.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering

Patch

diff --git a/src/openvpn/errlevel.h b/src/openvpn/errlevel.h
index e448fc37..5663f841 100644
--- a/src/openvpn/errlevel.h
+++ b/src/openvpn/errlevel.h
@@ -91,6 +91,7 @@ 
 #define D_OSBUF              LOGLEV(3, 43, 0)        /* show socket/tun/tap buffer sizes */
 #define D_PS_PROXY           LOGLEV(3, 44, 0)        /* messages related to --port-share option */
 #define D_PF_INFO            LOGLEV(3, 45, 0)        /* packet filter informational messages */
+#define D_IFCONFIG           LOGLEV(3, 0,  0)        /* show ifconfig info (don't mute) */
 
 #define D_SHOW_PARMS         LOGLEV(4, 50, 0)        /* show all parameters on program initiation */
 #define D_SHOW_OCC           LOGLEV(4, 51, 0)        /* show options compatibility string */
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index fde94294..faa02504 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -115,11 +115,17 @@  do_address_service(const bool add, const short family, const struct tuntap *tt)
     {
         addr.address.ipv4.s_addr = htonl(tt->local);
         addr.prefix_len = netmask_to_netbits2(tt->adapter_netmask);
+        msg(D_IFCONFIG, "INET address service: %s %s/%d",
+            add ? "add" : "remove",
+            print_in_addr_t(tt->local, 0, &gc), addr.prefix_len);
     }
     else
     {
         addr.address.ipv6 = tt->local_ipv6;
-        addr.prefix_len = tt->netbits_ipv6;
+        addr.prefix_len = (tt->type == DEV_TYPE_TUN) ? 128 : tt->netbits_ipv6;
+        msg(D_IFCONFIG, "INET6 address service: %s %s/%d",
+            add ? "add" : "remove",
+            print_in6_addr(tt->local_ipv6, 0, &gc), addr.prefix_len);
     }
 
     if (!send_msg_iservice(pipe, &addr, sizeof(addr), &ack, "TUN"))
@@ -1088,24 +1094,36 @@  do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu,
     else if (tt->options.msg_channel)
     {
         do_address_service(true, AF_INET6, tt);
-        add_route_connected_v6_net(tt, es);
+        if (tt->type == DEV_TYPE_TUN)
+        {
+            add_route_connected_v6_net(tt, es);
+        }
         do_dns_service(true, AF_INET6, tt);
         do_set_mtu_service(tt, AF_INET6, tun_mtu);
     }
     else
     {
         /* example: netsh interface ipv6 set address interface=42
-         *                  2001:608:8003::d store=active
+         *                  2001:608:8003::d/bits store=active
          */
         char iface[64];
 
+        /* in TUN mode, we only simulate a subnet, so the interface
+         * is configured with /128 + a route to fe80::8.  In TAP mode,
+         * the correct netbits must be set, and no on-link route
+         */
+        int netbits = (tt->type == DEV_TYPE_TUN) ? 128 : tt->netbits_ipv6;
+
         openvpn_snprintf(iface, sizeof(iface), "interface=%lu",
                          tt->adapter_index);
-        argv_printf(&argv, "%s%s interface ipv6 set address %s %s store=active",
+        argv_printf(&argv, "%s%s interface ipv6 set address %s %s/%d store=active",
                     get_win_sys_path(), NETSH_PATH_SUFFIX, iface,
-                    ifconfig_ipv6_local);
+                    ifconfig_ipv6_local, netbits);
         netsh_command(&argv, 4, M_FATAL);
-        add_route_connected_v6_net(tt, es);
+        if (tt->type == DEV_TYPE_TUN)
+        {
+            add_route_connected_v6_net(tt, es);
+        }
         /* set ipv6 dns servers if any are specified */
         netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, ifname);
         windows_set_mtu(tt->adapter_index, AF_INET6, tun_mtu);
@@ -6688,7 +6706,7 @@  netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc
         netsh_command(&argv, 1, M_WARN);
     }
 
-    if (ipv6)
+    if (ipv6 && tt->type == DEV_TYPE_TUN)
     {
         delete_route_connected_v6_net(tt);
     }