Skip to contentSkip to conversation

Handle --dhcp-option DNS6 on Windows using netsh

PATCH Superseded Selva Nair 3 participants 10 messages Nov 20, 2016 – Nov 22, 2016

lore
Share & tools
lore

Selva Nair

author
#0 lore raw

PATCH 1/1 Handle --dhcp-option DNS6 on Windows using netsh

TODO: set dns servers using the interactive service

---
 doc/openvpn.8         |  5 ++---
 src/openvpn/options.c | 22 ++++++++++++++--------
 src/openvpn/tun.c     | 30 ++++++++++++++++++++++++++++++
 src/openvpn/tun.h     |  3 +++
 4 files changed, 49 insertions(+), 11 deletions(-)
doc/openvpn.8 +2 -3
index d454a36..171bd72 100644
@@ -5634,13 +5634,12 @@ this option to set secondary DNS server addresses.
 Set primary domain name server IPv6 address.  Repeat
 this option to set secondary DNS server IPv6 addresses.
 
-Note: currently this is somewhat of a placeholder option - it is
-understood, but OpenVPN has no code to tell Windows about it (the
+Note: currently this is handled using netsh and requires admin rights (the
 existing DHCP code can only do IPv4 DHCP, and that protocol only
 permits IPv4 addresses anywhere).  The option will be put into the
 environment, so an
 .B \-\-up
-script could act upon it.
+script could act upon it if needed.
 
 .B WINS addr \-\-
 Set primary WINS server address (NetBIOS over TCP/IP Name Server).
src/openvpn/options.c +14 -8
index 9e828d8..97be7fa 100644
@@ -6407,14 +6407,20 @@ add_option (struct options *options,
 	{
 	  dhcp_option_address_parse ("DNS", p[2], o->dns, &o->dns_len, msglevel);
 	}
-      else if (streq (p[1], "DNS6") && p[2])
-	{
-	  /* this is somewhat of a placeholder - we understand the option,
-	   * but cannot act upon it - so we'll just accept it and put it
-	   * into the environment, as we would do on all non-win32 platforms
-	   */
-	  foreign_option (options, p, 3, es);
-	}
+      else if (streq (p[1], "DNS6") && p[2] && ipv6_addr_safe(p[2]))
+        {
+          struct in6_addr addr;
+          foreign_option (options, p, 3, es);
+          if (o->dns6_len >= N_DHCP_ADDR)
+            {
+              msg (msglevel, "--dhcp-option DNS6: maximum of %d dns servers can be specified",
+	           N_DHCP_ADDR);
+            }
+          else if (get_ipv6_addr (p[2], &addr, NULL, msglevel))
+            {
+              o->dns6[o->dns6_len++] = addr;
+            }
+        }
       else if (streq (p[1], "WINS") && p[2])
 	{
 	  dhcp_option_address_parse ("WINS", p[2], o->wins, &o->wins_len, msglevel);
src/openvpn/tun.c +30 -0
index 77ae72f..5950906 100644
@@ -68,6 +68,9 @@ static void netsh_ifconfig (const struct tuntap_options *to,
 			    const in_addr_t ip,
 			    const in_addr_t netmask,
 			    const unsigned int flags);
+static void netsh_dns6_servers (const struct in6_addr *addr_list,
+                                const int addr_len,
+                                const char *flex_name);
 static void netsh_command (const struct argv *a, int n, int msglevel);
 
 static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc);
@@ -1375,6 +1378,7 @@ do_ifconfig (struct tuntap *tt,
 	if (tt->options.msg_channel)
 	  {
 	    do_address_service (true, AF_INET6, tt);
+            /* TODO: do_dns6_service() */
 	  }
 	else
 	  {
@@ -1388,6 +1392,8 @@ do_ifconfig (struct tuntap *tt,
 			 iface,
 			 ifconfig_ipv6_local );
 	    netsh_command (&argv, 4, M_FATAL);
+            /* set ipv6 dns servers if any are specified */
+	    netsh_dns6_servers(tt->options.dns6, tt->options.dns6_len, actual);
 	  }
 
 	/* explicit route needed */
@@ -4618,6 +4624,30 @@ ip_addr_member_of (const in_addr_t addr, const IP_ADDR_STRING *ias)
 }
 
 static void
+netsh_dns6_servers (const struct in6_addr *addr_list,
+                    const int addr_len,
+                    const char *flex_name)
+{
+    struct gc_arena gc = gc_new ();
+    struct argv argv = argv_new ();
+
+    for (int i = 0; i < addr_len; ++i)
+    {
+        const char *fmt = (i == 0) ?
+            "%s%sc interface ipv6 set dnsservers %s static %s validate=no"
+	    : "%s%sc interface ipv6 add dnsservers %s %s validate=no";
+        argv_printf (&argv, fmt, get_win_sys_path(),
+                     NETSH_PATH_SUFFIX, flex_name,
+                     print_in6_addr (addr_list[i], 0, &gc));
+        /* Treat errors while adding as non-fatal as we do not check for duplicates */
+        netsh_command (&argv, 2, (i==0)? M_FATAL : M_NONFATAL);
+    }
+
+    argv_reset (&argv);
+    gc_free (&gc);
+}
+
+static void
 netsh_ifconfig_options (const char *type,
 			const in_addr_t *addr_list,
 			const int addr_len,
src/openvpn/tun.h +3 -0
index dedd915..9b5a1b7 100644
@@ -107,6 +107,9 @@ struct tuntap_options {
   bool dhcp_release;
 
   bool register_dns;
+
+  struct in6_addr dns6[N_DHCP_ADDR];
+  int dns6_len;
 };
 
 #elif TARGET_LINUX
Signature · 1 line
2.1.4
#2 lore raw

HI,

Quoted 4 lines · Selva Nair

Note: This is supposed to be applied on top of the 'Stub implementation of "--dhcp-option DNS6 <v6addr>"' patch (
https://www.mail-archive.com/[email protected]/msg13140.html
)

Now that was quick :-) - someone needs to ACK that one first...

gert

Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             [email protected]...
fax: +49-89-35655025                        [email protected]...
author
#3 lore raw
Quoted 11 lines · Gert Doering

HI,

Quoted 3 lines · Selva Nair

Note: This is supposed to be applied on top of the 'Stub implementation of "--dhcp-option DNS6 <v6addr>"' patch (
https://www.mail-archive.com/[email protected]...

sourceforge.net/msg13140.html

Quoted 1 line

)

Now that was quick :-) - someone needs to ACK that one first...

I had a draft in my repo.. :) The ACK is coming.

Selva

#4 lore raw
In reply to Selva Nair

Am 20.11.16 um 22:38 schrieb Selva Nair:

Quoted 2 lines

TODO: set dns servers using the interactive service

I was playing with ANdroid/IPv6 and this. For Android, the resolver takes the DNS server always in the order that I give it. Since there are now seperate lists for DNS and DNS6 I have to prefer always DNS or DNS6 and cannot use the order I am given from the server.

I think we refactor the dns_list into a common dns list. I can also do this later since this is probably an Android specific problem.

(So basically ACK to the patch, but I will send a followup later)

Arne

author
#5 lore raw

Hi,

Quoted 4 lines · Arne Schwabe

Am 20.11.16 um 22:38 schrieb Selva Nair:

Quoted 2 lines

TODO: set dns servers using the interactive service

Quoted 8 lines

I was playing with ANdroid/IPv6 and this. For Android, the resolver takes the DNS server always in the order that I give it. Since there are now seperate lists for DNS and DNS6 I have to prefer always DNS or DNS6 and cannot use the order I am given from the server.

I think we refactor the dns_list into a common dns list. I can also do this later since this is probably an Android specific problem.

Yeah, we'll need a single list to preserve the inter-protocol ordering info, if that is really important. Does android support a mixed ipv4/ipv6 dns server ordering?

For windows separate lists is more natural and easier to use.

Selva

#6 lore raw

Am 21.11.16 um 05:22 schrieb Selva Nair:

Quoted 14 lines

Hi,

On Sun, Nov 20, 2016 at 5:29 PM, Arne Schwabe <[email protected]... <mailto:[email protected]...>> wrote:

Am 20.11.16 um 22:38 schrieb Selva Nair:
> TODO: set dns servers using the interactive service >

I was playing with ANdroid/IPv6 and this. For Android, the resolver takes the DNS server always in the order that I give it. Since there are now seperate lists for DNS and DNS6 I have to prefer always DNS or DNS6 and cannot use the order I am given from the server.

Quoted 7 lines

I think we refactor the dns_list into a common dns list. I can also do this later since this is probably an Android specific problem.

Yeah, we'll need a single list to preserve the inter-protocol ordering info, if that is really important. Does android support a mixed ipv4/ipv6 dns server ordering?

Yeah, it does. At least the first dns server I add (IPv4 or IPv6) is always used as DNS server and the rest is treated as fallback.

Arne

author
#7 lore raw
In reply to Selva Nair
Quoted 10 lines · Selva Nair

TODO: set dns servers using the interactive service

---
 doc/openvpn.8         |  5 ++---
 src/openvpn/options.c | 22 ++++++++++++++--------
 src/openvpn/tun.c     | 30 ++++++++++++++++++++++++++++++
 src/openvpn/tun.h     |  3 +++
 4 files changed, 49 insertions(+), 11 deletions(-)

Just realized the dns addresses should be removed when tun is closed (these statically set server addresses will stick around otherwise). Will send a v2 after the "stub implementation v2" is merged.

Selva

author
#8 lore raw

PATCH v2 1/1 Handle --dhcp-option DNS6 on Windows using netsh

In reply to Selva Nair

v2: On closing tun delete the ipv6 dns addresses (if any were set). Also use "validate=no" only in Windows 7 and higher where it is supported. Its used to skip the time consuming automatic address validation which is on by default on those platforms.

Tested on Windows Server 2008 (i686), Win 7 (x64) and Win 10 (x64)

TODO: set dns servers using the interactive service

---
 doc/openvpn.8         |  5 ++---
 src/openvpn/options.c | 22 ++++++++++++++--------
 src/openvpn/tun.c     | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/openvpn/tun.h     |  3 +++
 4 files changed, 71 insertions(+), 11 deletions(-)
doc/openvpn.8 +2 -3
index d454a36..171bd72 100644
@@ -5634,13 +5634,12 @@ this option to set secondary DNS server addresses.
 Set primary domain name server IPv6 address.  Repeat
 this option to set secondary DNS server IPv6 addresses.
 
-Note: currently this is somewhat of a placeholder option - it is
-understood, but OpenVPN has no code to tell Windows about it (the
+Note: currently this is handled using netsh and requires admin rights (the
 existing DHCP code can only do IPv4 DHCP, and that protocol only
 permits IPv4 addresses anywhere).  The option will be put into the
 environment, so an
 .B \-\-up
-script could act upon it.
+script could act upon it if needed.
 
 .B WINS addr \-\-
 Set primary WINS server address (NetBIOS over TCP/IP Name Server).
src/openvpn/options.c +14 -8
index f30e62d..9ee6f27 100644
@@ -6407,14 +6407,20 @@ add_option (struct options *options,
 	{
 	  dhcp_option_address_parse ("DNS", p[2], o->dns, &o->dns_len, msglevel);
 	}
-      else if (streq (p[1], "DNS6") && p[2])
-	{
-	  /* this is somewhat of a placeholder - we understand the option,
-	   * but cannot act upon it - so we'll just accept it and put it
-	   * into the environment, as we would do on all non-win32 platforms
-	   */
-	  foreign_option (options, p, 3, es);
-	}
+      else if (streq (p[1], "DNS6") && p[2] && ipv6_addr_safe(p[2]))
+        {
+          struct in6_addr addr;
+          foreign_option (options, p, 3, es);
+          if (o->dns6_len >= N_DHCP_ADDR)
+            {
+              msg (msglevel, "--dhcp-option DNS6: maximum of %d dns servers can be specified",
+	           N_DHCP_ADDR);
+            }
+          else if (get_ipv6_addr (p[2], &addr, NULL, msglevel))
+            {
+              o->dns6[o->dns6_len++] = addr;
+            }
+        }
       else if (streq (p[1], "WINS") && p[2])
 	{
 	  dhcp_option_address_parse ("WINS", p[2], o->wins, &o->wins_len, msglevel);
src/openvpn/tun.c +52 -0

82 lines not on this page · raw message

src/openvpn/tun.h +3 -0
index dedd915..9b5a1b7 100644
@@ -107,6 +107,9 @@ struct tuntap_options {
   bool dhcp_release;
 
   bool register_dns;
+
+  struct in6_addr dns6[N_DHCP_ADDR];
+  int dns6_len;
 };
 
 #elif TARGET_LINUX
Signature · 1 line
2.1.4
#9 lore raw

ACK, code looks reasonable. Only tested for "it compiles", though.

I've taken the liberty to reformat a few lines with leading blanks into the (still-)current style with tabs.

Your patch has been applied to the master branch.

commit 786e06ade9f5dfad8ac360499187fa8e536d15cb

Author: Selva Nair
Date:   Mon Nov 21 22:12:12 2016 -0500
     Handle --dhcp-option DNS6 on Windows using netsh

     Signed-off-by: Selva Nair <[email protected]...>
     Acked-by: Gert Doering <[email protected]...>
     Message-Id: <[email protected]...>
     URL: https://www.mail-archive.com/[email protected]/msg13193.html
     Signed-off-by: Gert Doering <[email protected]...>

--
kind regards,

Gert Doering