Browse code

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 <gert@greenie.muc.de>

Gert Doering authored on 2011/05/23 02:02:39
Showing 5 changed files
... ...
@@ -392,3 +392,49 @@ So 24. Apr 16:51:45 CEST 2011
392 392
 
393 393
   * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
394 394
 
395
+Thu Apr 28 19:10:01 CEST 2011
396
+
397
+  * rebase to "origin/release/2.2" branch (at v2.2.0 tag)
398
+
399
+Thu May 19 20:51:12 CEST 2011
400
+
401
+  * include Windows "netsh add" -> "netsh set ... store=active" patch from
402
+    Seth Mos, to fix restart problems on Windows due to persistant addresses
403
+
404
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
405
+
406
+Sat May 21 17:03:20 CEST 2011
407
+
408
+  * tun.c: Solaris cleanup (use CLEAR() to zero-out "ifr")
409
+
410
+  * tun.c: Windows cleanup: remove route and IPv6 address on disconnect
411
+
412
+  * route.c, route.h: remove "static" from delete_route_ipv6(), needed
413
+    for ipv6-route cleanup on disconnect
414
+
415
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
416
+
417
+  * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
418
+
419
+So 22. Mai 14:46:12 CEST 2011
420
+
421
+  * Tony Lim: removing routes fails on windows if certain bits are set
422
+    in the "host part" (others are silently ignored) -->
423
+
424
+  * route.c: create print_in6_addr_netbits_only() helper, call from 
425
+    add_route_ipv6() and delete_route_ipv6() to get only network part
426
+    of route-to-be-modified
427
+
428
+  * route.c: set 'store=active' on adding routes on WIN32 as well (Tony Lim)
429
+
430
+  * options.c: bump IPv6 release to 20110522-1
431
+
432
+  * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
433
+
434
+  * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
435
+
436
+  * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
437
+
438
+  * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
439
+    TEST FAIL: OpenBSD 4.7: client-tun/subnet, v4
440
+    (seems to be due to "topology subnet has just not been implemented yet")
... ...
@@ -80,7 +80,7 @@ const char title_string[] =
80 80
 #ifdef ENABLE_EUREPHIA
81 81
   " [eurephia]"
82 82
 #endif
83
-  " [IPv6 payload 20110424-2 (2.2RC2)]"
83
+  " [IPv6 payload 20110522-1 (2.2.0)]"
84 84
   " built on " __DATE__
85 85
 ;
86 86
 
... ...
@@ -40,7 +40,6 @@
40 40
 #include "memdbg.h"
41 41
 
42 42
 static void delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
43
-static void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
44 43
 static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags);
45 44
 
46 45
 #ifdef ENABLE_DEBUG
... ...
@@ -1264,6 +1263,29 @@ add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const s
1264 1264
   gc_free (&gc);
1265 1265
 }
1266 1266
 
1267
+
1268
+static const char * 
1269
+print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits, 
1270
+                             struct gc_arena * gc)
1271
+{
1272
+  /* clear host bit parts of route 
1273
+   * (needed if routes are specified improperly, or if we need to 
1274
+   * explicitely setup/clear the "connected" network routes on some OSes)
1275
+   */
1276
+  int byte = 15;
1277
+  int bits_to_clear = 128 - netbits;
1278
+
1279
+  while( byte >= 0 && bits_to_clear > 0 )
1280
+    {
1281
+      if ( bits_to_clear >= 8 )
1282
+	{ network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
1283
+      else
1284
+	{ network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
1285
+    }
1286
+
1287
+  return print_in6_addr( network_copy, 0, gc);
1288
+}
1289
+
1267 1290
 void
1268 1291
 add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1269 1292
 {
... ...
@@ -1274,8 +1296,6 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla
1274 1274
   const char *gateway;
1275 1275
   bool status = false;
1276 1276
   const char *device = tt->actual_name;
1277
-  int byte, bits_to_clear;
1278
-  struct in6_addr network_copy = r6->network;
1279 1277
 
1280 1278
   if (!r6->defined)
1281 1279
     return;
... ...
@@ -1283,22 +1303,7 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla
1283 1283
   gc_init (&gc);
1284 1284
   argv_init (&argv);
1285 1285
 
1286
-  /* clear host bit parts of route 
1287
-   * (needed if routes are specified improperly, or if we need to 
1288
-   * explicitely setup the "connected" network routes on some OSes)
1289
-   */
1290
-  byte = 15;
1291
-  bits_to_clear = 128 - r6->netbits;
1292
-
1293
-  while( byte >= 0 && bits_to_clear > 0 )
1294
-    {
1295
-      if ( bits_to_clear >= 8 )
1296
-	{ network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
1297
-      else
1298
-	{ network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
1299
-    }
1300
-
1301
-  network = print_in6_addr( network_copy, 0, &gc);
1286
+  network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
1302 1287
   gateway = print_in6_addr( r6->gateway, 0, &gc);
1303 1288
 
1304 1289
   if ( !tt->ipv6 )
... ...
@@ -1363,6 +1368,11 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla
1363 1363
     argv_printf_cat (&argv, " METRIC %d", r->metric);
1364 1364
 #endif
1365 1365
 
1366
+  /* in some versions of Windows, routes are persistent across reboots by
1367
+   * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
1368
+   */
1369
+  argv_printf_cat( &argv, " store=active" );
1370
+
1366 1371
   argv_msg (D_ROUTE, &argv);
1367 1372
 
1368 1373
   netcmd_semaphore_lock ();
... ...
@@ -1573,7 +1583,7 @@ delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags
1573 1573
   gc_free (&gc);
1574 1574
 }
1575 1575
 
1576
-static void
1576
+void
1577 1577
 delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
1578 1578
 {
1579 1579
   struct gc_arena gc;
... ...
@@ -1588,7 +1598,7 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne
1588 1588
   gc_init (&gc);
1589 1589
   argv_init (&argv);
1590 1590
 
1591
-  network = print_in6_addr( r6->network, 0, &gc);
1591
+  network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
1592 1592
   gateway = print_in6_addr( r6->gateway, 0, &gc);
1593 1593
 
1594 1594
   if ( !tt->ipv6 )
... ...
@@ -176,6 +176,7 @@ struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_are
176 176
 
177 177
 void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
178 178
 void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
179
+void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
179 180
 
180 181
 void add_route_to_option_list (struct route_option_list *l,
181 182
 			       const char *network,
... ...
@@ -591,6 +591,18 @@ void add_route_connected_v6_net(struct tuntap * tt,
591 591
     r6.gateway = tt->local_ipv6;
592 592
     add_route_ipv6 (&r6, tt, 0, es);
593 593
 }
594
+
595
+void delete_route_connected_v6_net(struct tuntap * tt,
596
+	                           const struct env_set *es)
597
+{
598
+    struct route_ipv6 r6;
599
+
600
+    r6.defined = true;
601
+    r6.network = tt->local_ipv6;
602
+    r6.netbits = tt->netbits_ipv6;
603
+    r6.gateway = tt->local_ipv6;
604
+    delete_route_ipv6 (&r6, tt, 0, es);
605
+}
594 606
 #endif
595 607
 
596 608
 
... ...
@@ -1649,7 +1661,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
1649 1649
    * http://www.whiteboard.ne.jp/~admin2/tuntap/
1650 1650
    * has IPv6 support
1651 1651
    */
1652
-  memset(&ifr, 0x0, sizeof(ifr));
1652
+  CLEAR(ifr);
1653 1653
 
1654 1654
   if (tt->type == DEV_TYPE_NULL)
1655 1655
     {
... ...
@@ -4851,9 +4863,23 @@ close_tun (struct tuntap *tt)
4851 4851
     {
4852 4852
       if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
4853 4853
         {
4854
+	  struct argv argv;
4855
+	  argv_init (&argv);
4856
+
4857
+	  /* remove route pointing to interface */
4858
+	  delete_route_connected_v6_net(tt, NULL);
4859
+
4854 4860
 	  /* netsh interface ipv6 delete address \"%s\" %s */
4855 4861
 	  const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
4856
-	  msg( M_WARN, "TODO: remove IPv6 address %s", ifconfig_ipv6_local );
4862
+	  argv_printf (&argv,
4863
+		    "%s%sc interface ipv6 delete address %s %s",
4864
+		     get_win_sys_path(),
4865
+		     NETSH_PATH_SUFFIX,
4866
+		     tt->actual_name,
4867
+		     ifconfig_ipv6_local );
4868
+
4869
+	  netsh_command (&argv, 1);
4870
+          argv_reset (&argv);
4857 4871
 	}
4858 4872
 #if 1
4859 4873
       if (tt->ipapi_context_defined)