summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2013-11-19 15:43:11 +0100
committerArne Schwabe <arne@rfc2549.org>2013-11-19 15:43:11 +0100
commitbf13e848dc3de1b5cf0143d823f8a86a53ac71b8 (patch)
tree1abe31f00d3eeac2690aba7c6816bb07a00eb970
parent42f552b5eeb209ba32282c87f61414bcaf85cf23 (diff)
Update dual stack patch set, workaround for Android 4.4
-rw-r--r--openvpn/.gitignore1
-rw-r--r--openvpn/configure.ac8
-rw-r--r--openvpn/doc/openvpn.820
-rw-r--r--openvpn/src/openvpn/forward-inline.h1
-rw-r--r--openvpn/src/openvpn/init.c20
-rw-r--r--openvpn/src/openvpn/manage.c27
-rw-r--r--openvpn/src/openvpn/manage.h5
-rw-r--r--openvpn/src/openvpn/options.c26
-rw-r--r--openvpn/src/openvpn/options.h1
-rw-r--r--openvpn/src/openvpn/proxy.c86
-rw-r--r--openvpn/src/openvpn/ps.c4
-rw-r--r--openvpn/src/openvpn/socket.c347
-rw-r--r--openvpn/src/openvpn/socket.h36
-rw-r--r--openvpn/src/openvpn/ssl.c3
-rw-r--r--openvpn/src/openvpn/ssl_openssl.c27
-rw-r--r--openvpn/src/openvpn/tun.c64
16 files changed, 390 insertions, 286 deletions
diff --git a/openvpn/.gitignore b/openvpn/.gitignore
index a04afff7..3a2f3842 100644
--- a/openvpn/.gitignore
+++ b/openvpn/.gitignore
@@ -54,3 +54,4 @@ tests/t_client.sh
tests/t_client-*-20??????-??????/
src/openvpn/openvpn
config-version.h
+nbproject
diff --git a/openvpn/configure.ac b/openvpn/configure.ac
index 65c639c5..b181f6d6 100644
--- a/openvpn/configure.ac
+++ b/openvpn/configure.ac
@@ -754,7 +754,9 @@ PKG_CHECK_MODULES(
[
have_openssl_ssl="yes"
OPENSSL_SSL_LIBS="-lssl"
- ]
+ ],
+ [],
+ [-lcrypto]
)]
)
@@ -812,13 +814,13 @@ if test "${with_crypto_library}" = "polarssl" ; then
#include <polarssl/version.h>
]],
[[
-#if POLARSSL_VERSION_NUMBER < 0x01020500
+#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000
#error invalid version
#endif
]]
)],
[AC_MSG_RESULT([ok])],
- [AC_MSG_ERROR([PolarSSL 1.2.5 or newer required])]
+ [AC_MSG_ERROR([PolarSSL 1.2.x required and must be 1.2.10 or later])]
)
polarssl_with_pkcs11="no"
diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8
index 55152c1c..fba477ba 100644
--- a/openvpn/doc/openvpn.8
+++ b/openvpn/doc/openvpn.8
@@ -221,6 +221,9 @@ options.
indicates the protocol to use when connecting with the
remote, and may be "tcp" or "udp".
+For forcing IPv4 or IPv6 connection suffix tcp or udp
+with 4/6 like udp4/udp6/tcp4/tcp6.
+
The client will move on to the next host in the list,
in the event of connection failure.
Note that at any given time, the OpenVPN client
@@ -553,19 +556,22 @@ Set HTTP "User-Agent" string to
.B user-agent.
.B CUSTOM\-HEADER name content \-\-
-Adds the custom Header with
+Adds the custom Header with
.B name
-as name and
+as name and
.B content
as the content of the custom HTTP header.
.\"*********************************************************
.TP
-.B \-\-socks-proxy server [port]
+.B \-\-socks-proxy server [port] [authfile]
Connect to remote host through a Socks5 proxy at address
.B server
and port
.B port
(default=1080).
+.B authfile
+(optional) is a file containing a username and password on 2 lines, or
+"stdin" to prompt from console.
.\"*********************************************************
.TP
.B \-\-socks-proxy-retry
@@ -678,7 +684,7 @@ TCP/UDP port number or name for bind.
TCP/UDP port number or name for remote.
.\"*********************************************************
.TP
-.B \-\-bind
+.B \-\-bind [ipv6only]
Bind to local address and port. This is the default unless any of
.B \-\-proto tcp-client
,
@@ -686,6 +692,12 @@ Bind to local address and port. This is the default unless any of
or
.B \-\-socks-proxy
are used.
+
+If the
+.B \-\-ipv6only
+keyword is present OpenVPN will bind only to IPv6 (as oposed
+to IPv6 and IPv4) when a IPv6 socket is opened.
+
.\"*********************************************************
.TP
.B \-\-nobind
diff --git a/openvpn/src/openvpn/forward-inline.h b/openvpn/src/openvpn/forward-inline.h
index 7eb480dd..5853ce29 100644
--- a/openvpn/src/openvpn/forward-inline.h
+++ b/openvpn/src/openvpn/forward-inline.h
@@ -228,7 +228,6 @@ context_reschedule_sec (struct context *c, int sec)
static inline struct link_socket_info *
get_link_socket_info (struct context *c)
{
-
if (c->c2.link_socket_info)
return c->c2.link_socket_info;
else
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index 8cd136d5..7c9bf048 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -284,6 +284,7 @@ static void
init_connection_list (struct context *c)
{
struct connection_list *l = c->options.connection_list;
+
l->current = -1;
if (c->options.remote_random)
{
@@ -1425,10 +1426,10 @@ do_open_tun (struct context *c)
#ifdef TARGET_ANDROID
/* If we emulate persist-tun on android we still have to open a new tun and
- then close the old */
+ * then close the old */
int oldtunfd=-1;
if (c->c1.tuntap)
- oldtunfd = c->c1.tuntap->fd;
+ oldtunfd = c->c1.tuntap->fd;
#endif
/* initialize (but do not open) tun/tap object */
@@ -1462,14 +1463,14 @@ do_open_tun (struct context *c)
do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
c->c1.tuntap, c->plugins, c->c2.es);
}
-
+#ifdef TARGET_ANDROID
+ /* Store the old fd inside the fd so open_tun can use it */
+ c->c1.tuntap->fd = oldtunfd;
+#endif
/* open the tun device */
open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
c->c1.tuntap);
-#ifdef TARGET_ANDROID
- if (oldtunfd>=0)
- close(oldtunfd);
-#endif
+
/* set the hardware address */
if (c->options.lladdr)
set_lladdr(c->c1.tuntap->actual_name, c->options.lladdr, c->c2.es);
@@ -1580,7 +1581,7 @@ do_close_tun (struct context *c, bool force)
/* delete any routes we added */
if (c->c1.route_list || c->c1.route_ipv6_list )
- {
+ {
run_up_down (c->options.route_predown_script,
c->plugins,
OPENVPN_PLUGIN_ROUTE_PREDOWN,
@@ -2688,7 +2689,8 @@ do_init_socket_1 (struct context *c, const int mode)
c->options.ce.remote,
c->options.ce.remote_port,
c->options.ce.proto,
- c->options.ce.af,
+ c->options.ce.af,
+ c->options.ce.bind_ipv6_only,
mode,
c->c2.accept_from,
#ifdef ENABLE_HTTP_PROXY
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 23e76527..8217ead2 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -1570,7 +1570,7 @@ man_listen (struct management *man)
{
man->connection.sd_top = create_socket_tcp (AF_INET);
socket_bind (man->connection.sd_top, man->settings.local,
- AF_INET, "MANAGEMENT");
+ AF_INET, "MANAGEMENT", true);
}
/*
@@ -1864,6 +1864,31 @@ bool management_android_control (struct management *man, const char *command, co
management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0);
return strcmp ("ok", up.password)==0;
}
+
+/*
+ * In Android 4.4 it is not possible to open a new tun device and then close the
+ * old tun device without breaking the whole VPNService stack until the device
+ * is reported. This management method ask the UI what method should be taken to
+ * ensure the optimal solution for the situation
+ */
+int managment_android_persisttun_action (struct management *man)
+{
+ struct user_pass up;
+ CLEAR(up);
+ strcpy(up.username,"tunmethod");
+ management_query_user_pass(management, &up , "PERSIST_TUN_ACTION",
+ GET_USER_PASS_NEED_OK,(void*) 0);
+ if (!strcmp("NOACTION", up.password))
+ return ANDROID_KEEP_OLD_TUN;
+ else if (!strcmp ("OPEN_AFTER_CLOSE", up.password))
+ return ANDROID_OPEN_AFTER_CLOSE;
+ else if (!strcmp ("OPEN_BEFORE_CLOSE", up.password))
+ return ANDROID_OPEN_BEFORE_CLOSE;
+ else
+ ASSERT (0);
+}
+
+
#endif
static int
diff --git a/openvpn/src/openvpn/manage.h b/openvpn/src/openvpn/manage.h
index dc3ade10..f5a621b7 100644
--- a/openvpn/src/openvpn/manage.h
+++ b/openvpn/src/openvpn/manage.h
@@ -378,6 +378,11 @@ bool management_query_user_pass (struct management *man,
#ifdef TARGET_ANDROID
bool management_android_control (struct management *man, const char *command, const char *msg);
+
+#define ANDROID_KEEP_OLD_TUN 1
+#define ANDROID_OPEN_AFTER_CLOSE 2
+#define ANDROID_OPEN_BEFORE_CLOSE 3
+int managment_android_persisttun_action (struct management *man);
#endif
bool management_should_daemonize (struct management *man);
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 66fb8962..89a5888d 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -780,6 +780,7 @@ init_options (struct options *o, const bool init_gc)
o->topology = TOP_NET30;
o->ce.proto = PROTO_UDP;
o->ce.af = AF_UNSPEC;
+ o->ce.bind_local=false;
o->ce.connect_retry_seconds = 5;
o->ce.connect_timeout = 10;
o->connect_retry_max = 0;
@@ -2037,8 +2038,12 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (ce->socks_proxy_server)
msg (M_USAGE, "--socks-proxy cannot be used with --mode server");
#endif
- if (options->connection_list)
- msg (M_USAGE, "<connection> cannot be used with --mode server");
+ /* <connection> blocks force to have a remote embedded, so we check for the
+ * --remote and bail out if it is present */
+ if (options->connection_list->len >1 ||
+ options->connection_list->array[0]->remote)
+ msg (M_USAGE, "<connection> cannot be used with --mode server");
+
#if 0
if (options->tun_ipv6)
msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server");
@@ -4446,14 +4451,14 @@ add_option (struct options *options,
if (p[3])
{
const int proto = ascii2proto (p[3]);
- const sa_family_t af = ascii2af (p[3]);
+ const sa_family_t af = ascii2af (p[3]);
if (proto < 0)
{
msg (msglevel, "remote: bad protocol associated with host %s: '%s'", p[1], p[3]);
goto err;
}
re.proto = proto;
- re.af = af;
+ re.af = af;
}
}
if (permission_mask & OPT_P_GENERAL)
@@ -4875,6 +4880,9 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
options->ce.bind_defined = true;
+ if (p[1] && streq (p[1], "ipv6only"))
+ options->ce.bind_ipv6_only=true;
+
}
else if (streq (p[0], "nobind"))
{
@@ -5000,10 +5008,10 @@ add_option (struct options *options,
else if ((streq (p[1], "EXT1") || streq(p[1], "EXT2") || streq(p[1], "CUSTOM-HEADER"))
&& p[2])
{
- /* In the wild patched versions use both EXT1/2 and CUSTOM-HEADER with either two
- * argument or one */
+ /* In the wild patched versions use both EXT1/2 and CUSTOM-HEADER
+ * with either two argument or one */
- struct http_custom_header *custom_header =NULL;
+ struct http_custom_header *custom_header = NULL;
int i;
/* Find the first free header */
for (i=0; i < MAX_CUSTOM_HTTP_HEADER; i++) {
@@ -5014,11 +5022,11 @@ add_option (struct options *options,
}
if (!custom_header)
{
- msg (msglevel, "Cannot use more than %d http-proxy-option CUSTOM-HEAER : '%s'", MAX_CUSTOM_HTTP_HEADER, p[1]);
+ msg (msglevel, "Cannot use more than %d http-proxy-option CUSTOM-HEADER : '%s'", MAX_CUSTOM_HTTP_HEADER, p[1]);
}
else
{
- /* We will save p[2] and p[3], the proxy code will detect if
+ /* We will save p[2] and p[3], the proxy code will detect if
* p[3] is NULL */
custom_header->name = p[2];
custom_header->content = p[3];
diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h
index 99877da7..4e97a192 100644
--- a/openvpn/src/openvpn/options.h
+++ b/openvpn/src/openvpn/options.h
@@ -95,6 +95,7 @@ struct connection_entry
const char *remote;
bool remote_float;
bool bind_defined;
+ bool bind_ipv6_only;
bool bind_local;
int connect_retry_seconds;
int connect_timeout;
diff --git a/openvpn/src/openvpn/proxy.c b/openvpn/src/openvpn/proxy.c
index db26994c..f7f06487 100644
--- a/openvpn/src/openvpn/proxy.c
+++ b/openvpn/src/openvpn/proxy.c
@@ -489,37 +489,50 @@ http_proxy_close (struct http_proxy_info *hp)
}
bool
-add_proxy_header (struct http_proxy_info *p,
+add_proxy_headers (struct http_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */
const char *host, /* openvpn server remote */
- const char *port /* openvpn server port */
+ const char* port /* openvpn server port */
)
{
char buf[512];
int i;
- bool hostheadercustom=false;
-
- /* Check if any of the custom headers already provides Host: */
- i=0;
+ bool host_header_sent=false;
+
+ /*
+ * Send custom headers if provided
+ * If content is NULL the whole header is in name
+ * Also remember if we already sent a Host: header
+ */
for (i=0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name;i++)
{
- if(
- ((!strcasecmp(p->options.custom_headers[i].name, "Host")) &&
- (p->options.custom_headers[i].content))
- ||
- ((!strncasecmp(p->options.custom_headers[i].name, "Host:", 5)) &&
- p->options.custom_headers[i].content == NULL)
- )
- hostheadercustom=true;
- i++;
+ if (p->options.custom_headers[i].content)
+ {
+ openvpn_snprintf (buf, sizeof(buf), "%s: %s",
+ p->options.custom_headers[i].name,
+ p->options.custom_headers[i].content);
+ if (!strcasecmp(p->options.custom_headers[i].name, "Host"))
+ host_header_sent=true;
+ }
+ else
+ {
+ openvpn_snprintf (buf, sizeof(buf), "%s",
+ p->options.custom_headers[i].name);
+ if (!strncasecmp(p->options.custom_headers[i].name, "Host:", 5))
+ host_header_sent=true;
+ }
+
+ msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf (sd, buf))
+ return false;
}
- if (!hostheadercustom)
+ if (!host_header_sent)
{
- openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf(sd, buf))
- return false;
+ openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
+ msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ return false;
}
/* send User-Agent string if provided */
@@ -532,26 +545,6 @@ add_proxy_header (struct http_proxy_info *p,
return false;
}
- /*
- * Send custom headers if provided
- * If content is NULL whole header is in name
- */
- for (i=0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name;i++)
- {
- if (p->options.custom_headers[i].content)
- openvpn_snprintf (buf, sizeof(buf), "%s: %s",
- p->options.custom_headers[i].name,
- p->options.custom_headers[i].content);
- else
- openvpn_snprintf (buf, sizeof(buf), "%s",
- p->options.custom_headers[i].name);
-
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- return false;
- i++;
- }
-
return true;
}
@@ -598,9 +591,9 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
/* send HTTP CONNECT message to proxy */
if (!send_line_crlf (sd, buf))
goto error;
-
- if(!add_proxy_header (p, sd, host, port))
- goto error;
+
+ if (!add_proxy_headers (p, sd, host, port))
+ goto error;
/* auth specified? */
switch (p->auth_method)
@@ -715,9 +708,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
if (!send_line_crlf (sd, buf))
goto error;
-
/* send HOST etc, */
- if(!add_proxy_header (p, sd, host, port))
+ if (!add_proxy_headers (p, sd, host, port))
goto error;
msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3");
@@ -826,8 +818,8 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
goto error;
/* send HOST etc, */
- if(!add_proxy_header (p, sd, host, port))
- goto error;
+ if (!add_proxy_headers (p, sd, host, port))
+ goto error;
/* send digest response */
openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
diff --git a/openvpn/src/openvpn/ps.c b/openvpn/src/openvpn/ps.c
index c1868642..a57ac547 100644
--- a/openvpn/src/openvpn/ps.c
+++ b/openvpn/src/openvpn/ps.c
@@ -408,20 +408,18 @@ proxy_entry_new (struct proxy_connection **list,
struct buffer *initial_data,
const char *journal_dir)
{
- struct openvpn_sockaddr osaddr;
socket_descriptor_t sd_server;
int status;
struct proxy_connection *pc;
struct proxy_connection *cp;
/* connect to port share server */
- osaddr.addr.in4 = server_addr;
if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
msg (M_WARN|M_ERRNO, "PORT SHARE PROXY: cannot create socket");
return false;
}
- status = openvpn_connect (sd_server, &osaddr, 5, NULL);
+ status = openvpn_connect (sd_server,(const struct sockaddr*) &server_addr, 5, NULL);
if (status)
{
msg (M_WARN, "PORT SHARE PROXY: connect to port-share server failed");
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 0898babe..c5f085f8 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -663,10 +663,9 @@ create_socket (struct link_socket *sock)
{
/* create socket, use information carried over from getaddrinfo */
const int ai_proto = sock->info.lsa->actual.ai_protocol;
- const int ai_family = sock->info.lsa->actual.ai_family;
-
- ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family);
+ int ai_family = sock->info.lsa->actual.ai_family;
+ ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family);
if (ai_proto == IPPROTO_UDP)
{
@@ -889,7 +888,8 @@ void
socket_bind (socket_descriptor_t sd,
struct addrinfo *local,
int ai_family,
- const char *prefix)
+ const char *prefix,
+ bool ipv6only)
{
struct gc_arena gc = gc_new ();
@@ -900,8 +900,11 @@ socket_bind (socket_descriptor_t sd,
* What is the correct way to deal with it?
*/
- ASSERT(local);
struct addrinfo* cur;
+ int v6only= ipv6only ? 0: 1;
+
+ ASSERT(local);
+
/* find the first addrinfo with correct ai_family */
for (cur = local; cur; cur=cur->ai_next)
@@ -912,7 +915,14 @@ socket_bind (socket_descriptor_t sd,
if (!cur)
msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
prefix, addr_family_name(ai_family));
-
+
+ if (ai_family == AF_INET6)
+ {
+ if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
+ {
+ msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY failed");
+ }
+ }
if (bind (sd, cur->ai_addr, cur->ai_addrlen))
{
const int errnum = openvpn_errno ();
@@ -1138,19 +1148,20 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af)
if (!sock->info.lsa->bind_local)
{
int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL |
- GETADDR_FATAL | GETADDR_PASSIVE;
+ GETADDR_FATAL | GETADDR_PASSIVE;
int status;
-
+
if(proto_is_dgram(sock->info.proto))
- flags |= GETADDR_DATAGRAM;
-
+ flags |= GETADDR_DATAGRAM;
+
/* will return AF_{INET|INET6}from local_host */
status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0,
- NULL, af, &sock->info.lsa->bind_local);
+ NULL, af, &sock->info.lsa->bind_local);
+
if(status !=0) {
- msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s",
- sock->local_host, sock->local_port,
- gai_strerror(status));
+ msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s",
+ sock->local_host, sock->local_port,
+ gai_strerror(status));
}
}
@@ -1165,11 +1176,12 @@ static void bind_local (struct link_socket *sock)
#ifdef ENABLE_SOCKS
if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family, "SOCKS");
+ sock->info.lsa->actual.ai_family, "SOCKS", false);
else
#endif
socket_bind (sock->sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family, "TCP/UDP");
+ sock->info.lsa->actual.ai_family,
+ "TCP/UDP", sock->info.bind_ipv6_only);
}
}
@@ -1306,11 +1318,12 @@ create_new_socket (struct link_socket* sock)
resolve_bind_local (sock, sock->info.af);
}
resolve_remote (sock, 1, NULL, NULL);
+
/*
* In P2P or server mode we must create the socket even when resolving
* the remote site fails/is not specified. */
- if (sock->info.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local)
+ if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)
{
/* Copy sock parameters from bind addr */
set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local);
@@ -1321,7 +1334,7 @@ create_new_socket (struct link_socket* sock)
/*
* Create the socket early if socket should be bound
*/
- if (sock->bind_local && sock->info.lsa->actual.ai_family)
+ if (sock->bind_local)
{
create_socket (sock);
@@ -1339,7 +1352,8 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *remote_host,
const char *remote_port,
int proto,
- sa_family_t af,
+ sa_family_t af,
+ bool bind_ipv6_only,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -1400,6 +1414,7 @@ link_socket_init_phase1 (struct link_socket *sock,
sock->info.af = af;
sock->info.remote_float = remote_float;
sock->info.lsa = lsa;
+ sock->info.bind_ipv6_only = bind_ipv6_only;
sock->info.ipchange_command = ipchange_command;
sock->info.plugins = plugins;
@@ -1452,7 +1467,7 @@ link_socket_init_phase1 (struct link_socket *sock,
}
/* bind behavior for TCP server vs. client */
- if (sock->info.proto == PROTO_TCP_SERVER && sock->info.af==AF_INET)
+ if (sock->info.proto == PROTO_TCP_SERVER)
{
if (sock->mode == LS_MODE_TCP_ACCEPT_FROM)
sock->bind_local = false;
@@ -1475,7 +1490,7 @@ link_socket_init_phase1 (struct link_socket *sock,
static
void phase2_inetd (struct link_socket* sock, const struct frame *frame,
- const char *remote_dynamic, volatile int *signal_received)
+ const char *remote_dynamic, volatile int *signal_received)
{
bool remote_changed = false;
@@ -1488,27 +1503,28 @@ void phase2_inetd (struct link_socket* sock, const struct frame *frame,
struct openvpn_sockaddr local_addr;
socklen_t addrlen = sizeof(local_addr);
if (getsockname (sock->sd, &local_addr.addr.sa, &addrlen) == 0) {
- sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family;
- dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)",
- proto2ascii(sock->info.proto, sock->info.af, false), local_addr.addr.sa.sa_family,
- sock->sd);
+ sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family;
+ dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)",
+ proto2ascii(sock->info.proto, sock->info.af, false),
+ local_addr.addr.sa.sa_family, sock->sd);
} else
- msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET",
- proto2ascii(sock->info.proto, sock->info.af, false), sock->sd);
+ msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET",
+ proto2ascii(sock->info.proto, sock->info.af, false), sock->sd);
}
#else
msg (M_WARN, "inetd(%s): this OS does not provide the getsockname() "
- "function, using AF_INET",
- proto2ascii(sock->info.proto, false));
+ "function, using AF_INET",
+ proto2ascii(sock->info.proto, false));
#endif
sock->sd =
socket_listen_accept (sock->sd,
- &sock->info.lsa->actual,
- remote_dynamic,
- sock->info.lsa->bind_local,
- false,
- sock->inetd == INETD_NOWAIT,
- signal_received);
+ &sock->info.lsa->actual,
+ remote_dynamic,
+ sock->info.lsa->bind_local,
+ false,
+ sock->inetd == INETD_NOWAIT,
+ signal_received);
+
}
ASSERT (!remote_changed);
}
@@ -1549,68 +1565,68 @@ linksock_print_addr (struct link_socket *sock)
/* print local address */
{
const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO;
-
+
if (sock->inetd)
msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true));
else if (sock->bind_local)
{
- /* Socket is always bound on the first matching address */
- struct addrinfo *cur;
- for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next)
- {
- if(cur->ai_family == sock->info.lsa->actual.ai_family)
- break;
- }
- ASSERT (cur);
- msg (msglevel, "%s link local (bound): %s",
- proto2ascii (sock->info.proto, sock->info.af, true),
- print_sockaddr(cur->ai_addr,&gc));
+ /* Socket is always bound on the first matching address */
+ struct addrinfo *cur;
+ for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next)
+ {
+ if(cur->ai_family == sock->info.lsa->actual.ai_family)
+ break;
+ }
+ ASSERT (cur);
+ msg (msglevel, "%s link local (bound): %s",
+ proto2ascii (sock->info.proto, sock->info.af, true),
+ print_sockaddr(cur->ai_addr,&gc));
}
else
- msg (msglevel, "%s link local: (not bound)",
- proto2ascii (sock->info.proto, sock->info.af, true));
-
+ msg (msglevel, "%s link local: (not bound)",
+ proto2ascii (sock->info.proto, sock->info.af, true));
+
/* print active remote address */
msg (msglevel, "%s link remote: %s",
- proto2ascii (sock->info.proto, sock->info.af, true),
- print_link_socket_actual_ex (&sock->info.lsa->actual,
- ":",
- PS_SHOW_PORT_IF_DEFINED,
- &gc));
+ proto2ascii (sock->info.proto, sock->info.af, true),
+ print_link_socket_actual_ex (&sock->info.lsa->actual,
+ ":",
+ PS_SHOW_PORT_IF_DEFINED,
+ &gc));
}
gc_free(&gc);
}
static void
phase2_tcp_server (struct link_socket *sock, const char *remote_dynamic,
- volatile int *signal_received)
+ volatile int *signal_received)
{
switch (sock->mode)
{
case LS_MODE_DEFAULT:
sock->sd = socket_listen_accept (sock->sd,
- &sock->info.lsa->actual,
- remote_dynamic,
- sock->info.lsa->bind_local,
- true,
- false,
- signal_received);
+ &sock->info.lsa->actual,
+ remote_dynamic,
+ sock->info.lsa->bind_local,
+ true,
+ false,
+ signal_received);
break;
case LS_MODE_TCP_LISTEN:
socket_do_listen (sock->sd,
- sock->info.lsa->bind_local->ai_addr,
- true,
- false);
+ sock->info.lsa->bind_local->ai_addr,
+ true,
+ false);
break;
case LS_MODE_TCP_ACCEPT_FROM:
sock->sd = socket_do_accept (sock->sd,
- &sock->info.lsa->actual,
- false);
+ &sock->info.lsa->actual,
+ false);
if (!socket_defined (sock->sd))
- {
- *signal_received = SIGTERM;
- return;
- }
+ {
+ *signal_received = SIGTERM;
+ return;
+ }
tcp_connection_established (&sock->info.lsa->actual);
break;
default:
@@ -1624,50 +1640,51 @@ static void
phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)
{
#ifdef GENERAL_PROXY_SUPPORT
- bool proxy_retry = false;
+ bool proxy_retry = false;
#else
- const bool proxy_retry = false;
-#endif
- do {
- socket_connect (&sock->sd,
- sock->info.lsa,
- sock->connect_timeout,
- sig_info);
-
- if (sig_info->signal_received)
- return;
-
- if (false)
- ;
+ const bool proxy_retry = false;
+#endif
+ do {
+ socket_connect (&sock->sd,
+ sock->info.lsa,
+ sock->connect_timeout,
+ sig_info);
+
+ if (sig_info->signal_received)
+ return;
+
+ if (false)
+ ;
#ifdef ENABLE_HTTP_PROXY
- else if (sock->http_proxy)
- {
- proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
- sock->sd,
- sock->proxy_dest_host,
- sock->proxy_dest_port,
- &sock->stream_buf.residual,
- &sig_info->signal_received);
- }
+ else if (sock->http_proxy)
+ {
+ proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
+ sock->sd,
+ sock->proxy_dest_host,
+ sock->proxy_dest_port,
+ &sock->stream_buf.residual,
+ &sig_info->signal_received);
+ }
#endif
#ifdef ENABLE_SOCKS
- else if (sock->socks_proxy)
- {
- establish_socks_proxy_passthru (sock->socks_proxy,
- sock->sd,
- sock->proxy_dest_host,
- sock->proxy_dest_port,
- &sig_info->signal_received);
- }
+ else if (sock->socks_proxy)
+ {
+ establish_socks_proxy_passthru (sock->socks_proxy,
+ sock->sd,
+ sock->proxy_dest_host,
+ sock->proxy_dest_port,
+ &sig_info->signal_received);
+ }
#endif
- if (proxy_retry)
- {
- /* TODO (schwabe): This code assumes AF_INET for the proxy socket
- * when retrying a connection */
- openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp (AF_INET);
- }
- } while (proxy_retry);
+ if (proxy_retry)
+ {
+ /* TODO (schwabe): This code assumes AF_INET for the proxy socket
+ * when retrying a connection */
+ openvpn_close_socket (sock->sd);
+ sock->sd = create_socket_tcp (AF_INET);
+ }
+
+ } while (proxy_retry);
}
@@ -1676,44 +1693,43 @@ static void
phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info)
{
socket_connect (&sock->ctrl_sd,
- sock->info.lsa,
- sock->connect_timeout,
- sig_info);
-
+ sock->info.lsa,
+ sock->connect_timeout,
+ sig_info);
+
if (sig_info->signal_received)
- return;
-
+ return;
+
establish_socks_proxy_udpassoc (sock->socks_proxy,
- sock->ctrl_sd,
- sock->sd,
- &sock->socks_relay.dest,
- &sig_info->signal_received);
-
+ sock->ctrl_sd,
+ sock->sd,
+ &sock->socks_relay.dest,
+ &sig_info->signal_received);
+
if (sig_info->signal_received)
- return;
-
+ return;
+
sock->remote_host = sock->proxy_dest_host;
sock->remote_port = sock->proxy_dest_port;
sock->did_resolve_remote = false;
-
+
addr_zero_host(&sock->info.lsa->actual.dest);
if (sock->info.lsa->remote_list)
{
- freeaddrinfo(sock->info.lsa->remote_list);
+ freeaddrinfo(sock->info.lsa->remote_list);
sock->info.lsa->current_remote = NULL;
sock->info.lsa->remote_list = NULL;
}
-
+
resolve_remote (sock, 1, NULL, &sig_info->signal_received);
-
}
#endif
/* finalize socket initialization */
void
link_socket_init_phase2 (struct link_socket *sock,
- const struct frame *frame,
- struct signal_info *sig_info)
+ const struct frame *frame,
+ struct signal_info *sig_info)
{
const char *remote_dynamic = NULL;
int sig_save = 0;
@@ -1742,71 +1758,66 @@ link_socket_init_phase2 (struct link_socket *sock,
{
phase2_inetd (sock, frame, remote_dynamic, &sig_info->signal_received);
if (sig_info && sig_info->signal_received)
- goto done;
+ goto done;
}
else
{
/* Second chance to resolv/create socket */
resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received);
-
+
/* If socket has not already been created create it now */
if (sock->sd == SOCKET_UNDEFINED)
- {
- if (sock->info.lsa->actual.ai_family)
- {
- create_socket (sock);
- }
- else
- {
- msg (M_WARN, "Could not determine IPv4/IPv6 protocol");
- sig_info->signal_received = SIGUSR1;
- goto done;
- }
-
- if (sock->bind_local)
- bind_local(sock);
- }
+ {
+ if (sock->info.lsa->actual.ai_family)
+ {
+ create_socket (sock);
+ }
+ else
+ {
+ msg (M_WARN, "Could not determine IPv4/IPv6 protocol");
+ sig_info->signal_received = SIGUSR1;
+ goto done;
+ }
+
+ if (sock->bind_local)
+ bind_local(sock);
+ }
-
if (sig_info && sig_info->signal_received)
- goto done;
+ goto done;
if (sock->info.proto == PROTO_TCP_SERVER)
- {
- phase2_tcp_server (sock, remote_dynamic,
- &sig_info->signal_received);
- }
+ {
+ phase2_tcp_server (sock, remote_dynamic,
+ &sig_info->signal_received);
+ }
else if (sock->info.proto == PROTO_TCP_CLIENT)
- {
- phase2_tcp_client (sock, sig_info);
-
- }
- else if (sock->info.proto == PROTO_UDP)
- {
+ {
+ phase2_tcp_client (sock, sig_info);
+
+ }
#ifdef ENABLE_SOCKS
- if (sock->info.proto == PROTO_UDP && sock->socks_proxy)
- {
- phase2_socks_client (sock, sig_info);
+ else if (sock->info.proto == PROTO_UDP && sock->socks_proxy)
+ {
+ phase2_socks_client (sock, sig_info);
#endif
- }
+ }
#ifdef TARGET_ANDROID
- protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa);
+ protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa);
#endif
- }
-
if (sig_info && sig_info->signal_received)
- goto done;
+ goto done;
}
phase2_set_socket_flags(sock);
linksock_print_addr(sock);
-
+
done:
if (sig_save && sig_info)
{
if (!sig_info->signal_received)
- sig_info->signal_received = sig_save;
+ sig_info->signal_received = sig_save;
}
}
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index d077a153..4c18b740 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -118,6 +118,7 @@ struct link_socket_info
bool remote_float;
int proto; /* Protocol (PROTO_x defined below) */
sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/
+ bool bind_ipv6_only;
int mtu_changed; /* Set to true when mtu value is changed */
};
@@ -289,7 +290,8 @@ struct link_socket *link_socket_new (void);
void socket_bind (socket_descriptor_t sd,
struct addrinfo *local,
int af_family,
- const char *prefix);
+ const char *prefix,
+ bool ipv6only);
int openvpn_connect (socket_descriptor_t sd,
const struct sockaddr *remote,
@@ -308,6 +310,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *remote_port,
int proto,
sa_family_t af,
+ bool bind_ipv6_only,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -600,14 +603,14 @@ static inline bool
addr_local (const struct sockaddr *addr)
{
if (!addr)
- return false;
+ return false;
switch (addr->sa_family) {
- case AF_INET:
- return ((const struct sockaddr_in*)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK);
- case AF_INET6:
- return IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6*)addr)->sin6_addr);
- default:
- return false;
+ case AF_INET:
+ return ((const struct sockaddr_in*)addr)->sin_addr.s_addr == htonl(INADDR_LOOPBACK);
+ case AF_INET6:
+ return IN6_IS_ADDR_LOOPBACK(&((const struct sockaddr_in6*)addr)->sin6_addr);
+ default:
+ return false;
}
}
@@ -853,7 +856,7 @@ link_socket_verify_incoming_addr (struct buffer *buf,
case AF_INET:
if (!link_socket_actual_defined (from_addr))
return false;
- if (info->remote_float || !info->lsa->remote_list)
+ if (info->remote_float || (!info->lsa->remote_list))
return true;
if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto))
return true;
@@ -892,13 +895,14 @@ link_socket_set_outgoing_addr (const struct buffer *buf,
{
struct link_socket_addr *lsa = info->lsa;
if (
- /* new or changed address? */
- (!info->connection_established
- || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
- /* address undef or address == remote or --float */
- && (info->remote_float
- || !lsa->remote_list)
- || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)
+ (
+ /* new or changed address? */
+ (!info->connection_established
+ || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
+ /* address undef or address == remote or --float */
+ && (info->remote_float
+ || !lsa->remote_list))
+ || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)
)
{
link_socket_connection_initiated (buf, info, act, common_name, es);
diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c
index 60f5f67f..58ba2384 100644
--- a/openvpn/src/openvpn/ssl.c
+++ b/openvpn/src/openvpn/ssl.c
@@ -64,7 +64,6 @@
#include "ssl.h"
#include "ssl_verify.h"
#include "ssl_backend.h"
-#include "multi.h"
#include "memdbg.h"
@@ -1837,7 +1836,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc));
}
- /* push env vars that begin with UV_ and IV_OPENVPN_GUI_VERSION*/
+ /* push env vars that begin with UV_ and IV_OPENVPN_GUI_VERSION */
for (e=es->list; e != NULL; e=e->next)
{
if (e->string)
diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c
index f64177a8..e3926914 100644
--- a/openvpn/src/openvpn/ssl_openssl.c
+++ b/openvpn/src/openvpn/ssl_openssl.c
@@ -743,7 +743,7 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
X509_STORE *store = NULL;
X509_NAME *xn = NULL;
BIO *in = NULL;
- int i, added = 0;
+ int i, added = 0, prev = 0;
ASSERT(NULL != ctx);
@@ -770,6 +770,11 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
if (info->crl)
X509_STORE_add_crl (store, info->crl);
+ if (tls_server && !info->x509)
+ {
+ msg (M_SSLERR, "X509 name was missing in TLS mode");
+ }
+
if (info->x509)
{
X509_STORE_add_cert (store, info->x509);
@@ -799,6 +804,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
sk_X509_NAME_push (cert_names, xn);
}
}
+
+ if (tls_server) {
+ int cnum = sk_X509_NAME_num (cert_names);
+ if (cnum != (prev + 1)) {
+ msg (M_WARN, "Cannot load CA certificate file %s (entry %d did not validate)", np(ca_file), added);
+ }
+ prev = cnum;
+ }
+
}
sk_X509_INFO_pop_free (info_stack, X509_INFO_free);
}
@@ -806,8 +820,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
if (tls_server)
SSL_CTX_set_client_CA_list (ctx->ctx, cert_names);
- if (!added || (tls_server && sk_X509_NAME_num (cert_names) != added))
- msg (M_SSLERR, "Cannot load CA certificate file %s", np(ca_file));
+ if (!added)
+ msg (M_SSLERR, "Cannot load CA certificate file %s (no entries were read)", np(ca_file));
+
+ if (tls_server) {
+ int cnum = sk_X509_NAME_num (cert_names);
+ if (cnum != added)
+ msg (M_SSLERR, "Cannot load CA certificate file %s (only %d of %d entries were valid X509 names)", np(ca_file), cnum, added);
+ }
+
if (in)
BIO_free (in);
}
diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c
index bd62b392..c1dcc5e2 100644
--- a/openvpn/src/openvpn/tun.c
+++ b/openvpn/src/openvpn/tun.c
@@ -466,7 +466,7 @@ init_tun (const char *dev, /* --dev option */
*/
if (strict_warn)
{
- struct addrinfo *curele;
+ struct addrinfo *curele;
ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);
/*
@@ -483,14 +483,14 @@ init_tun (const char *dev, /* --dev option */
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);
- }
+ 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");
@@ -1501,19 +1501,38 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
struct gc_arena gc = gc_new ();
bool opentun;
+ 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));
+ print_in_addr_t(tt->options.dns[i], 0, &gc));
}
if(tt->options.domain)
management_android_control (management, "DNSDOMAIN", tt->options.domain);
- opentun = management_android_control (management, "OPENTUN", dev);
+ 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);
+ }
- /* 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_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);
@@ -3148,9 +3167,9 @@ get_panel_reg (struct gc_arena *gc)
char enum_name[256];
char connection_string[256];
HKEY connection_key;
- char name_data[256];
+ WCHAR name_data[256];
DWORD name_type;
- const char name_string[] = "Name";
+ const WCHAR name_string[] = L"Name";
len = sizeof (enum_name);
status = RegEnumKeyEx(
@@ -3184,12 +3203,12 @@ get_panel_reg (struct gc_arena *gc)
else
{
len = sizeof (name_data);
- status = RegQueryValueEx(
+ status = RegQueryValueExW(
connection_key,
name_string,
NULL,
&name_type,
- name_data,
+ (LPBYTE) name_data,
&len);
if (status != ERROR_SUCCESS || name_type != REG_SZ)
@@ -3197,10 +3216,15 @@ get_panel_reg (struct gc_arena *gc)
NETWORK_CONNECTIONS_KEY, connection_string, name_string);
else
{
+ int n;
+ LPSTR name;
struct panel_reg *reg;
ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc);
- reg->name = string_alloc (name_data, gc);
+ n = WideCharToMultiByte (CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL);
+ name = gc_malloc (n, false, gc);
+ WideCharToMultiByte (CP_UTF8, 0, name_data, -1, name, n, NULL, NULL);
+ reg->name = name;
reg->guid = string_alloc (enum_name, gc);
/* link into return list */
@@ -3410,7 +3434,7 @@ static void
at_least_one_tap_win (const struct tap_reg *tap_reg)
{
if (!tap_reg)
- msg (M_FATAL, "There are no TAP-Windows adapters on this system. You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Windows virtual ethernet adapter.");
+ msg (M_FATAL, "There are no TAP-Windows adapters on this system. You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> TAP-Windows -> Utilities -> Add a new TAP-Windows virtual ethernet adapter.");
}
/*