Skip to content
This repository has been archived by the owner on Oct 22, 2020. It is now read-only.

Commit

Permalink
Windows IPv6 cleanup - properly remove IPv6 routes and interface config
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cron2 committed May 22, 2011
1 parent 39990a2 commit b55e49b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 24 deletions.
46 changes: 46 additions & 0 deletions ChangeLog.IPv6
Original file line number Diff line number Diff line change
Expand Up @@ -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")
2 changes: 1 addition & 1 deletion options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__
;

Expand Down
52 changes: 31 additions & 21 deletions route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand All @@ -1274,31 +1296,14 @@ 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;

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 )
Expand Down Expand Up @@ -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 ();
Expand Down Expand Up @@ -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;
Expand All @@ -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 )
Expand Down
1 change: 1 addition & 0 deletions route.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 28 additions & 2 deletions tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit b55e49b

Please sign in to comment.