summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-09-10 16:21:36 +0200
committerArne Schwabe <arne@rfc2549.org>2012-09-10 16:21:36 +0200
commit191b7ecd2b1f6012ee9cba9e619de4805e7a058b (patch)
tree41f385bef935811c8fc818e28421bc2aff9dcf3e
parent5aa156924dbabdb7a55ccfd9556e63b337824635 (diff)
Update openvpn version. Matches github.com/schwabe/openvpn
-rw-r--r--openvpn/doc/openvpn.849
-rw-r--r--openvpn/include/openvpn-plugin.h61
-rw-r--r--openvpn/src/openvpn/error.c11
-rw-r--r--openvpn/src/openvpn/error.h2
-rw-r--r--openvpn/src/openvpn/init.c7
-rw-r--r--openvpn/src/openvpn/manage.c4
-rw-r--r--openvpn/src/openvpn/options.c25
-rw-r--r--openvpn/src/openvpn/plugin.c62
-rw-r--r--openvpn/src/openvpn/route.c45
-rw-r--r--openvpn/src/openvpn/socket.c548
-rw-r--r--openvpn/src/openvpn/socket.h19
-rw-r--r--openvpn/src/openvpn/ssl_common.h1
-rw-r--r--openvpn/src/openvpn/ssl_verify_openssl.h2
-rw-r--r--openvpn/src/openvpn/tun.c22
-rw-r--r--openvpn/src/openvpn/tun.h4
-rwxr-xr-xopenvpn/tests/t_client.sh.in3
16 files changed, 396 insertions, 469 deletions
diff --git a/openvpn/doc/openvpn.8 b/openvpn/doc/openvpn.8
index 56be29ec..f586744e 100644
--- a/openvpn/doc/openvpn.8
+++ b/openvpn/doc/openvpn.8
@@ -2431,11 +2431,14 @@ be set to 127.0.0.1
server to local clients.
.TP
.B \-\-management-client
-Management interface will connect as a TCP client to
+Management interface will connect as a TCP/unix domain client to
.B IP:port
specified by
.B \-\-management
-rather than listen as a TCP server.
+rather than listen as a TCP server or on a unix domain socket.
+
+If the client connection fails to connect or is disconnected,
+a SIGTERM signal will be generated causing OpenVPN to quit.
.\"*********************************************************
.TP
.B \-\-management-query-passwords
@@ -2478,7 +2481,8 @@ command.
.B \-\-management-signal
Send SIGUSR1 signal to OpenVPN if management session disconnects.
This is useful when you wish to disconnect an OpenVPN session on
-user logoff.
+user logoff. For --management-client this option is not needed since
+a disconnect will always generate a SIGTERM.
.\"*********************************************************
.TP
.B \-\-management-log-cache n
@@ -3621,6 +3625,14 @@ would see nothing
but random-looking data.
.\"*********************************************************
.TP
+.B \-\-key-direction
+Alternative way of specifying the optional direction parameter for the
+.B \-\-tls-auth
+and
+.B \-\-secret
+options. Useful when using inline files (See section on inline files).
+.\"*********************************************************
+.TP
.B \-\-auth alg
Authenticate packets with HMAC using message
digest algorithm
@@ -5901,6 +5913,37 @@ X509_1_C=KG
.ft
.fi
.\"*********************************************************
+.SH INLINE FILE SUPPORT
+OpenVPN allows including files in the main configuration for the
+.B \-\-ca, \-\-cert, \-\-dh, \-\-extra-certs, \-\-key, \-\-pkcs12, \-\-secret
+and
+.B \-\-tls-auth
+options.
+
+Each inline file started by the line
+.B <option>
+and ended by the line
+.B </option>
+
+Here is an example of an inline file usage
+
+.nf
+.ft 3
+.in +4
+<cert>
+-----BEGIN CERTIFICATE-----
+[...]
+-----END CERTIFICATE-----
+</cert>
+.in -4
+.ft
+.fi
+
+When using the inline file feature with
+.B \-\-pkcs12
+the inline file has to be base64 encoded. Encoding of a .p12 file into base64 can be done for example with OpenSSL by running
+.B openssl base64 -in input.p12
+
.SH SIGNALS
.TP
.B SIGHUP
diff --git a/openvpn/include/openvpn-plugin.h b/openvpn/include/openvpn-plugin.h
index 1c80eec3..0879f490 100644
--- a/openvpn/include/openvpn-plugin.h
+++ b/openvpn/include/openvpn-plugin.h
@@ -43,6 +43,8 @@ typedef X509 openvpn_x509_cert_t;
#endif
#endif
+#include <stdarg.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -145,7 +147,7 @@ typedef void *openvpn_plugin_handle_t;
/*
* For Windows (needs to be modified for MSVC)
*/
-#if defined(__MINGW32_VERSION) && !defined(OPENVPN_PLUGIN_H)
+#if defined(WIN32) && !defined(OPENVPN_PLUGIN_H)
# define OPENVPN_EXPORT __declspec(dllexport)
#else
# define OPENVPN_EXPORT
@@ -205,6 +207,59 @@ struct openvpn_plugin_string_list
#define OPENVPN_PLUGINv3_STRUCTVER 1
/**
+ * Definitions needed for the plug-in callback functions.
+ */
+typedef enum
+{
+ PLOG_ERR = (1 << 0), /* Error condition message */
+ PLOG_WARN = (1 << 1), /* General warning message */
+ PLOG_NOTE = (1 << 2), /* Informational message */
+ PLOG_DEBUG = (1 << 3), /* Debug message, displayed if verb >= 7 */
+
+ PLOG_ERRNO = (1 << 8), /* Add error description to message */
+ PLOG_NOMUTE = (1 << 9), /* Mute setting does not apply for message */
+
+} openvpn_plugin_log_flags_t;
+
+
+#ifdef __GNUC__
+#if __USE_MINGW_ANSI_STDIO
+# define _ovpn_chk_fmt(a, b) __attribute__ ((format(gnu_printf, (a), (b))))
+#else
+# define _ovpn_chk_fmt(a, b) __attribute__ ((format(__printf__, (a), (b))))
+#endif
+#else
+# define _ovpn_chk_fmt(a, b)
+#endif
+
+typedef void (*plugin_log_t) (openvpn_plugin_log_flags_t flags,
+ const char *plugin_name,
+ const char *format, ...) _ovpn_chk_fmt(3, 4);
+
+typedef void (*plugin_vlog_t) (openvpn_plugin_log_flags_t flags,
+ const char *plugin_name,
+ const char *format,
+ va_list arglist) _ovpn_chk_fmt(3, 0);
+
+#undef _ovpn_chk_fmt
+
+/**
+ * Used by the openvpn_plugin_open_v3() function to pass callback
+ * function pointers to the plug-in.
+ *
+ * plugin_log
+ * plugin_vlog : Use these functions to add information to the OpenVPN log file.
+ * Messages will only be displayed if the plugin_name parameter
+ * is set. PLOG_DEBUG messages will only be displayed with plug-in
+ * debug log verbosity (at the time of writing that's verb >= 7).
+ */
+struct openvpn_plugin_callbacks
+{
+ plugin_log_t plugin_log;
+ plugin_vlog_t plugin_vlog;
+};
+
+/**
* Arguments used to transport variables to the plug-in.
* The struct openvpn_plugin_args_open_in is only used
* by the openvpn_plugin_open_v3() function.
@@ -221,12 +276,16 @@ struct openvpn_plugin_string_list
* variables in "name=value" format. Note that for security reasons,
* these variables are not actually written to the "official"
* environmental variable store of the process.
+ *
+ * callbacks : a pointer to the plug-in callback function struct.
+ *
*/
struct openvpn_plugin_args_open_in
{
const int type_mask;
const char ** const argv;
const char ** const envp;
+ struct openvpn_plugin_callbacks *callbacks;
};
diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c
index 8396fe01..6848425e 100644
--- a/openvpn/src/openvpn/error.c
+++ b/openvpn/src/openvpn/error.c
@@ -201,8 +201,15 @@ int x_msg_line_num; /* GLOBAL */
void x_msg (const unsigned int flags, const char *format, ...)
{
- struct gc_arena gc;
va_list arglist;
+ va_start (arglist, format);
+ x_msg_va (flags, format, arglist);
+ va_end (arglist);
+}
+
+void x_msg_va (const unsigned int flags, const char *format, va_list arglist)
+{
+ struct gc_arena gc;
#if SYSLOG_CAPABILITY
int level;
#endif
@@ -237,9 +244,7 @@ void x_msg (const unsigned int flags, const char *format, ...)
m1 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc);
m2 = (char *) gc_malloc (ERR_BUF_SIZE, false, &gc);
- va_start (arglist, format);
vsnprintf (m1, ERR_BUF_SIZE, format, arglist);
- va_end (arglist);
m1[ERR_BUF_SIZE - 1] = 0; /* windows vsnprintf needs this */
if ((flags & M_ERRNO) && e)
diff --git a/openvpn/src/openvpn/error.h b/openvpn/src/openvpn/error.h
index aedb7c37..27c48b69 100644
--- a/openvpn/src/openvpn/error.h
+++ b/openvpn/src/openvpn/error.h
@@ -182,6 +182,8 @@ void x_msg (const unsigned int flags, const char *format, ...)
#endif
; /* should be called via msg above */
+void x_msg_va (const unsigned int flags, const char *format, va_list arglist);
+
/*
* Function prototypes
*/
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index b2013923..cd5ebd3d 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -2488,6 +2488,13 @@ do_option_warnings (struct context *c)
msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");
#endif
+ if (script_security >= SSEC_SCRIPTS)
+ msg (M_WARN, "NOTE: the current --script-security setting may allow this configuration to call user-defined scripts");
+ else if (script_security >= SSEC_PW_ENV)
+ msg (M_WARN, "WARNING: the current --script-security setting may allow passwords to be passed to scripts via environmental variables");
+ else
+ msg (M_WARN, "NOTE: " PACKAGE_NAME " 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables");
+
if (script_method == SM_SYSTEM)
msg (M_WARN, "NOTE: --script-security method='system' is deprecated due to the fact that passed parameters will be subject to shell expansion");
}
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 77d40833..45e0bd43 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -1567,7 +1567,7 @@ man_listen (struct management *man)
else
#endif
{
- man->connection.sd_top = create_socket_tcp ();
+ man->connection.sd_top = create_socket_tcp (AF_INET);
socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
}
@@ -1633,7 +1633,7 @@ man_connect (struct management *man)
else
#endif
{
- man->connection.sd_cli = create_socket_tcp ();
+ man->connection.sd_cli = create_socket_tcp (AF_INET);
status = openvpn_connect (man->connection.sd_cli,
&man->settings.local,
5,
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index a3029fc2..528583fe 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -62,6 +62,10 @@
#include "memdbg.h"
+#ifdef MANAGMENT_EXTERNAL_KEY
+#define EXTERNAL_KEY_STRING "EXTERNAL_PRIVATE_KEY"
+#endif
+
const char title_string[] =
PACKAGE_STRING
" " TARGET_ALIAS
@@ -106,8 +110,7 @@ const char title_string[] =
#if ENABLE_IP_PKTINFO
" [MH]"
#endif
- " [PF_INET6]"
- " [IPv6 payload 20110522-1 (2.2.0)]"
+ " [IPv6]"
" built on " __DATE__
;
@@ -2183,6 +2186,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
else
#endif
#ifdef ENABLE_CRYPTOAPI
+#ifdef MANAGMENT_EXTERNAL_KEY
+ if((options->management_flags & MF_EXTERNAL_KEY) && !strcmp(options->priv_key_file,EXTERNAL_KEY_STRING)==0)
+ msg (M_USAGE, "--key and --management-external-key are mutually exclusive");
+#endif
+
if (options->cryptoapi_cert)
{
if ((!(options->ca_file)) && (!(options->ca_path)))
@@ -2357,14 +2365,6 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
#endif
}
-#ifdef MANAGMENT_EXTERNAL_KEY
- if(o->management_flags & MF_EXTERNAL_KEY) {
- if(o->priv_key_file)
- msg (M_USAGE, "--key and --management-external-key are mutually exclusive");
- /* set a filename for nicer output in the logs */
- o->priv_key_file = "EXTERNAL_PRIVATE_KEY";
- }
-#endif
/*
* Set MTU defaults
*/
@@ -2640,7 +2640,7 @@ options_postprocess_filechecks (struct options *options)
#ifdef MANAGMENT_EXTERNAL_KEY
if(!options->management_flags & MF_EXTERNAL_KEY)
#endif
- errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK,
+ errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK,
"--key");
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->pkcs12_file, R_OK,
"--pkcs12");
@@ -4154,6 +4154,9 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL);
options->management_flags |= MF_EXTERNAL_KEY;
+ /* Set priv key file name only if not defined, so --key and this option can be checked later */
+ if(!options->priv_key_file)
+ options->priv_key_file = EXTERNAL_KEY_STRING;
}
#endif
#ifdef MANAGEMENT_DEF_AUTH
diff --git a/openvpn/src/openvpn/plugin.c b/openvpn/src/openvpn/plugin.c
index 7ce2f5e7..d785daec 100644
--- a/openvpn/src/openvpn/plugin.c
+++ b/openvpn/src/openvpn/plugin.c
@@ -287,6 +287,65 @@ plugin_init_item (struct plugin *p, const struct plugin_option *o)
}
static void
+plugin_vlog (openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist)
+{
+ unsigned int msg_flags;
+
+ if (!format)
+ return;
+
+ if (!name || name[0] == '\0')
+ {
+ msg (D_PLUGIN_DEBUG, "PLUGIN: suppressed log message from plugin with unknown name");
+ return;
+ }
+
+ if (flags & PLOG_ERR)
+ msg_flags = M_INFO | M_NONFATAL;
+ else if (flags & PLOG_WARN)
+ msg_flags = M_INFO | M_WARN;
+ else if (flags & PLOG_NOTE)
+ msg_flags = M_INFO;
+ else if (flags & PLOG_DEBUG)
+ msg_flags = D_PLUGIN_DEBUG;
+
+ if (flags & PLOG_ERRNO)
+ msg_flags |= M_ERRNO;
+ if (flags & PLOG_NOMUTE)
+ msg_flags |= M_NOMUTE;
+
+ if (MSG_TEST (msg_flags))
+ {
+ struct gc_arena gc;
+ char* msg_fmt;
+
+ /* Never add instance prefix; not thread safe */
+ msg_flags |= M_NOIPREFIX;
+
+ gc_init (&gc);
+ msg_fmt = gc_malloc (ERR_BUF_SIZE, false, &gc);
+ openvpn_snprintf (msg_fmt, ERR_BUF_SIZE, "PLUGIN %s: %s", name, format);
+ x_msg_va (msg_flags, msg_fmt, arglist);
+
+ gc_free (&gc);
+ }
+}
+
+static void
+plugin_log (openvpn_plugin_log_flags_t flags, const char *name, const char *format, ...)
+{
+ va_list arglist;
+ va_start (arglist, format);
+ plugin_vlog (flags, name, format, arglist);
+ va_end (arglist);
+}
+
+static struct openvpn_plugin_callbacks callbacks = {
+ plugin_log,
+ plugin_vlog
+};
+
+static void
plugin_open_item (struct plugin *p,
const struct plugin_option *o,
struct openvpn_plugin_string_list **retlist,
@@ -312,7 +371,8 @@ plugin_open_item (struct plugin *p,
if (p->open3) {
struct openvpn_plugin_args_open_in args = { p->plugin_type_mask,
(const char ** const) o->argv,
- (const char ** const) envp };
+ (const char ** const) envp,
+ &callbacks };
struct openvpn_plugin_args_open_return retargs;
CLEAR(retargs);
diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c
index e908be99..caa2459b 100644
--- a/openvpn/src/openvpn/route.c
+++ b/openvpn/src/openvpn/route.c
@@ -268,12 +268,14 @@ is_special_addr (const char *addr_str)
static bool
init_route (struct route *r,
- struct resolve_list *network_list,
+ struct addrinfo **network_list,
const struct route_option *ro,
const struct route_list *rl)
{
const in_addr_t default_netmask = IPV4_NETMASK_HOST;
bool status;
+ int ret;
+ struct in_addr special;
CLEAR (*r);
r->option = ro;
@@ -284,19 +286,22 @@ init_route (struct route *r,
{
goto fail;
}
-
- if (!get_special_addr (rl, ro->network, &r->network, &status))
+
+
+ /* get_special_addr replaces specialaddr with a special ip addr
+ like gw. getaddrinfo is called to convert a a addrinfo struct */
+
+ if(get_special_addr (rl, ro->network, &special.s_addr, &status))
{
- r->network = getaddr_multi (
- GETADDR_RESOLVE
- | GETADDR_HOST_ORDER
- | GETADDR_WARN_ON_SIGNAL,
- ro->network,
- 0,
- &status,
- NULL,
- network_list);
+ special.s_addr = htonl(special.s_addr);
+ ret = openvpn_getaddrinfo(0, inet_ntoa(special), 0, NULL,
+ AF_INET, network_list);
}
+ else
+ ret = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL,
+ ro->network, 0, NULL, AF_INET, network_list);
+
+ status = (ret == 0);
if (!status)
goto fail;
@@ -642,11 +647,8 @@ init_route_list (struct route_list *rl,
bool warned = false;
for (i = 0; i < opt->n; ++i)
{
- struct resolve_list netlist;
+ struct addrinfo* netlist;
struct route r;
- int k;
-
- CLEAR(netlist); /* init_route() will not always init this */
if (!init_route (&r,
&netlist,
@@ -655,16 +657,12 @@ init_route_list (struct route_list *rl,
ret = false;
else
{
- if (!netlist.len)
- {
- netlist.data[0] = r.network;
- netlist.len = 1;
- }
- for (k = 0; k < netlist.len; ++k)
+ struct addrinfo* curele;
+ for (curele = netlist; curele; curele = curele->ai_next)
{
if (j < rl->capacity)
{
- r.network = netlist.data[k];
+ r.network = ntohl(((struct sockaddr_in*)(curele)->ai_addr)->sin_addr.s_addr);
rl->routes[j++] = r;
}
else
@@ -676,6 +674,7 @@ init_route_list (struct route_list *rl,
}
}
}
+ freeaddrinfo(netlist);
}
}
rl->n = j;
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 339470b0..bb973bc9 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -94,220 +94,53 @@ h_errno_msg(int h_errno_err)
*/
in_addr_t
getaddr (unsigned int flags,
- const char *hostname,
- int resolve_retry_seconds,
- bool *succeeded,
- volatile int *signal_received)
+ const char *hostname,
+ int resolve_retry_seconds,
+ bool *succeeded,
+ volatile int *signal_received)
{
- return getaddr_multi (flags, hostname, resolve_retry_seconds, succeeded, signal_received, NULL);
-}
-
-in_addr_t
-getaddr_multi (unsigned int flags,
- const char *hostname,
- int resolve_retry_seconds,
- bool *succeeded,
- volatile int *signal_received,
- struct resolve_list *reslist)
-{
- struct in_addr ia;
+ struct addrinfo *ai;
int status;
- int sigrec = 0;
- int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
- struct gc_arena gc = gc_new ();
-
- if (reslist)
- reslist->len = 0;
-
- if (flags & GETADDR_RANDOMIZE)
- hostname = hostname_randomize(hostname, &gc);
-
- if (flags & GETADDR_MSG_VIRT_OUT)
- msglevel |= M_MSG_VIRT_OUT;
-
- CLEAR (ia);
- if (succeeded)
- *succeeded = false;
-
- if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL))
- && !signal_received)
- signal_received = &sigrec;
-
- status = openvpn_inet_aton (hostname, &ia); /* parse ascii IP address */
-
- if (status != OIA_IP) /* parse as IP address failed? */
- {
- const int fail_wait_interval = 5; /* seconds */
- int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : (resolve_retry_seconds / fail_wait_interval);
- struct hostent *h;
- const char *fmt;
- int level = 0;
-
- CLEAR (ia);
-
- fmt = "RESOLVE: Cannot resolve host address: %s: %s";
- if ((flags & GETADDR_MENTION_RESOLVE_RETRY)
- && !resolve_retry_seconds)
- fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)";
-
- if (!(flags & GETADDR_RESOLVE) || status == OIA_ERROR)
- {
- msg (msglevel, "RESOLVE: Cannot parse IP address: %s", hostname);
- goto done;
- }
-
-#ifdef ENABLE_MANAGEMENT
- if (flags & GETADDR_UPDATE_MANAGEMENT_STATE)
- {
- if (management)
- management_set_state (management,
- OPENVPN_STATE_RESOLVE,
- NULL,
- (in_addr_t)0,
- (in_addr_t)0);
- }
-#endif
-
- /*
- * Resolve hostname
- */
- while (true)
- {
- /* try hostname lookup */
-#if defined(HAVE_RES_INIT)
- res_init ();
-#endif
- h = gethostbyname (hostname);
-
- if (signal_received)
- {
- get_signal (signal_received);
- if (*signal_received) /* were we interrupted by a signal? */
- {
- h = NULL;
- if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */
- {
- msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt");
- *signal_received = 0;
- }
- else
- goto done;
- }
- }
-
- /* success? */
- if (h)
- break;
-
- /* resolve lookup failed, should we
- continue or fail? */
-
- level = msglevel;
- if (resolve_retries > 0)
- level = D_RESOLVE_ERRORS;
-
- msg (level,
- fmt,
- hostname,
- h_errno_msg (h_errno));
-
- if (--resolve_retries <= 0)
- goto done;
-
- openvpn_sleep (fail_wait_interval);
- }
-
- if (h->h_addrtype != AF_INET || h->h_length != 4)
- {
- msg (msglevel, "RESOLVE: Sorry, but we only accept IPv4 DNS names: %s", hostname);
- goto done;
- }
-
- ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
-
- if (ia.s_addr)
- {
- if (h->h_addr_list[1]) /* more than one address returned */
- {
- int n = 0;
-
- /* count address list */
- while (h->h_addr_list[n])
- ++n;
- ASSERT (n >= 2);
-
- msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses",
- hostname,
- n);
-
- /* choose address randomly, for basic load-balancing capability */
- /*ia.s_addr = *(in_addr_t *) (h->h_addr_list[get_random () % n]);*/
-
- /* choose first address */
- ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
-
- if (reslist)
- {
- int i;
- for (i = 0; i < n && i < SIZE(reslist->data); ++i)
- {
- in_addr_t a = *(in_addr_t *) (h->h_addr_list[i]);
- if (flags & GETADDR_HOST_ORDER)
- a = ntohl(a);
- reslist->data[i] = a;
- }
- reslist->len = i;
- }
- }
- }
-
- /* hostname resolve succeeded */
- if (succeeded)
- *succeeded = true;
- }
- else
- {
- /* IP address parse succeeded */
- if (succeeded)
- *succeeded = true;
- }
-
- done:
- if (signal_received && *signal_received)
- {
- int level = 0;
- if (flags & GETADDR_FATAL_ON_SIGNAL)
- level = M_FATAL;
- else if (flags & GETADDR_WARN_ON_SIGNAL)
- level = M_WARN;
- msg (level, "RESOLVE: signal received during DNS resolution attempt");
- }
-
- gc_free (&gc);
- return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr;
+ status = openvpn_getaddrinfo(flags, hostname, resolve_retry_seconds,
+ signal_received, AF_INET, &ai);
+ if(status==0) {
+ struct in_addr ia;
+ if(succeeded)
+ *succeeded=true;
+ ia = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
+ freeaddrinfo(ai);
+ return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr;
+ } else {
+ if(succeeded)
+ *succeeded =false;
+ return 0;
+ }
}
+
/*
- * Translate IPv6 addr or hostname into struct addrinfo
- * If resolve error, try again for
- * resolve_retry_seconds seconds.
+ * Translate IPv4/IPv6 addr or hostname into struct addrinfo
+ * If resolve error, try again for resolve_retry_seconds seconds.
*/
-bool
-getaddr6 (unsigned int flags,
- const char *hostname,
- int resolve_retry_seconds,
- volatile int *signal_received,
- int *gai_err,
- struct sockaddr_in6 *in6)
-{
- bool success;
- struct addrinfo hints, *ai;
+int
+openvpn_getaddrinfo (unsigned int flags,
+ const char *hostname,
+ int resolve_retry_seconds,
+ volatile int *signal_received,
+ int ai_family,
+ struct addrinfo **res)
+{
+ struct addrinfo hints;
int status;
int sigrec = 0;
int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
struct gc_arena gc = gc_new ();
- ASSERT(in6);
+ ASSERT(res);
+
+#if defined(HAVE_RES_INIT)
+ res_init ();
+#endif
if (!hostname)
hostname = "::";
@@ -318,151 +151,111 @@ getaddr6 (unsigned int flags,
if (flags & GETADDR_MSG_VIRT_OUT)
msglevel |= M_MSG_VIRT_OUT;
- CLEAR (ai);
- success = false;
-
if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL))
&& !signal_received)
signal_received = &sigrec;
/* try numeric ipv6 addr first */
CLEAR(hints);
- hints.ai_family = AF_INET6;
+ hints.ai_family = ai_family;
hints.ai_flags = AI_NUMERICHOST;
- if ((status = getaddrinfo(hostname, NULL, &hints, &ai))==0)
- {
- *in6 = *((struct sockaddr_in6 *)(ai->ai_addr));
- freeaddrinfo(ai);
- ai = NULL;
- }
- if (gai_err)
- *gai_err = status;
+ hints.ai_socktype = dnsflags_to_socktype(flags);
+ status = getaddrinfo(hostname, NULL, &hints, res);
- if (status != 0) /* parse as IPv6 address failed? */
+ if (status != 0) /* parse as numeric address failed? */
{
const int fail_wait_interval = 5; /* seconds */
int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : (resolve_retry_seconds / fail_wait_interval);
const char *fmt;
int level = 0;
- int err;
-
- ai = NULL;
fmt = "RESOLVE: Cannot resolve host address: %s: %s";
if ((flags & GETADDR_MENTION_RESOLVE_RETRY)
- && !resolve_retry_seconds)
- fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)";
+ && !resolve_retry_seconds)
+ fmt = "RESOLVE: Cannot resolve host address: %s: %s (I would have retried this name query if you had specified the --resolv-retry option.)";
if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL)
- {
- msg (msglevel, "RESOLVE: Cannot parse IPv6 address: %s", hostname);
- goto done;
- }
+ {
+ msg (msglevel, "RESOLVE: Cannot parse IP address: %s", hostname);
+ goto done;
+ }
#ifdef ENABLE_MANAGEMENT
if (flags & GETADDR_UPDATE_MANAGEMENT_STATE)
- {
- if (management)
- management_set_state (management,
- OPENVPN_STATE_RESOLVE,
- NULL,
- (in_addr_t)0,
- (in_addr_t)0);
- }
+ {
+ if (management)
+ management_set_state (management,
+ OPENVPN_STATE_RESOLVE,
+ NULL,
+ (in_addr_t)0,
+ (in_addr_t)0);
+ }
#endif
/*
* Resolve hostname
*/
while (true)
- {
- /* try hostname lookup */
+ {
+ /* try hostname lookup */
hints.ai_flags = 0;
- hints.ai_socktype = dnsflags_to_socktype(flags);
- dmsg (D_SOCKET_DEBUG, "GETADDR6 flags=0x%04x ai_family=%d ai_socktype=%d",
- flags, hints.ai_family, hints.ai_socktype);
- err = getaddrinfo(hostname, NULL, &hints, &ai);
+ dmsg (D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d",
+ flags, hints.ai_family, hints.ai_socktype);
+ status = getaddrinfo(hostname, NULL, &hints, res);
- if (gai_err)
- *gai_err = err;
-
- if (signal_received)
- {
- get_signal (signal_received);
- if (*signal_received) /* were we interrupted by a signal? */
- {
- if (0 == err) {
- ASSERT(ai);
- freeaddrinfo(ai);
- ai = NULL;
+ if (signal_received)
+ {
+ get_signal (signal_received);
+ if (*signal_received) /* were we interrupted by a signal? */
+ {
+ if (0 == status) {
+ ASSERT(res);
+ freeaddrinfo(*res);
+ res = NULL;
}
- if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */
- {
- msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt");
- *signal_received = 0;
- }
- else
- goto done;
- }
- }
-
- /* success? */
- if (0 == err)
- break;
-
- /* resolve lookup failed, should we
- continue or fail? */
-
- level = msglevel;
- if (resolve_retries > 0)
- level = D_RESOLVE_ERRORS;
-
- msg (level,
- fmt,
- hostname,
- gai_strerror(err));
-
- if (--resolve_retries <= 0)
- goto done;
-
- openvpn_sleep (fail_wait_interval);
- }
+ if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */
+ {
+ msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt");
+ *signal_received = 0;
+ }
+ else
+ goto done;
+ }
+ }
- ASSERT(ai);
+ /* success? */
+ if (0 == status)
+ break;
- if (!ai->ai_next)
- *in6 = *((struct sockaddr_in6*)(ai->ai_addr));
- else
- /* more than one address returned */
- {
- struct addrinfo *ai_cursor;
- int n = 0;
- /* count address list */
- for (ai_cursor = ai; ai_cursor; ai_cursor = ai_cursor->ai_next) n++;
- ASSERT (n >= 2);
+ /* resolve lookup failed, should we
+ continue or fail? */
+ level = msglevel;
+ if (resolve_retries > 0)
+ level = D_RESOLVE_ERRORS;
- msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d ipv6 addresses, choosing one by random",
+ msg (level,
+ fmt,
hostname,
- n);
+ gai_strerror(status));
+
+ if (--resolve_retries <= 0)
+ goto done;
- /* choose address randomly, for basic load-balancing capability */
- n--;
- n %= get_random();
- for (ai_cursor = ai; n; ai_cursor = ai_cursor->ai_next) n--;
- *in6 = *((struct sockaddr_in6*)(ai_cursor->ai_addr));
+ openvpn_sleep (fail_wait_interval);
}
- freeaddrinfo(ai);
- ai = NULL;
+ ASSERT(res);
/* hostname resolve succeeded */
- success = true;
+
+ /* Do not chose an IP Addresse by random or change the order *
+ * of IP addresses, doing so will break RFC 3484 address selection *
+ */
}
else
{
/* IP address parse succeeded */
- success = true;
}
done:
@@ -470,14 +263,14 @@ getaddr6 (unsigned int flags,
{
int level = 0;
if (flags & GETADDR_FATAL_ON_SIGNAL)
- level = M_FATAL;
+ level = M_FATAL;
else if (flags & GETADDR_WARN_ON_SIGNAL)
- level = M_WARN;
+ level = M_WARN;
msg (level, "RESOLVE: signal received during DNS resolution attempt");
}
gc_free (&gc);
- return success;
+ return status;
}
/*
@@ -653,18 +446,16 @@ update_remote (const char* host,
case AF_INET6:
if (host && addr)
{
- struct sockaddr_in6 sin6;
- int success;
- CLEAR(sin6);
- success = getaddr6 (
- sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags),
- host,
- 1,
- NULL,
- NULL,
- &sin6);
- if ( success )
+ int status;
+ struct addrinfo* ai;
+
+ status = openvpn_getaddrinfo(sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), host, 1, NULL, AF_INET6, &ai);
+
+ if ( status ==0 )
{
+ struct sockaddr_in6 sin6;
+ CLEAR(sin6);
+ sin6 = *((struct sockaddr_in6*)ai->ai_addr);
if (!IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, &addr->addr.in6.sin6_addr))
{
int port = addr->addr.in6.sin6_port;
@@ -672,6 +463,7 @@ update_remote (const char* host,
addr->addr.in6 = sin6;
addr->addr.in6.sin6_port = port;
}
+ freeaddrinfo(ai);
}
}
break;
@@ -830,11 +622,11 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
*/
socket_descriptor_t
-create_socket_tcp (void)
+create_socket_tcp (int af)
{
socket_descriptor_t sd;
- if ((sd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ if ((sd = socket (af, SOCK_STREAM, IPPROTO_TCP)) < 0)
msg (M_ERR, "Cannot create TCP socket");
#ifndef WIN32 /* using SO_REUSEADDR on Windows will cause bind to succeed on port conflicts! */
@@ -847,18 +639,6 @@ create_socket_tcp (void)
}
#endif
-#if 0
- /* set socket linger options */
- {
- struct linger linger;
- linger.l_onoff = 1;
- linger.l_linger = 2;
- if (setsockopt (sd, SOL_SOCKET, SO_LINGER,
- (void *) &linger, sizeof (linger)) < 0)
- msg (M_ERR, "TCP: Cannot setsockopt SO_LINGER on TCP socket");
- }
-#endif
-
return sd;
}
@@ -913,25 +693,6 @@ create_socket_udp6 (const unsigned int flags)
return sd;
}
-static socket_descriptor_t
-create_socket_tcp6 (void)
-{
- socket_descriptor_t sd;
-
- if ((sd = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0)
- msg (M_ERR, "Cannot create TCP6 socket");
-
- /* set SO_REUSEADDR on socket */
- {
- int on = 1;
- if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR,
- (void *) &on, sizeof (on)) < 0)
- msg (M_ERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP6 socket");
- }
-
- return sd;
-}
-
static void
create_socket (struct link_socket *sock)
{
@@ -943,18 +704,18 @@ create_socket (struct link_socket *sock)
#ifdef ENABLE_SOCKS
if (sock->socks_proxy)
- sock->ctrl_sd = create_socket_tcp ();
+ sock->ctrl_sd = create_socket_tcp (AF_INET);
#endif
}
else if (sock->info.proto == PROTO_TCPv4_SERVER
|| sock->info.proto == PROTO_TCPv4_CLIENT)
{
- sock->sd = create_socket_tcp ();
+ sock->sd = create_socket_tcp (AF_INET);
}
else if (sock->info.proto == PROTO_TCPv6_SERVER
|| sock->info.proto == PROTO_TCPv6_CLIENT)
{
- sock->sd = create_socket_tcp6 ();
+ sock->sd = create_socket_tcp (AF_INET6);
}
else if (sock->info.proto == PROTO_UDPv6)
{
@@ -1314,15 +1075,7 @@ socket_connect (socket_descriptor_t *sd,
if (*signal_received)
goto done;
- switch(local->addr.sa.sa_family)
- {
- case PF_INET6:
- *sd = create_socket_tcp6 ();
- break;
- case PF_INET:
- *sd = create_socket_tcp ();
- break;
- }
+ *sd = create_socket_tcp (local->addr.sa.sa_family);
if (bind_local)
socket_bind (*sd, local, "TCP Client");
@@ -1404,25 +1157,27 @@ resolve_bind_local (struct link_socket *sock)
break;
case AF_INET6:
{
- int success;
+ int status;
int err;
CLEAR(sock->info.lsa->local.addr.in6);
if (sock->local_host)
{
- success = getaddr6(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL,
- sock->local_host,
- 0,
- NULL,
- &err,
- &sock->info.lsa->local.addr.in6);
+ struct addrinfo *ai;
+
+ status = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL,
+ sock->local_host, 0, NULL, AF_INET6, &ai);
+ if(status ==0) {
+ sock->info.lsa->local.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr));
+ freeaddrinfo(ai);
+ }
}
else
{
sock->info.lsa->local.addr.in6.sin6_family = AF_INET6;
sock->info.lsa->local.addr.in6.sin6_addr = in6addr_any;
- success = true;
+ status = 0;
}
- if (!success)
+ if (!status == 0)
{
msg (M_FATAL, "getaddr6() failed for local \"%s\": %s",
sock->local_host,
@@ -1479,7 +1234,7 @@ resolve_remote (struct link_socket *sock,
{
unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
int retry = 0;
- bool status = false;
+ int status = -1;
if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
{
@@ -1516,40 +1271,27 @@ resolve_remote (struct link_socket *sock,
ASSERT (0);
}
- switch(af)
- {
- case AF_INET:
- sock->info.lsa->remote.addr.in4.sin_addr.s_addr = getaddr (
- flags,
- sock->remote_host,
- retry,
- &status,
- signal_received);
- break;
- case AF_INET6:
- status = getaddr6 (
- flags,
- sock->remote_host,
- retry,
- signal_received,
- NULL,
- &sock->info.lsa->remote.addr.in6);
- break;
- }
-
- dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d",
- flags,
- phase,
- retry,
- signal_received ? *signal_received : -1,
- status);
-
+ struct addrinfo* ai;
+ /* Temporary fix, this need to be changed for dual stack */
+ status = openvpn_getaddrinfo(flags, sock->remote_host, retry,
+ signal_received, af, &ai);
+ if(status == 0) {
+ sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr));
+ freeaddrinfo(ai);
+
+ dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d",
+ flags,
+ phase,
+ retry,
+ signal_received ? *signal_received : -1,
+ status);
+ }
if (signal_received)
{
if (*signal_received)
goto done;
}
- if (!status)
+ if (status!=0)
{
if (signal_received)
*signal_received = SIGUSR1;
@@ -1927,7 +1669,7 @@ link_socket_init_phase2 (struct link_socket *sock,
if (proxy_retry)
{
openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp ();
+ sock->sd = create_socket_tcp (AF_INET);
}
} while (proxy_retry);
}
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index 47c6e8eb..44f1098b 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -425,7 +425,7 @@ bool ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn);
bool mac_addr_safe (const char *mac_addr);
bool ipv6_addr_safe (const char *ipv6_text_addr);
-socket_descriptor_t create_socket_tcp (void);
+socket_descriptor_t create_socket_tcp (int af);
socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
struct link_socket_actual *act,
@@ -467,11 +467,6 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
* DNS resolution
*/
-struct resolve_list {
- int len;
- in_addr_t data[16];
-};
-
#define GETADDR_RESOLVE (1<<0)
#define GETADDR_FATAL (1<<1)
#define GETADDR_HOST_ORDER (1<<2)
@@ -494,12 +489,12 @@ in_addr_t getaddr (unsigned int flags,
bool *succeeded,
volatile int *signal_received);
-in_addr_t getaddr_multi (unsigned int flags,
- const char *hostname,
- int resolve_retry_seconds,
- bool *succeeded,
- volatile int *signal_received,
- struct resolve_list *reslist);
+int openvpn_getaddrinfo (unsigned int flags,
+ const char *hostname,
+ int resolve_retry_seconds,
+ volatile int *signal_received,
+ int ai_family,
+ struct addrinfo **res);
/*
* Transport protocol naming and other details.
diff --git a/openvpn/src/openvpn/ssl_common.h b/openvpn/src/openvpn/ssl_common.h
index f3f43be2..cb259a96 100644
--- a/openvpn/src/openvpn/ssl_common.h
+++ b/openvpn/src/openvpn/ssl_common.h
@@ -288,7 +288,6 @@ struct tls_options
# define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)
# define SSLF_USERNAME_AS_COMMON_NAME (1<<1)
# define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2)
-# define SSLF_NO_NAME_REMAPPING (1<<3)
# define SSLF_OPT_VERIFY (1<<4)
# define SSLF_CRL_VERIFY_DIR (1<<5)
unsigned int ssl_flags;
diff --git a/openvpn/src/openvpn/ssl_verify_openssl.h b/openvpn/src/openvpn/ssl_verify_openssl.h
index afd6110b..5a7e0a19 100644
--- a/openvpn/src/openvpn/ssl_verify_openssl.h
+++ b/openvpn/src/openvpn/ssl_verify_openssl.h
@@ -73,6 +73,4 @@ int verify_callback (int preverify_ok, X509_STORE_CTX * ctx);
/** @} name Function for authenticating a new connection from a remote OpenVPN peer */
-char *_openssl_get_subject (X509 *cert, char *buf, int size);
-
#endif /* SSL_VERIFY_OPENSSL_H_ */
diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c
index 81979476..cd61baf4 100644
--- a/openvpn/src/openvpn/tun.c
+++ b/openvpn/src/openvpn/tun.c
@@ -925,7 +925,7 @@ do_ifconfig (struct tuntap *tt,
#elif defined(TARGET_OPENBSD)
/*
- * On OpenBSD, tun interfaces are persistant if created with
+ * On OpenBSD, tun interfaces are persistent if created with
* "ifconfig tunX create", and auto-destroyed if created by
* opening "/dev/tunX" (so we just use the /dev/tunX)
*/
@@ -1270,7 +1270,7 @@ do_ifconfig (struct tuntap *tt,
gc_free (&gc);
}
-void
+static void
clear_tuntap (struct tuntap *tuntap)
{
CLEAR (*tuntap);
@@ -1379,6 +1379,13 @@ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
if (!dynamic_opened)
{
+ /* has named device existed before? if so, don't destroy at end */
+ if ( if_nametoindex( dev ) > 0 )
+ {
+ msg (M_INFO, "TUN/TAP device %s exists previously, keep at program end", dev );
+ tt->persistent_if = true;
+ }
+
if ((tt->fd = open (tunname, O_RDWR)) < 0)
msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname);
}
@@ -2116,7 +2123,7 @@ close_tun (struct tuntap* tt)
{
/* only *TAP* devices need destroying, tun devices auto-self-destruct
*/
- if (tt && tt->type == DEV_TYPE_TUN )
+ if (tt && (tt->type == DEV_TYPE_TUN || tt->persistent_if ) )
{
close_tun_generic (tt);
free(tt);
@@ -2251,7 +2258,7 @@ close_tun (struct tuntap *tt)
{
/* only tun devices need destroying, tap devices auto-self-destruct
*/
- if (tt && tt->type != DEV_TYPE_TUN )
+ if (tt && ( tt->type != DEV_TYPE_TUN || tt->persistent_if ) )
{
close_tun_generic (tt);
free(tt);
@@ -2389,7 +2396,12 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
void
close_tun (struct tuntap *tt)
{
- if (tt)
+ if (tt && tt->persistent_if ) /* keep pre-existing if around */
+ {
+ close_tun_generic (tt);
+ free (tt);
+ }
+ else if (tt) /* close and destroy */
{
struct gc_arena gc = gc_new ();
struct argv argv;
diff --git a/openvpn/src/openvpn/tun.h b/openvpn/src/openvpn/tun.h
index 0f4f0123..c31ac001 100644
--- a/openvpn/src/openvpn/tun.h
+++ b/openvpn/src/openvpn/tun.h
@@ -137,6 +137,8 @@ struct tuntap
bool ipv6;
+ bool persistent_if; /* if existed before, keep on program end */
+
struct tuntap_options options; /* options set on command line */
char *actual_name; /* actual name of TUN/TAP dev, usually including unit number */
@@ -201,7 +203,7 @@ tuntap_defined (const struct tuntap *tt)
* Function prototypes
*/
-void clear_tuntap (struct tuntap *tuntap);
+static void clear_tuntap (struct tuntap *tuntap);
void open_tun (const char *dev, const char *dev_type, const char *dev_node,
struct tuntap *tt);
diff --git a/openvpn/tests/t_client.sh.in b/openvpn/tests/t_client.sh.in
index 8c66033f..189eecce 100755
--- a/openvpn/tests/t_client.sh.in
+++ b/openvpn/tests/t_client.sh.in
@@ -234,7 +234,8 @@ do
fi
echo " run openvpn $openvpn_conf"
- $RUN_SUDO "${top_builddir}/src/openvpn/openvpn" $openvpn_conf >$LOGDIR/$SUF:openvpn.log &
+ echo "# src/openvpn/openvpn $openvpn_conf" >$LOGDIR/$SUF:openvpn.log
+ $RUN_SUDO "${top_builddir}/src/openvpn/openvpn" $openvpn_conf >>$LOGDIR/$SUF:openvpn.log &
opid=$!
# make sure openvpn client is terminated in case shell exits