]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Windows IPv6 cleanup - properly remove IPv6 routes and interface config
authorGert Doering <gert@greenie.muc.de>
Sun, 22 May 2011 17:02:39 +0000 (19:02 +0200)
committerGert Doering <gert@greenie.muc.de>
Sun, 22 May 2011 17:08:22 +0000 (19:08 +0200)
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 <gert@greenie.muc.de>
ChangeLog.IPv6
options.c
route.c
route.h
tun.c

index 38f444689fdf6bb7dd9e4e87297dc496efbcc842..283fe6e6732abbe110b95c3fe993da224cb38fb6 100644 (file)
@@ -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")
index 6f98d140a14a4558f34e2775bada6ff8119bfb81..824492e589f0638045bbc9f507583496e3143640 100644 (file)
--- 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 9cf07be7238ffef40bcfd586d0256a11621cde8c..7c81f757939775c7ca4463df9320178e12a28dd7 100644 (file)
--- 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 739d12ddbf96b5d36336ab3066ea709db7bbba90..6a7704f09c50c09c8ec6922cfb0f55e80dd76a7d 100644 (file)
--- 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 55d66e11ad3af4210fed39491b3ac631ff5b3bc9..cea1784bff294cff9a930e637a77372712a9178d 100644 (file)
--- 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)