summaryrefslogtreecommitdiff
path: root/src/openvpn/tun.c
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2016-11-21 09:37:33 +0100
committerAlberto Gonzalez Iniesta <agi@inittab.org>2016-11-21 09:37:33 +0100
commit93b77cacdbb7e6f310c4e20f85c3a24ed5ba18ba (patch)
tree55a7688c9969ef4d01625caa58c7f679098c76eb /src/openvpn/tun.c
parentdaa9ef0efeb5e10a1b43820fbab3a4ff5fbd22f1 (diff)
parent20c8675ba46bda97330a4117c459a59a9f1c465e (diff)
Merge tag 'upstream/2.4_beta1'
Upstream version 2.4~beta1
Diffstat (limited to 'src/openvpn/tun.c')
-rw-r--r--src/openvpn/tun.c830
1 files changed, 562 insertions, 268 deletions
diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c
index b70410d..77ae72f 100644
--- a/src/openvpn/tun.c
+++ b/src/openvpn/tun.c
@@ -49,7 +49,13 @@
#include "memdbg.h"
-#ifdef WIN32
+#ifdef _WIN32
+#include "openvpn-msg.h"
+#endif
+
+#include <string.h>
+
+#ifdef _WIN32
/* #define SIMULATE_DHCP_FAILED */ /* simulate bad DHCP negotiation */
@@ -62,12 +68,70 @@ 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_command (const struct argv *a, int n);
+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);
static DWORD get_adapter_index_flexible (const char *name);
+static bool
+do_address_service (const bool add, const short family, const struct tuntap *tt)
+{
+ DWORD len;
+ bool ret = false;
+ ack_message_t ack;
+ struct gc_arena gc = gc_new ();
+ HANDLE pipe = tt->options.msg_channel;
+
+ address_message_t addr = {
+ .header = {
+ (add ? msg_add_address : msg_del_address),
+ sizeof (address_message_t),
+ 0 },
+ .family = family,
+ .iface = { .index = tt->adapter_index, .name = "" }
+ };
+
+ if (addr.iface.index == TUN_ADAPTER_INDEX_INVALID)
+ {
+ strncpy (addr.iface.name, tt->actual_name, sizeof (addr.iface.name));
+ addr.iface.name[sizeof (addr.iface.name) - 1] = '\0';
+ }
+
+ if (addr.family == AF_INET)
+ {
+ addr.address.ipv4.s_addr = tt->local;
+ addr.prefix_len = 32;
+ }
+ else
+ {
+ addr.address.ipv6 = tt->local_ipv6;
+ addr.prefix_len = tt->netbits_ipv6;
+ }
+
+ if (!WriteFile (pipe, &addr, sizeof (addr), &len, NULL) ||
+ !ReadFile (pipe, &ack, sizeof (ack), &len, NULL))
+ {
+ msg (M_WARN, "TUN: could not talk to service: %s [%lu]",
+ strerror_win32 (GetLastError (), &gc), GetLastError ());
+ goto out;
+ }
+
+ if (ack.error_number != NO_ERROR)
+ {
+ msg (M_WARN, "TUN: %s address failed using service: %s [status=%u if_index=%lu]",
+ (add ? "adding" : "deleting"), strerror_win32 (ack.error_number, &gc),
+ ack.error_number, addr.iface.index);
+ goto out;
+ }
+
+ ret = true;
+
+out:
+ gc_free (&gc);
+ return ret;
+}
+
#endif
#ifdef TARGET_SOLARIS
@@ -134,7 +198,7 @@ guess_tuntap_dev (const char *dev,
const char *dev_node,
struct gc_arena *gc)
{
-#ifdef WIN32
+#ifdef _WIN32
const int dt = dev_type_enum (dev, dev_type);
if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP)
{
@@ -357,7 +421,7 @@ tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
{
buf_printf (&out, "T%s",
(tt->rwflags_debug & EVENT_READ) ? "R" : "r");
-#ifdef WIN32
+#ifdef _WIN32
buf_printf (&out, "%s",
overlapped_io_state_ascii (&tt->reads));
#endif
@@ -366,7 +430,7 @@ tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
{
buf_printf (&out, "T%s",
(tt->rwflags_debug & EVENT_WRITE) ? "W" : "w");
-#ifdef WIN32
+#ifdef _WIN32
buf_printf (&out, "%s",
overlapped_io_state_ascii (&tt->writes));
#endif
@@ -455,8 +519,8 @@ init_tun (const char *dev, /* --dev option */
const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
int ifconfig_ipv6_netbits_parm,
const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
- in_addr_t local_public,
- in_addr_t remote_public,
+ struct addrinfo *local_public,
+ struct addrinfo *remote_public,
const bool strict_warn,
struct env_set *es)
{
@@ -507,6 +571,7 @@ init_tun (const char *dev, /* --dev option */
*/
if (strict_warn)
{
+ struct addrinfo *curele;
ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);
/*
@@ -514,17 +579,23 @@ init_tun (const char *dev, /* --dev option */
* make sure they do not clash with our virtual subnet.
*/
- check_addr_clash ("local",
+ for(curele=local_public;curele;curele=curele->ai_next) {
+ if(curele->ai_family == AF_INET)
+ check_addr_clash ("local",
tt->type,
- local_public,
+ ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr,
tt->local,
tt->remote_netmask);
+ }
- check_addr_clash ("remote",
- tt->type,
- remote_public,
- tt->local,
- tt->remote_netmask);
+ for (curele=remote_public;curele;curele=curele->ai_next) {
+ if (curele->ai_family == AF_INET)
+ check_addr_clash ("remote",
+ tt->type,
+ ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr,
+ tt->local,
+ tt->remote_netmask);
+ }
if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
check_subnet_conflict (tt->local, tt->remote_netmask, "TUN/TAP adapter");
@@ -540,6 +611,21 @@ init_tun (const char *dev, /* --dev option */
tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask);
}
+#ifdef _WIN32
+ /*
+ * Make sure that both ifconfig addresses are part of the
+ * same .252 subnet.
+ */
+ if (tun)
+ {
+ verify_255_255_255_252 (tt->local, tt->remote_netmask);
+ tt->adapter_netmask = ~3;
+ }
+ else
+ {
+ tt->adapter_netmask = tt->remote_netmask;
+ }
+#endif
tt->did_ifconfig_setup = true;
}
@@ -579,7 +665,7 @@ init_tun_post (struct tuntap *tt,
const struct tuntap_options *options)
{
tt->options = *options;
-#ifdef WIN32
+#ifdef _WIN32
overlapped_io_init (&tt->reads, frame, FALSE, true);
overlapped_io_init (&tt->writes, frame, TRUE, true);
tt->rw_handle.read = tt->reads.overlapped.hEvent;
@@ -588,7 +674,7 @@ init_tun_post (struct tuntap *tt,
#endif
}
-#if defined(WIN32) || \
+#if defined(_WIN32) || \
defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD)
/* some of the platforms will auto-add a "network route" pointing
@@ -601,12 +687,12 @@ void add_route_connected_v6_net(struct tuntap * tt,
{
struct route_ipv6 r6;
- r6.defined = true;
+ CLEAR(r6);
r6.network = tt->local_ipv6;
r6.netbits = tt->netbits_ipv6;
r6.gateway = tt->local_ipv6;
r6.metric = 0; /* connected route */
- r6.metric_defined = true;
+ r6.flags = RT_DEFINED | RT_METRIC_DEFINED;
add_route_ipv6 (&r6, tt, 0, es);
}
@@ -615,17 +701,18 @@ void delete_route_connected_v6_net(struct tuntap * tt,
{
struct route_ipv6 r6;
- r6.defined = true;
+ CLEAR(r6);
r6.network = tt->local_ipv6;
r6.netbits = tt->netbits_ipv6;
r6.gateway = tt->local_ipv6;
r6.metric = 0; /* connected route */
- r6.metric_defined = true;
+ r6.flags = RT_DEFINED | RT_ADDED | RT_METRIC_DEFINED;
delete_route_ipv6 (&r6, tt, 0, es);
}
#endif
-#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)||\
+ defined(TARGET_OPENBSD)
/* we can't use true subnet mode on tun on all platforms, as that
* conflicts with IPv6 (wants to use ND then, which we don't do),
* but the OSes want "a remote address that is different from ours"
@@ -635,8 +722,8 @@ void delete_route_connected_v6_net(struct tuntap * tt,
* is still point to point and no layer 2 resolution is done...
*/
-const char *
-create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc )
+in_addr_t
+create_arbitrary_remote( struct tuntap *tt )
{
in_addr_t remote;
@@ -644,7 +731,7 @@ create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc )
if ( remote == tt->local ) remote ++;
- return print_in_addr_t (remote, 0, gc);
+ return remote;
}
#endif
@@ -664,14 +751,11 @@ do_ifconfig (struct tuntap *tt,
const char *ifconfig_remote_netmask = NULL;
const char *ifconfig_broadcast = NULL;
const char *ifconfig_ipv6_local = NULL;
- const char *ifconfig_ipv6_remote = NULL;
bool do_ipv6 = false;
- struct argv argv;
-
- argv_init (&argv);
+ struct argv argv = argv_new ();
- msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
- tt->ipv6, tt->did_ifconfig_ipv6_setup );
+ msg( M_DEBUG, "do_ifconfig, tt->did_ifconfig_ipv6_setup=%d",
+ tt->did_ifconfig_ipv6_setup );
/*
* We only handle TUN/TAP devices here, not --dev null devices.
@@ -684,10 +768,9 @@ do_ifconfig (struct tuntap *tt,
ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
- if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
+ if (tt->did_ifconfig_ipv6_setup )
{
ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
- ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
do_ipv6 = true;
}
@@ -703,8 +786,10 @@ do_ifconfig (struct tuntap *tt,
management_set_state (management,
OPENVPN_STATE_ASSIGN_IP,
NULL,
- tt->local,
- 0);
+ &tt->local,
+ &tt->local_ipv6,
+ NULL,
+ NULL);
}
#endif
@@ -743,7 +828,7 @@ do_ifconfig (struct tuntap *tt,
iproute_path,
actual,
ifconfig_local,
- count_netmask_bits(ifconfig_remote_netmask),
+ netmask_to_netbits2(tt->remote_netmask),
ifconfig_broadcast
);
argv_msg (M_INFO, &argv);
@@ -799,8 +884,35 @@ do_ifconfig (struct tuntap *tt,
tt->did_ifconfig = true;
#endif /*ENABLE_IPROUTE*/
-#elif defined(TARGET_SOLARIS)
+#elif defined(TARGET_ANDROID)
+
+ if (do_ipv6) {
+ struct buffer out6 = alloc_buf_gc (64, &gc);
+ buf_printf (&out6, "%s/%d", ifconfig_ipv6_local,tt->netbits_ipv6);
+ management_android_control(management, "IFCONFIG6",buf_bptr(&out6));
+ }
+
+ struct buffer out = alloc_buf_gc (64, &gc);
+
+ char* top;
+ switch(tt->topology) {
+ case TOP_NET30:
+ top="net30";
+ break;
+ case TOP_P2P:
+ top="p2p";
+ break;
+ case TOP_SUBNET:
+ top="subnet";
+ break;
+ default:
+ top="undef";
+ }
+
+ buf_printf (&out, "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu, top);
+ management_android_control (management, "IFCONFIG", buf_bptr(&out));
+#elif defined(TARGET_SOLARIS)
/* Solaris 2.6 (and 7?) cannot set all parameters in one go...
* example:
* ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up
@@ -862,6 +974,9 @@ do_ifconfig (struct tuntap *tt,
if ( tt->type == DEV_TYPE_TUN )
{
+ const char *ifconfig_ipv6_remote =
+ print_in6_addr (tt->remote_ipv6, 0, &gc);
+
argv_printf (&argv,
"%s %s inet6 plumb %s/%d %s up",
IFCONFIG_PATH,
@@ -916,6 +1031,8 @@ do_ifconfig (struct tuntap *tt,
#elif defined(TARGET_OPENBSD)
+ in_addr_t remote_end; /* for "virtual" subnet topology */
+
/*
* On OpenBSD, tun interfaces are persistent if created with
* "ifconfig tunX create", and auto-destroyed if created by
@@ -935,12 +1052,13 @@ do_ifconfig (struct tuntap *tt,
else
if ( tt->topology == TOP_SUBNET )
{
+ remote_end = create_arbitrary_remote( tt );
argv_printf (&argv,
"%s %s %s %s mtu %d netmask %s up -link0",
IFCONFIG_PATH,
actual,
ifconfig_local,
- ifconfig_local,
+ print_in_addr_t (remote_end, 0, &gc),
tun_mtu,
ifconfig_remote_netmask
);
@@ -957,6 +1075,19 @@ do_ifconfig (struct tuntap *tt,
);
argv_msg (M_INFO, &argv);
openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig failed");
+
+ /* Add a network route for the local tun interface */
+ if (!tun && tt->topology == TOP_SUBNET)
+ {
+ struct route_ipv4 r;
+ CLEAR (r);
+ r.flags = RT_DEFINED;
+ r.network = tt->local & tt->remote_netmask;
+ r.netmask = tt->remote_netmask;
+ r.gateway = remote_end;
+ add_route (&r, tt, 0, NULL, es);
+ }
+
if ( do_ipv6 )
{
argv_printf (&argv,
@@ -976,13 +1107,6 @@ do_ifconfig (struct tuntap *tt,
#elif defined(TARGET_NETBSD)
-/* whether or not NetBSD can do IPv6 can be seen by the availability of
- * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
- */
-#ifdef TUNSIFHEAD
-# define NETBSD_MULTI_AF
-#endif
-
if (tun)
argv_printf (&argv,
"%s %s %s %s mtu %d netmask 255.255.255.255 up",
@@ -1025,7 +1149,6 @@ do_ifconfig (struct tuntap *tt,
if ( do_ipv6 )
{
-#ifdef NETBSD_MULTI_AF
argv_printf (&argv,
"%s %s inet6 %s/%d",
IFCONFIG_PATH,
@@ -1038,10 +1161,6 @@ do_ifconfig (struct tuntap *tt,
/* and, hooray, we explicitely need to add a route... */
add_route_connected_v6_net(tt, es);
-#else
- msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 (if your system is newer, recompile openvpn)" );
- tt->ipv6 = false;
-#endif
}
tt->did_ifconfig = true;
@@ -1126,6 +1245,8 @@ do_ifconfig (struct tuntap *tt,
#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
+ in_addr_t remote_end; /* for "virtual" subnet topology */
+
/* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
if (tun)
argv_printf (&argv,
@@ -1138,12 +1259,13 @@ do_ifconfig (struct tuntap *tt,
);
else if ( tt->topology == TOP_SUBNET )
{
+ remote_end = create_arbitrary_remote( tt );
argv_printf (&argv,
"%s %s %s %s mtu %d netmask %s up",
IFCONFIG_PATH,
actual,
ifconfig_local,
- create_arbitrary_remote( tt, &gc ),
+ print_in_addr_t (remote_end, 0, &gc),
tun_mtu,
ifconfig_remote_netmask
);
@@ -1170,7 +1292,7 @@ do_ifconfig (struct tuntap *tt,
r.flags = RT_DEFINED;
r.network = tt->local & tt->remote_netmask;
r.netmask = tt->remote_netmask;
- r.gateway = tt->local;
+ r.gateway = remote_end;
add_route (&r, tt, 0, NULL, es);
}
@@ -1187,21 +1309,46 @@ do_ifconfig (struct tuntap *tt,
openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed");
}
-#elif defined (WIN32)
+#elif defined(TARGET_AIX)
{
- /*
- * Make sure that both ifconfig addresses are part of the
- * same .252 subnet.
- */
+ /* AIX ifconfig will complain if it can't find ODM path in env */
+ struct env_set *aix_es = env_set_create (NULL);
+ env_set_add( aix_es, "ODMDIR=/etc/objrepos" );
+
if (tun)
+ msg(M_FATAL, "no tun support on AIX (canthappen)");
+
+ /* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */
+ argv_printf (&argv,
+ "%s %s %s netmask %s mtu %d up",
+ IFCONFIG_PATH,
+ actual,
+ ifconfig_local,
+ ifconfig_remote_netmask,
+ tun_mtu
+ );
+
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig failed");
+ tt->did_ifconfig = true;
+
+ if ( do_ipv6 )
{
- verify_255_255_255_252 (tt->local, tt->remote_netmask);
- tt->adapter_netmask = ~3;
- }
- else
- {
- tt->adapter_netmask = tt->remote_netmask;
+ argv_printf (&argv,
+ "%s %s inet6 %s/%d",
+ IFCONFIG_PATH,
+ actual,
+ ifconfig_ipv6_local,
+ tt->netbits_ipv6
+ );
+ argv_msg (M_INFO, &argv);
+ openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig inet6 failed");
}
+ env_set_destroy (aix_es);
+ }
+#elif defined (_WIN32)
+ {
+ ASSERT (actual != NULL);
switch (tt->options.ip_win32_type)
{
@@ -1212,9 +1359,6 @@ do_ifconfig (struct tuntap *tt,
print_in_addr_t (tt->adapter_netmask, 0, &gc));
break;
case IPW32_SET_NETSH:
- if (!strcmp (actual, "NULL"))
- msg (M_FATAL, "Error: When using --ip-win32 netsh, if you have more than one TAP-Windows adapter, you must also specify --dev-node");
-
netsh_ifconfig (&tt->options,
actual,
tt->local,
@@ -1226,39 +1370,28 @@ do_ifconfig (struct tuntap *tt,
tt->did_ifconfig = true;
}
- /* IPv6 always uses "netsh" interface */
if ( do_ipv6 )
{
- char * saved_actual;
- char iface[64];
- DWORD idx;
-
- if (!strcmp (actual, "NULL"))
- msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than one TAP-Windows adapter, you must also specify --dev-node");
-
- idx = get_adapter_index_flexible(actual);
- openvpn_snprintf(iface, sizeof(iface), "interface=%lu", idx);
-
- /* example: netsh interface ipv6 set address interface=42 2001:608:8003::d store=active */
- argv_printf (&argv,
- "%s%sc interface ipv6 set address %s %s store=active",
- get_win_sys_path(),
- NETSH_PATH_SUFFIX,
- win32_version_info() == WIN_XP ? actual : iface,
- ifconfig_ipv6_local);
- netsh_command (&argv, 4);
+ if (tt->options.msg_channel)
+ {
+ do_address_service (true, AF_INET6, tt);
+ }
+ else
+ {
+ /* example: netsh interface ipv6 set address interface=42 2001:608:8003::d store=active */
+ char iface[64];
+ openvpn_snprintf(iface, sizeof(iface), "interface=%lu", tt->adapter_index );
+ argv_printf (&argv,
+ "%s%sc interface ipv6 set address %s %s store=active",
+ get_win_sys_path(),
+ NETSH_PATH_SUFFIX,
+ iface,
+ ifconfig_ipv6_local );
+ netsh_command (&argv, 4, M_FATAL);
+ }
/* explicit route needed */
- /* on windows, OpenVPN does ifconfig first, open_tun later, so
- * tt->actual_name might not yet be initialized, but routing code
- * needs to know interface name - point to "actual", restore later
- */
- saved_actual = tt->actual_name;
- tt->actual_name = (char*) actual;
- /* we use adapter_index in add_route_ipv6 */
- tt->adapter_index = idx;
add_route_connected_v6_net(tt, es);
- tt->actual_name = saved_actual;
}
#else
msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
@@ -1272,7 +1405,7 @@ static void
clear_tuntap (struct tuntap *tuntap)
{
CLEAR (*tuntap);
-#ifdef WIN32
+#ifdef _WIN32
tuntap->hand = NULL;
#else
tuntap->fd = -1;
@@ -1280,7 +1413,6 @@ clear_tuntap (struct tuntap *tuntap)
#ifdef TARGET_SOLARIS
tuntap->ip_fd = -1;
#endif
- tuntap->ipv6 = false;
}
static void
@@ -1333,7 +1465,7 @@ write_tun_header (struct tuntap* tt, uint8_t *buf, int len)
iph = (struct ip *) buf;
- if (tt->ipv6 && iph->ip_v == 6)
+ if (iph->ip_v == 6)
type = htonl (AF_INET6);
else
type = htonl (AF_INET);
@@ -1370,20 +1502,15 @@ read_tun_header (struct tuntap* tt, uint8_t *buf, int len)
#endif
-#ifndef WIN32
+#if !(defined(_WIN32) || defined(TARGET_LINUX))
static void
open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
- bool ipv6_explicitly_supported, bool dynamic,
- struct tuntap *tt)
+ bool dynamic, struct tuntap *tt)
{
char tunname[256];
char dynamic_name[256];
bool dynamic_opened = false;
-
- if ( tt->ipv6 && ! ipv6_explicitly_supported )
- msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
-
if (tt->type == DEV_TYPE_NULL)
{
open_null (tt);
@@ -1477,7 +1604,9 @@ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
tt->actual_name = string_alloc (dynamic_opened ? dynamic_name : dev, NULL);
}
}
+#endif /* !_WIN32 && !TARGET_LINUX */
+#if !defined(_WIN32)
static void
close_tun_generic (struct tuntap *tt)
{
@@ -1487,12 +1616,83 @@ close_tun_generic (struct tuntap *tt)
free (tt->actual_name);
clear_tuntap (tt);
}
+#endif /* !_WIN32 */
-#endif
+#if defined (TARGET_ANDROID)
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+{
+#define ANDROID_TUNNAME "vpnservice-tun"
+ int i;
+ struct user_pass up;
+ struct gc_arena gc = gc_new ();
+ bool opentun;
-#if defined(TARGET_LINUX)
+ int oldtunfd = tt->fd;
+
+ for (i = 0; i < tt->options.dns_len; ++i) {
+ management_android_control (management, "DNSSERVER",
+ print_in_addr_t(tt->options.dns[i], 0, &gc));
+ }
-#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
+ if(tt->options.domain)
+ management_android_control (management, "DNSDOMAIN", tt->options.domain);
+
+ int android_method = managment_android_persisttun_action (management);
+
+ /* Android 4.4 workaround */
+ if (oldtunfd >=0 && android_method == ANDROID_OPEN_AFTER_CLOSE)
+ {
+ close(oldtunfd);
+ openvpn_sleep(2);
+ }
+
+ if (oldtunfd >=0 && android_method == ANDROID_KEEP_OLD_TUN) {
+ /* keep the old fd */
+ opentun = true;
+ } else {
+ opentun = management_android_control (management, "OPENTUN", dev);
+ /* Pick up the fd from management interface after calling the
+ * OPENTUN command */
+ tt->fd = management->connection.lastfdreceived;
+ management->connection.lastfdreceived=-1;
+ }
+
+ if (oldtunfd>=0 && android_method == ANDROID_OPEN_BEFORE_CLOSE)
+ close(oldtunfd);
+
+ /* Set the actual name to a dummy name */
+ tt->actual_name = string_alloc (ANDROID_TUNNAME, NULL);
+
+ if ((tt->fd < 0) || !opentun)
+ msg (M_ERR, "ERROR: Cannot open TUN");
+
+ gc_free (&gc);
+}
+
+void
+close_tun (struct tuntap *tt)
+{
+ if (tt)
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(TARGET_LINUX)
#ifndef HAVE_LINUX_SOCKIOS_H
#error header file linux/sockios.h required
@@ -1533,8 +1733,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
* Process --tun-ipv6
*/
CLEAR (ifr);
- if (!tt->ipv6)
- ifr.ifr_flags = IFF_NO_PI;
+ ifr.ifr_flags = IFF_NO_PI;
#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
ifr.ifr_flags |= IFF_ONE_QUEUE;
@@ -1615,32 +1814,10 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
ASSERT (0);
}
-#endif
-
-#else
-
-void
-open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
-{
- open_tun_generic (dev, dev_type, dev_node, false, true, tt);
-}
-
-#endif /* HAVE_LINUX_IF_TUN_H */
+#endif /* !PENDANTIC */
#ifdef ENABLE_FEATURE_TUN_PERSIST
-/*
- * This can be removed in future
- * when all systems will use newer
- * linux-headers
- */
-#ifndef TUNSETOWNER
-#define TUNSETOWNER _IOW('T', 204, int)
-#endif
-#ifndef TUNSETGROUP
-#define TUNSETGROUP _IOW('T', 206, int)
-#endif
-
void
tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
{
@@ -1686,9 +1863,8 @@ close_tun (struct tuntap *tt)
{
if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig)
{
- struct argv argv;
+ struct argv argv = argv_new ();
struct gc_arena gc = gc_new ();
- argv_init (&argv);
#ifdef ENABLE_IPROUTE
if (is_tun_p2p (tt))
@@ -1708,7 +1884,7 @@ close_tun (struct tuntap *tt)
iproute_path,
tt->actual_name,
print_in_addr_t (tt->local, 0, &gc),
- count_netmask_bits(print_in_addr_t (tt->remote_netmask, 0, &gc))
+ netmask_to_netbits2(tt->remote_netmask)
);
}
#else
@@ -1722,7 +1898,7 @@ close_tun (struct tuntap *tt)
argv_msg (M_INFO, &argv);
openvpn_execve_check (&argv, NULL, 0, "Linux ip addr del failed");
- if (tt->ipv6 && tt->did_ifconfig_ipv6_setup)
+ if (tt->did_ifconfig_ipv6_setup)
{
const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
@@ -1759,53 +1935,13 @@ close_tun (struct tuntap *tt)
int
write_tun (struct tuntap* tt, uint8_t *buf, int len)
{
- if (tt->ipv6)
- {
- struct tun_pi pi;
- struct iphdr *iph;
- struct iovec vect[2];
- int ret;
-
- iph = (struct iphdr *)buf;
-
- pi.flags = 0;
-
- if(iph->version == 6)
- pi.proto = htons(OPENVPN_ETH_P_IPV6);
- else
- pi.proto = htons(OPENVPN_ETH_P_IPV4);
-
- vect[0].iov_len = sizeof(pi);
- vect[0].iov_base = &pi;
- vect[1].iov_len = len;
- vect[1].iov_base = buf;
-
- ret = writev(tt->fd, vect, 2);
- return(ret - sizeof(pi));
- }
- else
- return write (tt->fd, buf, len);
+ return write (tt->fd, buf, len);
}
int
read_tun (struct tuntap* tt, uint8_t *buf, int len)
{
- if (tt->ipv6)
- {
- struct iovec vect[2];
- struct tun_pi pi;
- int ret;
-
- vect[0].iov_len = sizeof(pi);
- vect[0].iov_base = &pi;
- vect[1].iov_len = len;
- vect[1].iov_base = buf;
-
- ret = readv(tt->fd, vect, 2);
- return(ret - sizeof(pi));
- }
- else
- return read (tt->fd, buf, len);
+ return read (tt->fd, buf, len);
}
#elif defined(TARGET_SOLARIS)
@@ -2009,10 +2145,9 @@ solaris_close_tun (struct tuntap *tt)
if (tt)
{
/* IPv6 interfaces need to be 'manually' de-configured */
- if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
+ if ( tt->did_ifconfig_ipv6_setup )
{
- struct argv argv;
- argv_init (&argv);
+ struct argv argv = argv_new ();
argv_printf( &argv, "%s %s inet6 unplumb",
IFCONFIG_PATH, tt->actual_name );
argv_msg (M_INFO, &argv);
@@ -2075,8 +2210,7 @@ static void
solaris_error_close (struct tuntap *tt, const struct env_set *es,
const char *actual, bool unplumb_inet6 )
{
- struct argv argv;
- argv_init (&argv);
+ struct argv argv = argv_new ();
if (unplumb_inet6)
{
@@ -2123,7 +2257,7 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
void
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
{
- open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
/* Enable multicast on the interface */
if (tt->fd >= 0)
@@ -2168,12 +2302,11 @@ close_tun (struct tuntap* tt)
else if (tt)
{
struct gc_arena gc = gc_new ();
- struct argv argv;
+ struct argv argv = argv_new ();
/* setup command, close tun dev (clears tt->actual_name!), run command
*/
- argv_init (&argv);
argv_printf (&argv, "%s %s destroy",
IFCONFIG_PATH, tt->actual_name);
@@ -2217,11 +2350,7 @@ read_tun (struct tuntap *tt, uint8_t *buf, int len)
void
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
{
-#ifdef NETBSD_MULTI_AF
- open_tun_generic (dev, dev_type, dev_node, true, true, tt);
-#else
- open_tun_generic (dev, dev_type, dev_node, false, true, tt);
-#endif
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
if (tt->fd >= 0)
{
@@ -2230,7 +2359,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
i = 0;
ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */
-#ifdef NETBSD_MULTI_AF
if ( tt->type == DEV_TYPE_TUN )
{
i = 1;
@@ -2239,7 +2367,6 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
}
}
-#endif
}
}
@@ -2260,12 +2387,11 @@ close_tun (struct tuntap *tt)
else if (tt)
{
struct gc_arena gc = gc_new ();
- struct argv argv;
+ struct argv argv = argv_new ();
/* setup command, close tun dev (clears tt->actual_name!), run command
*/
- argv_init (&argv);
argv_printf (&argv, "%s %s destroy",
IFCONFIG_PATH, tt->actual_name);
@@ -2278,8 +2404,6 @@ close_tun (struct tuntap *tt)
}
}
-#ifdef NETBSD_MULTI_AF
-
static inline int
netbsd_modify_read_write_return (int len)
{
@@ -2300,7 +2424,7 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len)
iph = (struct openvpn_iphdr *) buf;
- if (tt->ipv6 && OPENVPN_IPH_GET_VER(iph->version_len) == 6)
+ if (OPENVPN_IPH_GET_VER(iph->version_len) == 6)
type = htonl (AF_INET6);
else
type = htonl (AF_INET);
@@ -2335,21 +2459,6 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
return read (tt->fd, buf, len);
}
-#else /* not NETBSD_MULTI_AF -> older code, IPv4 only */
-
-int
-write_tun (struct tuntap* tt, uint8_t *buf, int len)
-{
- return write (tt->fd, buf, len);
-}
-
-int
-read_tun (struct tuntap* tt, uint8_t *buf, int len)
-{
- return read (tt->fd, buf, len);
-}
-#endif /* NETBSD_MULTI_AF */
-
#elif defined(TARGET_FREEBSD)
static inline int
@@ -2364,7 +2473,7 @@ freebsd_modify_read_write_return (int len)
void
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
{
- open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
{
@@ -2397,12 +2506,11 @@ close_tun (struct tuntap *tt)
}
else if (tt) /* close and destroy */
{
- struct argv argv;
+ struct argv argv = argv_new ();
/* setup command, close tun dev (clears tt->actual_name!), run command
*/
- argv_init (&argv);
argv_printf (&argv, "%s %s destroy",
IFCONFIG_PATH, tt->actual_name);
@@ -2426,7 +2534,7 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len)
iph = (struct ip *) buf;
- if (tt->ipv6 && iph->ip_v == 6)
+ if (iph->ip_v == 6)
type = htonl (AF_INET6);
else
type = htonl (AF_INET);
@@ -2475,7 +2583,7 @@ dragonfly_modify_read_write_return (int len)
void
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
{
- open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
if (tt->fd >= 0)
{
@@ -2509,7 +2617,7 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len)
iph = (struct ip *) buf;
- if (tt->ipv6 && iph->ip_v == 6)
+ if (iph->ip_v == 6)
type = htonl (AF_INET6);
else
type = htonl (AF_INET);
@@ -2702,7 +2810,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
{
/* No explicit utun and utun failed, try the generic way) */
msg (M_INFO, "Failed to open utun device. Falling back to /dev/tun device");
- open_tun_generic (dev, dev_type, NULL, true, true, tt);
+ open_tun_generic (dev, dev_type, NULL, true, tt);
}
else
{
@@ -2723,7 +2831,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
if (dev_node && strcmp (dev_node, "tun")==0)
dev_node=NULL;
- open_tun_generic (dev, dev_type, dev_node, true, true, tt);
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
}
}
@@ -2733,10 +2841,9 @@ close_tun (struct tuntap* tt)
if (tt)
{
struct gc_arena gc = gc_new ();
- struct argv argv;
- argv_init (&argv);
+ struct argv argv = argv_new ();
- if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
+ if (tt->did_ifconfig_ipv6_setup )
{
const char * ifconfig_ipv6_local =
print_in6_addr (tt->local_ipv6, 0, &gc);
@@ -2776,7 +2883,137 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)
return read (tt->fd, buf, len);
}
-#elif defined(WIN32)
+#elif defined(TARGET_AIX)
+
+void
+open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
+{
+ char tunname[256];
+ char dynamic_name[20];
+ const char *p;
+
+ if (tt->type == DEV_TYPE_NULL)
+ {
+ open_null (tt);
+ return;
+ }
+
+ if ( tt->type == DEV_TYPE_TUN)
+ {
+ msg(M_FATAL, "no support for 'tun' devices on AIX" );
+ }
+
+ if ( strncmp( dev, "tap", 3 ) != 0 || dev_node )
+ {
+ msg(M_FATAL, "'--dev %s' and/or '--dev-node' not supported on AIX, use '--dev tap0', 'tap1', etc.", dev );
+ }
+
+ if ( strcmp( dev, "tap" ) == 0 ) /* find first free tap dev */
+ { /* (= no /dev/tapN node) */
+ int i;
+ for (i=0; i<99; i++ )
+ {
+ openvpn_snprintf (tunname, sizeof (tunname), "/dev/tap%d", i);
+ if ( access( tunname, F_OK ) < 0 && errno == ENOENT )
+ { break; }
+ }
+ if ( i >= 99 )
+ msg( M_FATAL, "cannot find unused tap device" );
+
+ openvpn_snprintf( dynamic_name, sizeof(dynamic_name), "tap%d", i );
+ dev = dynamic_name;
+ }
+ else /* name given, sanity check */
+ {
+ /* ensure that dev name is "tap+<digits>" *only* */
+ p = &dev[3];
+ while( isdigit(*p) ) p++;
+ if ( *p != '\0' )
+ msg( M_FATAL, "TAP device name must be '--dev tapNNNN'" );
+
+ openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev);
+ }
+
+ /* pre-existing device?
+ */
+ if ( access( tunname, F_OK ) < 0 && errno == ENOENT )
+ {
+
+ /* tunnel device must be created with 'ifconfig tapN create'
+ */
+ struct argv argv = argv_new ();
+ struct env_set *es = env_set_create (NULL);
+ argv_printf (&argv, "%s %s create", IFCONFIG_PATH, dev);
+ argv_msg (M_INFO, &argv);
+ env_set_add( es, "ODMDIR=/etc/objrepos" );
+ openvpn_execve_check (&argv, es, S_FATAL, "AIX 'create tun interface' failed");
+ env_set_destroy (es);
+ }
+ else
+ {
+ /* we didn't make it, we're not going to break it */
+ tt->persistent_if = TRUE;
+ }
+
+ if ((tt->fd = open (tunname, O_RDWR)) < 0)
+ {
+ msg (M_ERR, "Cannot open TAP device '%s'", tunname);
+ }
+
+ set_nonblock (tt->fd);
+ set_cloexec (tt->fd); /* don't pass fd to scripts */
+ msg (M_INFO, "TUN/TAP device %s opened", tunname);
+
+ /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
+ tt->actual_name = string_alloc(dev, NULL);
+}
+
+/* tap devices need to be manually destroyed on AIX
+ */
+void
+close_tun (struct tuntap* tt)
+{
+ struct gc_arena gc = gc_new ();
+ struct argv argv = argv_new ();
+ struct env_set *es = env_set_create (NULL);
+
+ if (!tt) return;
+
+ /* persistent devices need IP address unconfig, others need destroyal
+ */
+ if (tt->persistent_if)
+ {
+ argv_printf (&argv, "%s %s 0.0.0.0 down",
+ IFCONFIG_PATH, tt->actual_name);
+ }
+ else
+ {
+ argv_printf (&argv, "%s %s destroy",
+ IFCONFIG_PATH, tt->actual_name);
+ }
+
+ close_tun_generic (tt);
+ argv_msg (M_INFO, &argv);
+ env_set_add( es, "ODMDIR=/etc/objrepos" );
+ openvpn_execve_check (&argv, es, 0, "AIX 'destroy tap interface' failed (non-critical)");
+
+ free(tt);
+ env_set_destroy (es);
+}
+
+int
+write_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return write (tt->fd, buf, len);
+}
+
+int
+read_tun (struct tuntap* tt, uint8_t *buf, int len)
+{
+ return read (tt->fd, buf, len);
+}
+
+#elif defined(_WIN32)
int
tun_read_queue (struct tuntap *tt, int maxsize)
@@ -4246,7 +4483,7 @@ dhcp_renew (const struct tuntap *tt)
*/
static void
-netsh_command (const struct argv *a, int n)
+netsh_command (const struct argv *a, int n, int msglevel)
{
int i;
for (i = 0; i < n; ++i)
@@ -4261,21 +4498,19 @@ netsh_command (const struct argv *a, int n)
return;
openvpn_sleep (4);
}
- msg (M_FATAL, "NETSH: command failed");
+ msg (msglevel, "NETSH: command failed");
}
void
ipconfig_register_dns (const struct env_set *es)
{
- struct argv argv;
+ struct argv argv = argv_new ();
bool status;
const char err[] = "ERROR: Windows ipconfig command failed";
msg (D_TUNTAP_INFO, "Start net commands...");
netcmd_semaphore_lock ();
- argv_init (&argv);
-
argv_printf (&argv, "%s%sc stop dnscache",
get_win_sys_path(),
WIN_NET_PATH_SUFFIX);
@@ -4411,7 +4646,7 @@ netsh_ifconfig_options (const char *type,
NETSH_PATH_SUFFIX,
type,
flex_name);
- netsh_command (&argv, 2);
+ netsh_command (&argv, 2, M_FATAL);
}
/* add new DNS/WINS settings to TAP interface */
@@ -4432,7 +4667,7 @@ netsh_ifconfig_options (const char *type,
type,
flex_name,
print_in_addr_t (addr_list[i], 0, &gc));
- netsh_command (&argv, 2);
+ netsh_command (&argv, 2, M_FATAL);
++count;
}
@@ -4507,7 +4742,7 @@ netsh_ifconfig (const struct tuntap_options *to,
print_in_addr_t (ip, 0, &gc),
print_in_addr_t (netmask, 0, &gc));
- netsh_command (&argv, 4);
+ netsh_command (&argv, 4, M_FATAL);
}
}
@@ -4543,8 +4778,7 @@ static void
netsh_enable_dhcp (const struct tuntap_options *to,
const char *actual_name)
{
- struct argv argv;
- argv_init (&argv);
+ struct argv argv = argv_new ();
/* example: netsh interface ip set address my-tap dhcp */
argv_printf (&argv,
@@ -4553,7 +4787,7 @@ netsh_enable_dhcp (const struct tuntap_options *to,
NETSH_PATH_SUFFIX,
actual_name);
- netsh_command (&argv, 4);
+ netsh_command (&argv, 4, M_FATAL);
argv_reset (&argv);
}
@@ -4750,10 +4984,43 @@ fork_dhcp_action (struct tuntap *tt)
}
}
+static void
+register_dns_service (const struct tuntap *tt)
+{
+ DWORD len;
+ HANDLE msg_channel = tt->options.msg_channel;
+ ack_message_t ack;
+ struct gc_arena gc = gc_new ();
+
+ message_header_t rdns = { msg_register_dns, sizeof(message_header_t), 0 };
+
+ if (!WriteFile (msg_channel, &rdns, sizeof (rdns), &len, NULL) ||
+ !ReadFile (msg_channel, &ack, sizeof (ack), &len, NULL))
+ {
+ msg (M_WARN, "Register_dns: could not talk to service: %s [status=0x%lx]",
+ strerror_win32 (GetLastError (), &gc), GetLastError ());
+ }
+
+ else if (ack.error_number != NO_ERROR)
+ {
+ msg (M_WARN, "Register_dns failed using service: %s [status=0x%x]",
+ strerror_win32 (ack.error_number, &gc), ack.error_number);
+ }
+
+ else
+ msg (M_INFO, "Register_dns request sent to the service");
+
+ gc_free (&gc);
+}
+
void
fork_register_dns_action (struct tuntap *tt)
{
- if (tt && tt->options.register_dns)
+ if (tt && tt->options.register_dns && tt->options.msg_channel)
+ {
+ register_dns_service (tt);
+ }
+ else if (tt && tt->options.register_dns)
{
struct gc_arena gc = gc_new ();
struct buffer cmd = alloc_buf_gc (256, &gc);
@@ -4798,7 +5065,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
/*netcmd_semaphore_lock ();*/
- msg( M_INFO, "open_tun, tt->ipv6=%d", tt->ipv6 );
+ msg( M_INFO, "open_tun");
if (tt->type == DEV_TYPE_NULL)
{
@@ -4924,11 +5191,10 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
/* usage of numeric constants is ugly, but this is really tied to
* *this* version of the driver
*/
- if ( tt->ipv6 && tt->type == DEV_TYPE_TUN &&
+ if (tt->type == DEV_TYPE_TUN &&
info[0] == 9 && info[1] < 8)
{
- msg( M_INFO, "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will be disabled. Upgrade to Tap-Win32 9.8 (2.2-beta3 release or later) or use TAP mode to get IPv6", (int) info[0], (int) info[1] );
- tt->ipv6 = false;
+ msg( M_INFO, "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will not work. Upgrade your Tap-Win32 driver.", (int) info[0], (int) info[1] );
}
/* tap driver 9.8 (2.2.0 and 2.2.1 release) is buggy
@@ -4936,7 +5202,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
if ( tt->type == DEV_TYPE_TUN &&
info[0] == 9 && info[1] == 8)
{
- msg( M_FATAL, "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade to Tap-Win32 9.9 (2.2.2 release or later) or use TAP mode", (int) info[0], (int) info[1] );
+ msg( M_FATAL, "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade your Tap-Win32 driver.", (int) info[0], (int) info[1] );
}
}
@@ -5122,13 +5388,35 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
/* flush arp cache */
if (index != TUN_ADAPTER_INDEX_INVALID)
{
- DWORD status;
+ DWORD status = -1;
+
+ if (tt->options.msg_channel)
+ {
+ ack_message_t ack;
+ flush_neighbors_message_t msg = {
+ .header = {
+ msg_flush_neighbors,
+ sizeof (flush_neighbors_message_t),
+ 0 },
+ .family = AF_INET,
+ .iface = { .index = index, .name = "" }
+ };
+
+ if (!WriteFile (tt->options.msg_channel, &msg, sizeof (msg), &len, NULL) ||
+ !ReadFile (tt->options.msg_channel, &ack, sizeof (ack), &len, NULL))
+ msg (M_WARN, "TUN: could not talk to service: %s [%lu]",
+ strerror_win32 (GetLastError (), &gc), GetLastError ());
+
+ status = ack.error_number;
+ }
+ else
+ status = FlushIpNetTable (index);
- if ((status = FlushIpNetTable (index)) == NO_ERROR)
+ if (status == NO_ERROR)
msg (M_INFO, "Successful ARP Flush on interface [%u] %s",
(unsigned int)index,
device_guid);
- else
+ else if (status != -1)
msg (D_TUNTAP_INFO, "NOTE: FlushIpNetTable failed on interface [%u] %s (status=%u) : %s",
(unsigned int)index,
device_guid,
@@ -5247,30 +5535,36 @@ close_tun (struct tuntap *tt)
if (tt)
{
- if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
+ if ( tt->did_ifconfig_ipv6_setup )
{
- const char *ifconfig_ipv6_local;
- struct argv argv;
- argv_init (&argv);
-
- /* remove route pointing to interface */
- delete_route_connected_v6_net(tt, NULL);
-
- /* "store=active" is needed in Windows 8(.1) to delete the
- * address we added (pointed out by Cedric Tabary).
- */
-
- /* netsh interface ipv6 delete address \"%s\" %s */
- ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
- argv_printf (&argv,
- "%s%sc interface ipv6 delete address %s %s store=active",
- get_win_sys_path(),
- NETSH_PATH_SUFFIX,
- tt->actual_name,
- ifconfig_ipv6_local );
-
- netsh_command (&argv, 1);
- argv_reset (&argv);
+ if (tt->options.msg_channel)
+ {
+ do_address_service (false, AF_INET6, tt);
+ }
+ else
+ {
+ const char *ifconfig_ipv6_local;
+ struct argv argv = argv_new ();
+
+ /* remove route pointing to interface */
+ delete_route_connected_v6_net(tt, NULL);
+
+ /* "store=active" is needed in Windows 8(.1) to delete the
+ * address we added (pointed out by Cedric Tabary).
+ */
+
+ /* netsh interface ipv6 delete address \"%s\" %s */
+ ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
+ argv_printf (&argv,
+ "%s%sc interface ipv6 delete address %s %s store=active",
+ get_win_sys_path(),
+ NETSH_PATH_SUFFIX,
+ tt->actual_name,
+ ifconfig_ipv6_local);
+
+ netsh_command (&argv, 1, M_WARN);
+ argv_reset (&argv);
+ }
}
#if 1
if (tt->ipapi_context_defined)
@@ -5377,7 +5671,7 @@ ipset2ascii_all (struct gc_arena *gc)
void
open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
{
- open_tun_generic (dev, dev_type, dev_node, false, true, tt);
+ open_tun_generic (dev, dev_type, dev_node, true, tt);
}
void