mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-06-10 17:33:17 -04:00
Windows reliability changes:
* Added code to make sure that the local PATH environmental variable points to the Windows system32 directory. * Added new --ip-win32 adaptive mode which tries 'dynamic' and then fails over to 'netsh' if the DHCP negotiation fails. * Made --ip-win32 adaptive the default. git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@739 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
1df5be5981
commit
c67d59cd5c
12 changed files with 410 additions and 113 deletions
|
|
@ -131,6 +131,7 @@
|
|||
#define D_SHOW_PKCS11 LOGLEV(7, 70, M_DEBUG) /* show PKCS#11 actions */
|
||||
#define D_ALIGN_DEBUG LOGLEV(7, 70, M_DEBUG) /* show verbose struct alignment info */
|
||||
#define D_PACKET_TRUNC_DEBUG LOGLEV(7, 70, M_DEBUG) /* PACKET_TRUNCATION_CHECK verbose */
|
||||
#define D_PING LOGLEV(7, 70, M_DEBUG) /* PING send/receive messages */
|
||||
|
||||
#define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG) /* show detailed description of each handshake */
|
||||
#define D_TLS_DEBUG_MED LOGLEV(8, 70, M_DEBUG) /* limited info from tls_session routines */
|
||||
|
|
|
|||
10
forward.c
10
forward.c
|
|
@ -274,8 +274,12 @@ check_add_routes_dowork (struct context *c)
|
|||
else
|
||||
{
|
||||
msg (D_ROUTE, "Route: Waiting for TUN/TAP interface to come up...");
|
||||
if (c->c1.tuntap)
|
||||
tun_standby (c->c1.tuntap);
|
||||
update_time ();
|
||||
if (c->c2.route_wakeup.n != 1)
|
||||
event_timeout_init (&c->c2.route_wakeup, 1, now);
|
||||
event_timeout_reset (&c->c2.ping_rec_interval);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -773,7 +777,7 @@ process_incoming_link (struct context *c)
|
|||
#endif
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; JYFIXME */
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
|
||||
ipv4_packet_size_verify (BPTR (&c->c2.buf),
|
||||
BLEN (&c->c2.buf),
|
||||
TUNNEL_TYPE (c->c1.tuntap),
|
||||
|
|
@ -807,7 +811,7 @@ process_incoming_link (struct context *c)
|
|||
/* Did we just receive an openvpn ping packet? */
|
||||
if (is_ping_msg (&c->c2.buf))
|
||||
{
|
||||
dmsg (D_PACKET_CONTENT, "RECEIVED PING PACKET");
|
||||
dmsg (D_PING, "RECEIVED PING PACKET");
|
||||
c->c2.buf.len = 0; /* drop packet */
|
||||
}
|
||||
|
||||
|
|
@ -911,7 +915,7 @@ process_incoming_tun (struct context *c)
|
|||
process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX, &c->c2.buf);
|
||||
|
||||
#ifdef PACKET_TRUNCATION_CHECK
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; JYFIXME */
|
||||
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
|
||||
ipv4_packet_size_verify (BPTR (&c->c2.buf),
|
||||
BLEN (&c->c2.buf),
|
||||
TUNNEL_TYPE (c->c1.tuntap),
|
||||
|
|
|
|||
6
init.c
6
init.c
|
|
@ -122,7 +122,7 @@ context_init_1 (struct context *c)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* JYFIXME -- test get_user_pass with GET_USER_PASS_NEED_OK flag */
|
||||
#if 0 /* test get_user_pass with GET_USER_PASS_NEED_OK flag */
|
||||
{
|
||||
/*
|
||||
* In the management interface, you can okay the request by entering "needok token-insertion-request ok"
|
||||
|
|
@ -175,6 +175,8 @@ context_gc_free (struct context *c)
|
|||
bool
|
||||
init_static (void)
|
||||
{
|
||||
configure_path ();
|
||||
|
||||
#if defined(USE_CRYPTO) && defined(DMALLOC)
|
||||
openssl_dmalloc_init ();
|
||||
#endif
|
||||
|
|
@ -964,6 +966,8 @@ do_up (struct context *c, bool pulled_options, unsigned int option_types_found)
|
|||
{
|
||||
event_timeout_init (&c->c2.route_wakeup, c->options.route_delay, now);
|
||||
event_timeout_init (&c->c2.route_wakeup_expire, c->options.route_delay + c->options.route_delay_window, now);
|
||||
if (c->c1.tuntap)
|
||||
tun_standby_init (c->c1.tuntap);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
30
misc.c
30
misc.c
|
|
@ -1372,3 +1372,33 @@ openvpn_sleep (const int n)
|
|||
#endif
|
||||
sleep (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure PATH. On Windows, sometimes PATH is not set correctly
|
||||
* by default.
|
||||
*/
|
||||
void
|
||||
configure_path (void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
FILE *fp;
|
||||
fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
|
||||
if (fp)
|
||||
{
|
||||
const int bufsiz = 512;
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer oldpath = alloc_buf_gc (bufsiz, &gc);
|
||||
struct buffer newpath = alloc_buf_gc (bufsiz, &gc);
|
||||
DWORD status;
|
||||
fclose (fp);
|
||||
status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
|
||||
if (status > 0)
|
||||
{
|
||||
buf_printf (&newpath, "C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;%s", BSTR(&oldpath));
|
||||
SetEnvironmentVariable ("PATH", BSTR(&newpath));
|
||||
/*printf ("PATH: %s\n", BSTR(&newpath));*/
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
2
misc.h
2
misc.h
|
|
@ -257,4 +257,6 @@ const char *safe_print (const char *str, struct gc_arena *gc);
|
|||
*/
|
||||
void openvpn_sleep (const int n);
|
||||
|
||||
void configure_path (void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
12
options.c
12
options.c
|
|
@ -612,7 +612,7 @@ init_options (struct options *o)
|
|||
o->tuntap_options.txqueuelen = 100;
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
o->tuntap_options.ip_win32_type = IPW32_SET_DHCP_MASQ;
|
||||
o->tuntap_options.ip_win32_type = IPW32_SET_ADAPTIVE;
|
||||
o->tuntap_options.dhcp_lease_time = 31536000; /* one year */
|
||||
o->tuntap_options.dhcp_masq_offset = 0; /* use network address as internal DHCP server address */
|
||||
o->route_method = ROUTE_METHOD_IPAPI;
|
||||
|
|
@ -1469,9 +1469,10 @@ options_postprocess (struct options *options, bool first_time)
|
|||
&& !(pull || (options->ifconfig_local && options->ifconfig_remote_netmask)))
|
||||
msg (M_USAGE, "On Windows, --ip-win32 doesn't make sense unless --ifconfig is also used");
|
||||
|
||||
if (options->tuntap_options.dhcp_options &&
|
||||
options->tuntap_options.ip_win32_type != IPW32_SET_DHCP_MASQ)
|
||||
msg (M_USAGE, "--dhcp-options requires --ip-win32 dynamic");
|
||||
if (options->tuntap_options.dhcp_options
|
||||
&& options->tuntap_options.ip_win32_type != IPW32_SET_DHCP_MASQ
|
||||
&& options->tuntap_options.ip_win32_type != IPW32_SET_ADAPTIVE)
|
||||
msg (M_USAGE, "--dhcp-options requires --ip-win32 dynamic or adaptive");
|
||||
|
||||
if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && !options->route_delay_defined)
|
||||
{
|
||||
|
|
@ -4280,6 +4281,9 @@ add_option (struct options *options,
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (index == IPW32_SET_ADAPTIVE)
|
||||
options->route_delay_window = IPW32_SET_ADAPTIVE_DELAY_WINDOW;
|
||||
|
||||
if (index == IPW32_SET_DHCP_MASQ)
|
||||
{
|
||||
if (p[2])
|
||||
|
|
|
|||
2
ping.c
2
ping.c
|
|
@ -92,5 +92,5 @@ check_ping_send_dowork (struct context *c)
|
|||
* encrypt, sign, etc.
|
||||
*/
|
||||
encrypt_sign (c, true);
|
||||
dmsg (D_PACKET_CONTENT, "SENT PING");
|
||||
dmsg (D_PING, "SENT PING");
|
||||
}
|
||||
|
|
|
|||
1
plugin.h
1
plugin.h
|
|
@ -75,7 +75,6 @@ struct plugin {
|
|||
|
||||
struct plugin_per_client
|
||||
{
|
||||
/* bool initialized; JYFIXME */
|
||||
void *per_client_context[MAX_PLUGINS];
|
||||
};
|
||||
|
||||
|
|
|
|||
2
route.c
2
route.c
|
|
@ -22,6 +22,8 @@
|
|||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* JYFIXME WIN32 todo: add adaptive route-method */
|
||||
|
||||
/*
|
||||
* Support routines for adding/deleting network routes.
|
||||
*/
|
||||
|
|
|
|||
2
ssl.c
2
ssl.c
|
|
@ -315,9 +315,7 @@ ssl_set_auth_nocache (void)
|
|||
void
|
||||
ssl_purge_auth (void)
|
||||
{
|
||||
#if 1 /* JYFIXME -- todo: bad private key should trigger a signal, then this code can be included */
|
||||
purge_user_pass (&passbuf, true);
|
||||
#endif
|
||||
purge_user_pass (&auth_user_pass, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
431
tun.c
431
tun.c
|
|
@ -47,6 +47,22 @@
|
|||
|
||||
#include "memdbg.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define NI_TEST_FIRST (1<<0)
|
||||
#define NI_IP_NETMASK (1<<1)
|
||||
#define NI_OPTIONS (1<<2)
|
||||
|
||||
static void netsh_ifconfig (const struct tuntap_options *to,
|
||||
const char *flex_name,
|
||||
const in_addr_t ip,
|
||||
const in_addr_t netmask,
|
||||
unsigned int flags);
|
||||
|
||||
static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_SOLARIS
|
||||
static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual);
|
||||
#endif
|
||||
|
|
@ -125,7 +141,7 @@ guess_tuntap_dev (const char *dev,
|
|||
const int dt = dev_type_enum (dev, dev_type);
|
||||
if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP)
|
||||
{
|
||||
return get_netsh_id (dev_node, gc);
|
||||
return netsh_get_id (dev_node, gc);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -768,8 +784,6 @@ do_ifconfig (struct tuntap *tt,
|
|||
|
||||
#elif defined (WIN32)
|
||||
{
|
||||
const char *netmask;
|
||||
|
||||
/*
|
||||
* Make sure that both ifconfig addresses are part of the
|
||||
* same .252 subnet.
|
||||
|
|
@ -778,36 +792,30 @@ do_ifconfig (struct tuntap *tt,
|
|||
{
|
||||
verify_255_255_255_252 (tt->local, tt->remote_netmask);
|
||||
tt->adapter_netmask = ~3;
|
||||
netmask = print_in_addr_t (tt->adapter_netmask, 0, &gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
netmask = ifconfig_remote_netmask;
|
||||
tt->adapter_netmask = tt->remote_netmask;
|
||||
}
|
||||
|
||||
/* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */
|
||||
openvpn_snprintf (command_line, sizeof (command_line),
|
||||
"netsh interface ip set address \"%s\" static %s %s",
|
||||
actual,
|
||||
ifconfig_local,
|
||||
netmask);
|
||||
|
||||
switch (tt->options.ip_win32_type)
|
||||
{
|
||||
case IPW32_SET_MANUAL:
|
||||
msg (M_INFO, "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)",
|
||||
actual,
|
||||
ifconfig_local,
|
||||
netmask);
|
||||
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-Win32 adapter, you must also specify --dev-node");
|
||||
netcmd_semaphore_lock ();
|
||||
msg (M_INFO, "%s", command_line);
|
||||
system_check (command_line, es, S_FATAL, "ERROR: netsh command failed");
|
||||
netcmd_semaphore_release ();
|
||||
|
||||
netsh_ifconfig (&tt->options,
|
||||
actual,
|
||||
tt->local,
|
||||
tt->adapter_netmask,
|
||||
NI_IP_NETMASK|NI_OPTIONS);
|
||||
|
||||
break;
|
||||
}
|
||||
tt->did_ifconfig = true;
|
||||
|
|
@ -2262,7 +2270,7 @@ get_unspecified_device_guid (const int device_number,
|
|||
if (act)
|
||||
buf_printf (&actual, "%s", act);
|
||||
else
|
||||
buf_printf (&actual, "NULL");
|
||||
buf_printf (&actual, "%s", tap_reg->guid);
|
||||
}
|
||||
|
||||
/* Save GUID for return value */
|
||||
|
|
@ -2305,7 +2313,7 @@ get_device_guid (const char *name,
|
|||
if (act)
|
||||
buf_printf (&actual, "%s", act);
|
||||
else
|
||||
buf_printf (&actual, "NULL");
|
||||
buf_printf (&actual, "%s", name);
|
||||
return BSTR (&ret);
|
||||
}
|
||||
|
||||
|
|
@ -2323,39 +2331,6 @@ get_device_guid (const char *name,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a TAP name for netsh commands.
|
||||
*/
|
||||
const char *
|
||||
get_netsh_id (const char *dev_node, struct gc_arena *gc)
|
||||
{
|
||||
const struct tap_reg *tap_reg = get_tap_reg (gc);
|
||||
const struct panel_reg *panel_reg = get_panel_reg (gc);
|
||||
struct buffer actual = alloc_buf_gc (256, gc);
|
||||
const char *guid;
|
||||
|
||||
at_least_one_tap_win32 (tap_reg);
|
||||
|
||||
if (dev_node)
|
||||
{
|
||||
guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
|
||||
|
||||
if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */
|
||||
guid = NULL;
|
||||
}
|
||||
|
||||
if (!guid)
|
||||
return "NULL"; /* not found */
|
||||
else if (strcmp (BPTR (&actual), "NULL"))
|
||||
return BPTR (&actual); /* control panel name */
|
||||
else
|
||||
return guid; /* no control panel name, return GUID instead */
|
||||
}
|
||||
|
||||
/*
|
||||
* Get adapter info list
|
||||
*/
|
||||
|
|
@ -2394,23 +2369,26 @@ get_per_adapter_info (const DWORD index, struct gc_arena *gc)
|
|||
IP_PER_ADAPTER_INFO *pi = NULL;
|
||||
DWORD status;
|
||||
|
||||
if ((status = GetPerAdapterInfo (index, NULL, &size)) != ERROR_BUFFER_OVERFLOW)
|
||||
if (index != ~0)
|
||||
{
|
||||
msg (M_INFO, "GetPerAdapterInfo #1 failed (status=%u) : %s",
|
||||
(unsigned int)status,
|
||||
strerror_win32 (status, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
pi = (PIP_PER_ADAPTER_INFO) gc_malloc (size, false, gc);
|
||||
if ((status = GetPerAdapterInfo ((ULONG)index, pi, &size)) == ERROR_SUCCESS)
|
||||
return pi;
|
||||
else
|
||||
if ((status = GetPerAdapterInfo (index, NULL, &size)) != ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
msg (M_INFO, "GetPerAdapterInfo #2 failed (status=%u) : %s",
|
||||
msg (M_INFO, "GetPerAdapterInfo #1 failed (status=%u) : %s",
|
||||
(unsigned int)status,
|
||||
strerror_win32 (status, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
pi = (PIP_PER_ADAPTER_INFO) gc_malloc (size, false, gc);
|
||||
if ((status = GetPerAdapterInfo ((ULONG)index, pi, &size)) == ERROR_SUCCESS)
|
||||
return pi;
|
||||
else
|
||||
{
|
||||
msg (M_INFO, "GetPerAdapterInfo #2 failed (status=%u) : %s",
|
||||
(unsigned int)status,
|
||||
strerror_win32 (status, gc));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pi;
|
||||
}
|
||||
|
|
@ -2547,6 +2525,20 @@ get_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, i
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
test_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
|
||||
{
|
||||
if (ai)
|
||||
{
|
||||
in_addr_t ip_adapter = 0;
|
||||
in_addr_t netmask_adapter = 0;
|
||||
const bool status = get_adapter_ip_netmask (ai, 0, &ip_adapter, &netmask_adapter);
|
||||
return (status && ip_adapter == ip && netmask_adapter == netmask);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const IP_ADAPTER_INFO *
|
||||
get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list)
|
||||
{
|
||||
|
|
@ -2675,16 +2667,28 @@ adapter_index_of_ip (const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count
|
|||
* Given an adapter index, return true if the adapter
|
||||
* is DHCP disabled.
|
||||
*/
|
||||
static bool
|
||||
dhcp_disabled (DWORD index)
|
||||
|
||||
#define DHCP_STATUS_UNDEF 0
|
||||
#define DHCP_STATUS_ENABLED 1
|
||||
#define DHCP_STATUS_DISABLED 2
|
||||
|
||||
static int
|
||||
dhcp_status (DWORD index)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc);
|
||||
bool ret = false;
|
||||
|
||||
if (ai && !ai->DhcpEnabled)
|
||||
ret = true;
|
||||
int ret = DHCP_STATUS_UNDEF;
|
||||
if (index != ~0)
|
||||
{
|
||||
const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc);
|
||||
|
||||
if (ai)
|
||||
{
|
||||
if (ai->DhcpEnabled)
|
||||
ret = DHCP_STATUS_ENABLED;
|
||||
else
|
||||
ret = DHCP_STATUS_DISABLED;
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2733,28 +2737,75 @@ delete_temp_addresses (DWORD index)
|
|||
* Get interface index for use with IP Helper API functions.
|
||||
*/
|
||||
static DWORD
|
||||
get_interface_index (const char *guid)
|
||||
get_adapter_index_method_1 (const char *guid)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
ULONG index;
|
||||
ULONG index = ~0;
|
||||
DWORD status;
|
||||
wchar_t wbuf[256];
|
||||
snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
|
||||
wbuf [SIZE(wbuf) - 1] = 0;
|
||||
if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR)
|
||||
index = ~0;
|
||||
gc_free (&gc);
|
||||
return index;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
get_adapter_index_method_2 (const char *guid)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
DWORD index = ~0;
|
||||
|
||||
const IP_ADAPTER_INFO *list = get_adapter_info_list (&gc);
|
||||
|
||||
while (list)
|
||||
{
|
||||
msg (M_INFO, "NOTE: could not get adapter index for %S, status=%u : %s",
|
||||
wbuf,
|
||||
(unsigned int)status,
|
||||
strerror_win32 (status, &gc));
|
||||
gc_free (&gc);
|
||||
return (DWORD)~0;
|
||||
if (!strcmp (guid, list->AdapterName))
|
||||
{
|
||||
index = list->Index;
|
||||
break;
|
||||
}
|
||||
list = list->Next;
|
||||
}
|
||||
else
|
||||
|
||||
gc_free (&gc);
|
||||
return index;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
get_adapter_index (const char *guid)
|
||||
{
|
||||
DWORD index;
|
||||
index = get_adapter_index_method_1 (guid);
|
||||
if (index == ~0)
|
||||
index = get_adapter_index_method_2 (guid);
|
||||
if (index == ~0)
|
||||
msg (M_INFO, "NOTE: could not get adapter index for %s", guid);
|
||||
return index;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
get_adapter_index_flexible (const char *name) /* actual name or GUID */
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
DWORD index;
|
||||
index = get_adapter_index_method_1 (name);
|
||||
if (index == ~0)
|
||||
index = get_adapter_index_method_2 (name);
|
||||
if (index == ~0)
|
||||
{
|
||||
gc_free (&gc);
|
||||
return index;
|
||||
const struct tap_reg *tap_reg = get_tap_reg (&gc);
|
||||
const struct panel_reg *panel_reg = get_panel_reg (&gc);
|
||||
const char *guid = name_to_guid (name, tap_reg, panel_reg);
|
||||
index = get_adapter_index_method_1 (guid);
|
||||
if (index == ~0)
|
||||
index = get_adapter_index_method_2 (guid);
|
||||
}
|
||||
if (index == ~0)
|
||||
msg (M_INFO, "NOTE: could not get adapter index for name/GUID '%s'", name);
|
||||
gc_free (&gc);
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2869,7 +2920,7 @@ tap_allow_nonadmin_access (const char *dev_node)
|
|||
const struct panel_reg *panel_reg = get_panel_reg (&gc);
|
||||
const char *device_guid = NULL;
|
||||
HANDLE hand;
|
||||
char guid_buffer[256];
|
||||
char actual_buffer[256];
|
||||
char device_path[256];
|
||||
|
||||
at_least_one_tap_win32 (tap_reg);
|
||||
|
|
@ -2877,7 +2928,7 @@ tap_allow_nonadmin_access (const char *dev_node)
|
|||
if (dev_node)
|
||||
{
|
||||
/* Get the device GUID for the device specified with --dev-node. */
|
||||
device_guid = get_device_guid (dev_node, guid_buffer, sizeof (guid_buffer), tap_reg, panel_reg, &gc);
|
||||
device_guid = get_device_guid (dev_node, actual_buffer, sizeof (actual_buffer), tap_reg, panel_reg, &gc);
|
||||
|
||||
if (!device_guid)
|
||||
msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node);
|
||||
|
|
@ -2912,8 +2963,8 @@ tap_allow_nonadmin_access (const char *dev_node)
|
|||
while (true)
|
||||
{
|
||||
device_guid = get_unspecified_device_guid (device_number,
|
||||
guid_buffer,
|
||||
sizeof (guid_buffer),
|
||||
actual_buffer,
|
||||
sizeof (actual_buffer),
|
||||
tap_reg,
|
||||
panel_reg,
|
||||
&gc);
|
||||
|
|
@ -3007,6 +3058,149 @@ dhcp_renew (const struct tuntap *tt)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* netsh functions
|
||||
*/
|
||||
|
||||
static void
|
||||
netsh_command (const char *cmd, int n)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
bool status;
|
||||
netcmd_semaphore_lock ();
|
||||
msg (M_INFO, "NETSH: %s", cmd);
|
||||
status = system_check (cmd, NULL, 0, "ERROR: netsh command failed");
|
||||
netcmd_semaphore_release ();
|
||||
if (status)
|
||||
return;
|
||||
openvpn_sleep (5);
|
||||
}
|
||||
msg (M_FATAL, "NETSH: command failed");
|
||||
}
|
||||
|
||||
static void
|
||||
netsh_ifconfig (const struct tuntap_options *to,
|
||||
const char *flex_name,
|
||||
const in_addr_t ip,
|
||||
const in_addr_t netmask,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer out = alloc_buf_gc (256, &gc);
|
||||
const IP_ADAPTER_INFO *ai = NULL;
|
||||
const IP_PER_ADAPTER_INFO *pai = NULL;
|
||||
|
||||
if (flags & NI_TEST_FIRST)
|
||||
{
|
||||
const IP_ADAPTER_INFO *list = get_adapter_info_list (&gc);
|
||||
const int index = get_adapter_index_flexible (flex_name);
|
||||
ai = get_adapter (list, index);
|
||||
pai = get_per_adapter_info (index, &gc);
|
||||
}
|
||||
|
||||
if (flags & NI_IP_NETMASK)
|
||||
{
|
||||
if (test_adapter_ip_netmask (ai, ip, netmask))
|
||||
{
|
||||
msg (M_INFO, "NETSH: \"%s\" %s/%s [already set]",
|
||||
flex_name,
|
||||
print_in_addr_t (ip, 0, &gc),
|
||||
print_in_addr_t (netmask, 0, &gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */
|
||||
buf_init (&out, 0);
|
||||
buf_printf (&out,
|
||||
"netsh interface ip set address \"%s\" static %s %s",
|
||||
flex_name,
|
||||
print_in_addr_t (ip, 0, &gc),
|
||||
print_in_addr_t (netmask, 0, &gc));
|
||||
|
||||
netsh_command (BSTR(&out), 4);
|
||||
}
|
||||
}
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
static void
|
||||
netsh_enable_dhcp (const struct tuntap_options *to,
|
||||
const char *actual_name)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer out = alloc_buf_gc (256, &gc);
|
||||
|
||||
/* example: netsh interface ip set address my-tap dhcp */
|
||||
buf_printf (&out,
|
||||
"netsh interface ip set address \"%s\" dhcp",
|
||||
actual_name);
|
||||
|
||||
netsh_command (BSTR(&out), 4);
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a TAP name for netsh commands.
|
||||
*/
|
||||
static const char *
|
||||
netsh_get_id (const char *dev_node, struct gc_arena *gc)
|
||||
{
|
||||
const struct tap_reg *tap_reg = get_tap_reg (gc);
|
||||
const struct panel_reg *panel_reg = get_panel_reg (gc);
|
||||
struct buffer actual = alloc_buf_gc (256, gc);
|
||||
const char *guid;
|
||||
|
||||
at_least_one_tap_win32 (tap_reg);
|
||||
|
||||
if (dev_node)
|
||||
{
|
||||
guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
|
||||
}
|
||||
else
|
||||
{
|
||||
guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
|
||||
|
||||
if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */
|
||||
guid = NULL;
|
||||
}
|
||||
|
||||
if (!guid)
|
||||
return "NULL"; /* not found */
|
||||
else if (strcmp (BPTR (&actual), "NULL"))
|
||||
return BPTR (&actual); /* control panel name */
|
||||
else
|
||||
return guid; /* no control panel name, return GUID instead */
|
||||
}
|
||||
|
||||
/*
|
||||
* Called iteratively on TAP-Win32 wait-for-initialization polling loop
|
||||
*/
|
||||
void
|
||||
tun_standby_init (struct tuntap *tt)
|
||||
{
|
||||
tt->standby_iter = 0;
|
||||
}
|
||||
|
||||
void
|
||||
tun_standby (struct tuntap *tt)
|
||||
{
|
||||
++tt->standby_iter;
|
||||
if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE
|
||||
&& tt->standby_iter % IPW32_SET_ADAPTIVE_TRY_NETSH == 0)
|
||||
{
|
||||
msg (M_INFO, "NOTE: --ip-win32 dynamic failed, now trying --ip-win32 netsh (this may take some time)");
|
||||
netsh_ifconfig (&tt->options,
|
||||
tt->actual_name,
|
||||
tt->local,
|
||||
tt->adapter_netmask,
|
||||
NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert DHCP options from the command line / config file
|
||||
* into a raw DHCP-format options string.
|
||||
|
|
@ -3091,6 +3285,8 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
char device_path[256];
|
||||
const char *device_guid = NULL;
|
||||
DWORD len;
|
||||
bool dhcp_masq = false;
|
||||
bool dhcp_masq_post = false;
|
||||
|
||||
/*netcmd_semaphore_lock ();*/
|
||||
|
||||
|
|
@ -3117,14 +3313,14 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
{
|
||||
const struct tap_reg *tap_reg = get_tap_reg (&gc);
|
||||
const struct panel_reg *panel_reg = get_panel_reg (&gc);
|
||||
char guid_buffer[256];
|
||||
char actual_buffer[256];
|
||||
|
||||
at_least_one_tap_win32 (tap_reg);
|
||||
|
||||
if (dev_node)
|
||||
{
|
||||
/* Get the device GUID for the device specified with --dev-node. */
|
||||
device_guid = get_device_guid (dev_node, guid_buffer, sizeof (guid_buffer), tap_reg, panel_reg, &gc);
|
||||
device_guid = get_device_guid (dev_node, actual_buffer, sizeof (actual_buffer), tap_reg, panel_reg, &gc);
|
||||
|
||||
if (!device_guid)
|
||||
msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node);
|
||||
|
|
@ -3156,8 +3352,8 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
while (true)
|
||||
{
|
||||
device_guid = get_unspecified_device_guid (device_number,
|
||||
guid_buffer,
|
||||
sizeof (guid_buffer),
|
||||
actual_buffer,
|
||||
sizeof (actual_buffer),
|
||||
tap_reg,
|
||||
panel_reg,
|
||||
&gc);
|
||||
|
|
@ -3192,10 +3388,11 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
|
||||
/* translate high-level device name into a device instance
|
||||
GUID using the registry */
|
||||
tt->actual_name = string_alloc (guid_buffer, NULL);
|
||||
tt->actual_name = string_alloc (actual_buffer, NULL);
|
||||
}
|
||||
|
||||
msg (M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path);
|
||||
tt->adapter_index = get_adapter_index (device_guid);
|
||||
|
||||
/* get driver version info */
|
||||
{
|
||||
|
|
@ -3230,6 +3427,42 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Preliminaries for setting TAP-Win32 adapter TCP/IP
|
||||
* properties via --ip-win32 dynamic or --ip-win32 adaptive.
|
||||
*/
|
||||
if (tt->did_ifconfig_setup)
|
||||
{
|
||||
if (tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
|
||||
{
|
||||
/*
|
||||
* If adapter is set to non-DHCP, set to DHCP mode.
|
||||
*/
|
||||
if (dhcp_status (tt->adapter_index) == DHCP_STATUS_DISABLED)
|
||||
netsh_enable_dhcp (&tt->options, tt->actual_name);
|
||||
dhcp_masq = true;
|
||||
dhcp_masq_post = true;
|
||||
}
|
||||
else if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
|
||||
{
|
||||
/*
|
||||
* If adapter is set to non-DHCP, use netsh right away.
|
||||
*/
|
||||
if (dhcp_status (tt->adapter_index) != DHCP_STATUS_ENABLED)
|
||||
{
|
||||
netsh_ifconfig (&tt->options,
|
||||
tt->actual_name,
|
||||
tt->local,
|
||||
tt->adapter_netmask,
|
||||
NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
|
||||
}
|
||||
else
|
||||
{
|
||||
dhcp_masq = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set point-to-point mode if TUN device */
|
||||
|
||||
if (tt->type == DEV_TYPE_TUN)
|
||||
|
|
@ -3273,7 +3506,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
|
||||
/* should we tell the TAP-Win32 driver to masquerade as a DHCP server as a means
|
||||
of setting the adapter address? */
|
||||
if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
|
||||
if (dhcp_masq)
|
||||
{
|
||||
uint32_t ep[4];
|
||||
|
||||
|
|
@ -3320,6 +3553,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
|
||||
ASSERT (ep[3] > 0);
|
||||
|
||||
#if 1 /* TAP_IOCTL_CONFIG_DHCP_MASQ -- disable to simulate bad DHCP negotiation */
|
||||
if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ,
|
||||
ep, sizeof (ep),
|
||||
ep, sizeof (ep), &len, NULL))
|
||||
|
|
@ -3332,6 +3566,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
print_in_addr_t (ep[2], IA_NET_ORDER, &gc),
|
||||
ep[3]
|
||||
);
|
||||
#endif
|
||||
|
||||
/* user-supplied DHCP options capability */
|
||||
if (tt->options.dhcp_options)
|
||||
|
|
@ -3368,8 +3603,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
|
||||
/* possibly use IP Helper API to set IP address on adapter */
|
||||
{
|
||||
DWORD index = get_interface_index (device_guid);
|
||||
tt->adapter_index = index;
|
||||
const DWORD index = tt->adapter_index;
|
||||
|
||||
/* flush arp cache */
|
||||
if (index != (DWORD)~0)
|
||||
|
|
@ -3393,10 +3627,10 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
* make sure the TCP/IP properties for the adapter are
|
||||
* set correctly.
|
||||
*/
|
||||
if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
|
||||
if (dhcp_masq_post)
|
||||
{
|
||||
/* check dhcp enable status */
|
||||
if (dhcp_disabled (index))
|
||||
if (dhcp_status (index) == DHCP_STATUS_DISABLED)
|
||||
msg (M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
|
||||
|
||||
/* force an explicit DHCP lease renewal on TAP adapter? */
|
||||
|
|
@ -3420,7 +3654,7 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6
|
|||
}
|
||||
|
||||
/* check dhcp enable status */
|
||||
if (dhcp_disabled (index))
|
||||
if (dhcp_status (index) == DHCP_STATUS_DISABLED)
|
||||
msg (M_WARN, "NOTE: You have selected (explicitly or by default) '--ip-win32 ipapi', which has a better chance of working correctly if the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
|
||||
|
||||
/* delete previously added IP addresses which were not
|
||||
|
|
@ -3556,7 +3790,8 @@ static const struct ipset_names ipset_names[] = {
|
|||
{"manual"},
|
||||
{"netsh"},
|
||||
{"ipapi"},
|
||||
{"dynamic"}
|
||||
{"dynamic"},
|
||||
{"adaptive"}
|
||||
};
|
||||
|
||||
int
|
||||
|
|
|
|||
24
tun.h
24
tun.h
|
|
@ -40,6 +40,10 @@
|
|||
|
||||
#ifdef WIN32
|
||||
|
||||
/* time constants for --ip-win32 adaptive */
|
||||
#define IPW32_SET_ADAPTIVE_DELAY_WINDOW 300
|
||||
#define IPW32_SET_ADAPTIVE_TRY_NETSH 20
|
||||
|
||||
struct tuntap_options {
|
||||
/* --ip-win32 options */
|
||||
bool ip_win32_defined;
|
||||
|
|
@ -48,7 +52,8 @@ struct tuntap_options {
|
|||
# define IPW32_SET_NETSH 1 /* "--ip-win32 netsh" */
|
||||
# define IPW32_SET_IPAPI 2 /* "--ip-win32 ipapi" */
|
||||
# define IPW32_SET_DHCP_MASQ 3 /* "--ip-win32 dynamic" */
|
||||
# define IPW32_SET_N 4
|
||||
# define IPW32_SET_ADAPTIVE 4 /* "--ip-win32 adaptive" */
|
||||
# define IPW32_SET_N 5
|
||||
int ip_win32_type;
|
||||
|
||||
/* --ip-win32 dynamic options */
|
||||
|
|
@ -155,6 +160,8 @@ struct tuntap
|
|||
/* Windows adapter index for TAP-Win32 adapter,
|
||||
~0 if undefined */
|
||||
DWORD adapter_index;
|
||||
|
||||
int standby_iter;
|
||||
#else
|
||||
int fd; /* file descriptor for TUN/TAP dev */
|
||||
#endif
|
||||
|
|
@ -318,12 +325,13 @@ void tun_show_debug (struct tuntap *tt);
|
|||
bool dhcp_release (const struct tuntap *tt);
|
||||
bool dhcp_renew (const struct tuntap *tt);
|
||||
|
||||
void tun_standby_init (struct tuntap *tt);
|
||||
void tun_standby (struct tuntap *tt);
|
||||
|
||||
int tun_read_queue (struct tuntap *tt, int maxsize);
|
||||
int tun_write_queue (struct tuntap *tt, struct buffer *buf);
|
||||
int tun_finalize (HANDLE h, struct overlapped_io *io, struct buffer *buf);
|
||||
|
||||
const char *get_netsh_id (const char *dev_node, struct gc_arena *gc);
|
||||
|
||||
static inline bool
|
||||
tuntap_stop (int status)
|
||||
{
|
||||
|
|
@ -379,6 +387,16 @@ tuntap_stop (int status)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tun_standby_init (struct tuntap *tt)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
tun_standby (struct tuntap *tt)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in a new issue