Hi,

On Tue, May 10, 2011 at 03:00:35PM +0200, Seth Mos wrote:
> Here is the tun.c patch for correction of the netsh.exe commands.

So.  Took me a while to incorporate it, and I took the opportunity to
do more windows ipv6 related cleanups:

 - add routes with "store=active" as well (so if the machine crashes while
   OpenVPN is connectes, routes don't survive)

 - remove ifconfig and routes on disconnect - the latter part needed changes
   in more generic parts of route.c, route.h and tun.c

I have built and tested the resulting code on Linux, OpenBSD (because that
would be affected by a breakage in the changed route.c code), WinXP and
Win7 - and I also got independent test success reports for Win7 from 
Tony Lim (thanks!), so I consider this code sane :-)

Patches attached for review.

David: please pull from git://compile.svr01.mucip.net/openvpn-gert.git,
       all that is in the "feat_ipv6_payload_2.3" branch

gert
-- 
USENET is *not* the non-clickable part of WWW!
                                                           //www.muc.de/~gert/
Gert Doering - Munich, Germany                             g...@greenie.muc.de
fax: +49-89-35655025                        g...@net.informatik.tu-muenchen.de
From 39990a2b83308baf1372bbc8846136036a55cf50 Mon Sep 17 00:00:00 2001
From: smos <seth....@dds.nl>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Tue, 10 May 2011 10:01:48 +0200
Subject: [PATCH 1/2] Change the netsh.exe command from "add" to "set".

This prevents the netsh.exe command from exiting with a status 1
when the address already exists. By adding store=active the address
will not survive a reboot and be assigned temporarily.

Tested on Windows 7 and Windows XP SP 2.

Signed-off-by: smos <seth....@dds.nl>
Acked-by: Gert Doering <g...@greenie.muc.de>
Signed-off-by: Gert Doering <g...@greenie.muc.de>
---
 tun.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tun.c b/tun.c
index 45db2b5..55d66e1 100644
--- a/tun.c
+++ b/tun.c
@@ -1167,9 +1167,9 @@ do_ifconfig (struct tuntap *tt,
        if (!strcmp (actual, "NULL"))
          msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than 
one TAP-Win32 adapter, you must also specify --dev-node");
 
-       /* example: netsh interface ipv6 add address MyTap 2001:608:8003::d */
+       /* example: netsh interface ipv6 set address MyTap 2001:608:8003::d 
store=active */
        argv_printf (&argv,
-                   "%s%sc interface ipv6 add address %s %s",
+                   "%s%sc interface ipv6 set address %s %s store=active",
                     get_win_sys_path(),
                     NETSH_PATH_SUFFIX,
                     actual,
-- 
1.7.3.4

From b55e49bd69484fdd440098f9485de159251e1cce Mon Sep 17 00:00:00 2001
From: Gert Doering <g...@greenie.muc.de>
List-Post: openvpn-devel@lists.sourceforge.net
Date: Sun, 22 May 2011 19:02:39 +0200
Subject: [PATCH 2/2] Windows IPv6 cleanup - properly remove IPv6 routes and 
interface config
 after tunnel shutdown.  Needs to make delete_route_ipv6() visible from
 tun.c (route.c, route.h) and to properly zero-out host bits from IPv6
 "network" at interface route clearing.  Further, add IPv6 routes with
 "store=active" to make sure nothing lingers after a system crash while
 OpenVPN was running.

While at it, small Solaris cleanup - use CLEAR() to zero-out "ifr" struct.

Tested on Windows XP SP3 and Win7 by Gert Doering and Tony Lim.

Signed-off-by: Gert Doering <g...@greenie.muc.de>
---
 ChangeLog.IPv6 |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 options.c      |    2 +-
 route.c        |   52 +++++++++++++++++++++++++++++++---------------------
 route.h        |    1 +
 tun.c          |   30 ++++++++++++++++++++++++++++--
 5 files changed, 107 insertions(+), 24 deletions(-)

diff --git a/ChangeLog.IPv6 b/ChangeLog.IPv6
index 38f4446..283fe6e 100644
--- a/ChangeLog.IPv6
+++ b/ChangeLog.IPv6
@@ -392,3 +392,49 @@ So 24. Apr 16:51:45 CEST 2011
 
   * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
 
+Thu Apr 28 19:10:01 CEST 2011
+
+  * rebase to "origin/release/2.2" branch (at v2.2.0 tag)
+
+Thu May 19 20:51:12 CEST 2011
+
+  * include Windows "netsh add" -> "netsh set ... store=active" patch from
+    Seth Mos, to fix restart problems on Windows due to persistant addresses
+
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
+
+Sat May 21 17:03:20 CEST 2011
+
+  * tun.c: Solaris cleanup (use CLEAR() to zero-out "ifr")
+
+  * tun.c: Windows cleanup: remove route and IPv6 address on disconnect
+
+  * route.c, route.h: remove "static" from delete_route_ipv6(), needed
+    for ipv6-route cleanup on disconnect
+
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
+
+  * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
+
+So 22. Mai 14:46:12 CEST 2011
+
+  * Tony Lim: removing routes fails on windows if certain bits are set
+    in the "host part" (others are silently ignored) -->
+
+  * route.c: create print_in6_addr_netbits_only() helper, call from 
+    add_route_ipv6() and delete_route_ipv6() to get only network part
+    of route-to-be-modified
+
+  * route.c: set 'store=active' on adding routes on WIN32 as well (Tony Lim)
+
+  * options.c: bump IPv6 release to 20110522-1
+
+  * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
+
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
+
+  * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
+
+  * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
+    TEST FAIL: OpenBSD 4.7: client-tun/subnet, v4
+    (seems to be due to "topology subnet has just not been implemented yet")
diff --git a/options.c b/options.c
index 6f98d14..824492e 100644
--- a/options.c
+++ b/options.c
@@ -80,7 +80,7 @@ const char title_string[] =
 #ifdef ENABLE_EUREPHIA
   " [eurephia]"
 #endif
-  " [IPv6 payload 20110424-2 (2.2RC2)]"
+  " [IPv6 payload 20110522-1 (2.2.0)]"
   " built on " __DATE__
 ;
 
diff --git a/route.c b/route.c
index 9cf07be..7c81f75 100644
--- a/route.c
+++ b/route.c
@@ -40,7 +40,6 @@
 #include "memdbg.h"
 
 static void delete_route (const struct route *r, const struct tuntap *tt, 
unsigned int flags, const struct env_set *es);
-static void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap 
*tt, unsigned int flags, const struct env_set *es);
 static void get_bypass_addresses (struct route_bypass *rb, const unsigned int 
flags);
 
 #ifdef ENABLE_DEBUG
@@ -1264,6 +1263,29 @@ add_route (struct route *r, const struct tuntap *tt, 
unsigned int flags, const s
   gc_free (&gc);
 }
 
+
+static const char * 
+print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits, 
+                             struct gc_arena * gc)
+{
+  /* clear host bit parts of route 
+   * (needed if routes are specified improperly, or if we need to 
+   * explicitely setup/clear the "connected" network routes on some OSes)
+   */
+  int byte = 15;
+  int bits_to_clear = 128 - netbits;
+
+  while( byte >= 0 && bits_to_clear > 0 )
+    {
+      if ( bits_to_clear >= 8 )
+       { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
+      else
+       { network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear 
= 0; }
+    }
+
+  return print_in6_addr( network_copy, 0, gc);
+}
+
 void
 add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int 
flags, const struct env_set *es)
 {
@@ -1274,8 +1296,6 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct 
tuntap *tt, unsigned int fla
   const char *gateway;
   bool status = false;
   const char *device = tt->actual_name;
-  int byte, bits_to_clear;
-  struct in6_addr network_copy = r6->network;
 
   if (!r6->defined)
     return;
@@ -1283,22 +1303,7 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct 
tuntap *tt, unsigned int fla
   gc_init (&gc);
   argv_init (&argv);
 
-  /* clear host bit parts of route 
-   * (needed if routes are specified improperly, or if we need to 
-   * explicitely setup the "connected" network routes on some OSes)
-   */
-  byte = 15;
-  bits_to_clear = 128 - r6->netbits;
-
-  while( byte >= 0 && bits_to_clear > 0 )
-    {
-      if ( bits_to_clear >= 8 )
-       { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
-      else
-       { network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear 
= 0; }
-    }
-
-  network = print_in6_addr( network_copy, 0, &gc);
+  network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
   gateway = print_in6_addr( r6->gateway, 0, &gc);
 
   if ( !tt->ipv6 )
@@ -1363,6 +1368,11 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct 
tuntap *tt, unsigned int fla
     argv_printf_cat (&argv, " METRIC %d", r->metric);
 #endif
 
+  /* in some versions of Windows, routes are persistent across reboots by
+   * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
+   */
+  argv_printf_cat( &argv, " store=active" );
+
   argv_msg (D_ROUTE, &argv);
 
   netcmd_semaphore_lock ();
@@ -1573,7 +1583,7 @@ delete_route (const struct route *r, const struct tuntap 
*tt, unsigned int flags
   gc_free (&gc);
 }
 
-static void
+void
 delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, 
unsigned int flags, const struct env_set *es)
 {
   struct gc_arena gc;
@@ -1588,7 +1598,7 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const 
struct tuntap *tt, unsigne
   gc_init (&gc);
   argv_init (&argv);
 
-  network = print_in6_addr( r6->network, 0, &gc);
+  network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
   gateway = print_in6_addr( r6->gateway, 0, &gc);
 
   if ( !tt->ipv6 )
diff --git a/route.h b/route.h
index 739d12d..6a7704f 100644
--- a/route.h
+++ b/route.h
@@ -176,6 +176,7 @@ struct route_ipv6_list *new_route_ipv6_list (const int 
max_routes, struct gc_are
 
 void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, 
const struct env_set *es);
 void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned 
int flags, const struct env_set *es);
+void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, 
unsigned int flags, const struct env_set *es);
 
 void add_route_to_option_list (struct route_option_list *l,
                               const char *network,
diff --git a/tun.c b/tun.c
index 55d66e1..cea1784 100644
--- a/tun.c
+++ b/tun.c
@@ -591,6 +591,18 @@ void add_route_connected_v6_net(struct tuntap * tt,
     r6.gateway = tt->local_ipv6;
     add_route_ipv6 (&r6, tt, 0, es);
 }
+
+void delete_route_connected_v6_net(struct tuntap * tt,
+                                  const struct env_set *es)
+{
+    struct route_ipv6 r6;
+
+    r6.defined = true;
+    r6.network = tt->local_ipv6;
+    r6.netbits = tt->netbits_ipv6;
+    r6.gateway = tt->local_ipv6;
+    delete_route_ipv6 (&r6, tt, 0, es);
+}
 #endif
 
 
@@ -1649,7 +1661,7 @@ open_tun (const char *dev, const char *dev_type, const 
char *dev_node, struct tu
    * http://www.whiteboard.ne.jp/~admin2/tuntap/
    * has IPv6 support
    */
-  memset(&ifr, 0x0, sizeof(ifr));
+  CLEAR(ifr);
 
   if (tt->type == DEV_TYPE_NULL)
     {
@@ -4851,9 +4863,23 @@ close_tun (struct tuntap *tt)
     {
       if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
         {
+         struct argv argv;
+         argv_init (&argv);
+
+         /* remove route pointing to interface */
+         delete_route_connected_v6_net(tt, NULL);
+
          /* netsh interface ipv6 delete address \"%s\" %s */
          const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, 
&gc);
-         msg( M_WARN, "TODO: remove IPv6 address %s", ifconfig_ipv6_local );
+         argv_printf (&argv,
+                   "%s%sc interface ipv6 delete address %s %s",
+                    get_win_sys_path(),
+                    NETSH_PATH_SUFFIX,
+                    tt->actual_name,
+                    ifconfig_ipv6_local );
+
+         netsh_command (&argv, 1);
+          argv_reset (&argv);
        }
 #if 1
       if (tt->ipapi_context_defined)
-- 
1.7.3.4

Attachment: pgpr7cxAU7PjW.pgp
Description: PGP signature

Reply via email to