summaryrefslogtreecommitdiff
path: root/openvpn/src
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2012-12-14 12:58:27 +0100
committerArne Schwabe <arne@rfc2549.org>2012-12-14 12:58:27 +0100
commit76a0da0622b9bf04756f5ad39bc31759809e76ff (patch)
tree0aa1574634fd62578248f548dc51f3f08f7460c1 /openvpn/src
parent1c83b296a1d31da96531f74fc2010346566aaf57 (diff)
Update openvpn to Dual Stack version
Diffstat (limited to 'openvpn/src')
-rw-r--r--openvpn/src/openvpn/buffer.c10
-rw-r--r--openvpn/src/openvpn/buffer.h5
-rw-r--r--openvpn/src/openvpn/error.c8
-rw-r--r--openvpn/src/openvpn/forward-inline.h1
-rw-r--r--openvpn/src/openvpn/forward.c34
-rw-r--r--openvpn/src/openvpn/forward.h4
-rw-r--r--openvpn/src/openvpn/init.c282
-rw-r--r--openvpn/src/openvpn/manage.c49
-rw-r--r--openvpn/src/openvpn/manage.h4
-rw-r--r--openvpn/src/openvpn/misc.c106
-rw-r--r--openvpn/src/openvpn/misc.h5
-rw-r--r--openvpn/src/openvpn/mss.c57
-rw-r--r--openvpn/src/openvpn/mss.h3
-rw-r--r--openvpn/src/openvpn/multi.c6
-rw-r--r--openvpn/src/openvpn/options.c346
-rw-r--r--openvpn/src/openvpn/options.h41
-rw-r--r--openvpn/src/openvpn/pf.c1
-rw-r--r--openvpn/src/openvpn/pkcs11.c2
-rw-r--r--openvpn/src/openvpn/platform.c27
-rw-r--r--openvpn/src/openvpn/platform.h4
-rw-r--r--openvpn/src/openvpn/plugin.c8
-rw-r--r--openvpn/src/openvpn/proto.c19
-rw-r--r--openvpn/src/openvpn/proto.h3
-rw-r--r--openvpn/src/openvpn/proxy.c10
-rw-r--r--openvpn/src/openvpn/proxy.h6
-rw-r--r--openvpn/src/openvpn/ps.c33
-rw-r--r--openvpn/src/openvpn/ps.h2
-rw-r--r--openvpn/src/openvpn/push.c2
-rw-r--r--openvpn/src/openvpn/route.c8
-rw-r--r--openvpn/src/openvpn/sig.c22
-rw-r--r--openvpn/src/openvpn/sig.h11
-rw-r--r--openvpn/src/openvpn/socket.c1302
-rw-r--r--openvpn/src/openvpn/socket.h207
-rw-r--r--openvpn/src/openvpn/socks.c32
-rw-r--r--openvpn/src/openvpn/socks.h6
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.c2
-rw-r--r--openvpn/src/openvpn/tun.c33
-rw-r--r--openvpn/src/openvpn/tun.h4
-rw-r--r--openvpn/src/openvpn/win32.c127
39 files changed, 1392 insertions, 1440 deletions
diff --git a/openvpn/src/openvpn/buffer.c b/openvpn/src/openvpn/buffer.c
index 5eee3ee4..56d14b1a 100644
--- a/openvpn/src/openvpn/buffer.c
+++ b/openvpn/src/openvpn/buffer.c
@@ -782,6 +782,16 @@ char_class (const unsigned char c, const unsigned int flags)
return true;
if ((flags & CC_EQUAL) && c == '=')
return true;
+ if ((flags & CC_LESS_THAN) && c == '<')
+ return true;
+ if ((flags & CC_GREATER_THAN) && c == '>')
+ return true;
+ if ((flags & CC_PIPE) && c == '|')
+ return true;
+ if ((flags & CC_QUESTION_MARK) && c == '?')
+ return true;
+ if ((flags & CC_ASTERISK) && c == '*')
+ return true;
return false;
}
diff --git a/openvpn/src/openvpn/buffer.h b/openvpn/src/openvpn/buffer.h
index 9bc33dba..5e11de05 100644
--- a/openvpn/src/openvpn/buffer.h
+++ b/openvpn/src/openvpn/buffer.h
@@ -736,6 +736,11 @@ const char *np (const char *str);
#define CC_REVERSE_QUOTE (1<<23)
#define CC_AT (1<<24)
#define CC_EQUAL (1<<25)
+#define CC_LESS_THAN (1<<26)
+#define CC_GREATER_THAN (1<<27)
+#define CC_PIPE (1<<28)
+#define CC_QUESTION_MARK (1<<29)
+#define CC_ASTERISK (1<<30)
/* macro classes */
#define CC_NAME (CC_ALNUM|CC_UNDERBAR)
diff --git a/openvpn/src/openvpn/error.c b/openvpn/src/openvpn/error.c
index 6848425e..ebe9a52d 100644
--- a/openvpn/src/openvpn/error.c
+++ b/openvpn/src/openvpn/error.c
@@ -259,7 +259,7 @@ void x_msg_va (const unsigned int flags, const char *format, va_list arglist)
if (flags & M_SSL)
{
int nerrs = 0;
- int err;
+ size_t err;
while ((err = ERR_get_error ()))
{
openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s",
@@ -602,7 +602,7 @@ x_check_status (int status,
const char *extended_msg = NULL;
msg (x_cs_verbose_level, "%s %s returned %d",
- sock ? proto2ascii (sock->info.proto, true) : "",
+ sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
description,
status);
@@ -630,14 +630,14 @@ x_check_status (int status,
if (extended_msg)
msg (x_cs_info_level, "%s %s [%s]: %s (code=%d)",
description,
- sock ? proto2ascii (sock->info.proto, true) : "",
+ sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
extended_msg,
strerror_ts (my_errno, &gc),
my_errno);
else
msg (x_cs_info_level, "%s %s: %s (code=%d)",
description,
- sock ? proto2ascii (sock->info.proto, true) : "",
+ sock ? proto2ascii (sock->info.proto, sock->info.af, true) : "",
strerror_ts (my_errno, &gc),
my_errno);
diff --git a/openvpn/src/openvpn/forward-inline.h b/openvpn/src/openvpn/forward-inline.h
index 5853ce29..7eb480dd 100644
--- a/openvpn/src/openvpn/forward-inline.h
+++ b/openvpn/src/openvpn/forward-inline.h
@@ -228,6 +228,7 @@ 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/forward.c b/openvpn/src/openvpn/forward.c
index 57c78462..9e9c406c 100644
--- a/openvpn/src/openvpn/forward.c
+++ b/openvpn/src/openvpn/forward.c
@@ -620,7 +620,7 @@ check_timeout_random_component (struct context *c)
static inline void
socks_postprocess_incoming_link (struct context *c)
{
- if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDPv4)
+ if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP)
socks_process_incoming_udp (&c->c2.buf, &c->c2.from);
}
@@ -629,7 +629,7 @@ socks_preprocess_outgoing_link (struct context *c,
struct link_socket_actual **to_addr,
int *size_delta)
{
- if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDPv4)
+ if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP)
{
*size_delta += socks_process_outgoing_udp (&c->c2.to_link, c->c2.to_link_addr);
*to_addr = &c->c2.link_socket->socks_relay;
@@ -778,7 +778,7 @@ process_incoming_link (struct context *c)
fprintf (stderr, "R");
#endif
msg (D_LINK_RW, "%s READ [%d] from %s: %s",
- proto2ascii (lsi->proto, true),
+ proto2ascii (lsi->proto, lsi->af, true),
BLEN (&c->c2.buf),
print_link_socket_actual (&c->c2.from, &gc),
PROTO_DUMP (&c->c2.buf, &gc));
@@ -985,9 +985,9 @@ process_incoming_tun (struct context *c)
{
/*
* The --passtos and --mssfix options require
- * us to examine the IPv4 header.
+ * us to examine the IP header (IPv4 or IPv6).
*/
- process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
+ process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
#ifdef PACKET_TRUNCATION_CHECK
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
@@ -1009,10 +1009,10 @@ process_incoming_tun (struct context *c)
}
void
-process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
+process_ip_header (struct context *c, unsigned int flags, struct buffer *buf)
{
if (!c->options.ce.mssfix)
- flags &= ~PIPV4_MSSFIX;
+ flags &= ~PIP_MSSFIX;
#if PASSTOS_CAPABILITY
if (!c->options.passtos)
flags &= ~PIPV4_PASSTOS;
@@ -1027,9 +1027,9 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
* us to examine the IPv4 header.
*/
#if PASSTOS_CAPABILITY
- if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
+ if (flags & (PIPV4_PASSTOS|PIP_MSSFIX))
#else
- if (flags & PIPV4_MSSFIX)
+ if (flags & PIP_MSSFIX)
#endif
{
struct buffer ipbuf = *buf;
@@ -1042,8 +1042,8 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
#endif
/* possibly alter the TCP MSS */
- if (flags & PIPV4_MSSFIX)
- mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+ if (flags & PIP_MSSFIX)
+ mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
#ifdef ENABLE_CLIENT_NAT
/* possibly do NAT on packet */
@@ -1061,6 +1061,12 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
}
}
+ else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
+ {
+ /* possibly alter the TCP MSS */
+ if (flags & PIP_MSSFIX)
+ mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+ }
}
}
}
@@ -1116,7 +1122,7 @@ process_outgoing_link (struct context *c)
fprintf (stderr, "W");
#endif
msg (D_LINK_RW, "%s WRITE [%d] to %s: %s",
- proto2ascii (c->c2.link_socket->info.proto, true),
+ proto2ascii (c->c2.link_socket->info.proto, c->c2.link_socket->info.proto, true),
BLEN (&c->c2.to_link),
print_link_socket_actual (c->c2.to_link_addr, &gc),
PROTO_DUMP (&c->c2.to_link, &gc));
@@ -1217,9 +1223,9 @@ process_outgoing_tun (struct context *c)
/*
* The --mssfix option requires
- * us to examine the IPv4 header.
+ * us to examine the IP header (IPv4 or IPv6).
*/
- process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
+ process_ip_header (c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
{
diff --git a/openvpn/src/openvpn/forward.h b/openvpn/src/openvpn/forward.h
index 0f829bde..1830a00b 100644
--- a/openvpn/src/openvpn/forward.h
+++ b/openvpn/src/openvpn/forward.h
@@ -228,12 +228,12 @@ void process_outgoing_tun (struct context *c);
bool send_control_channel_string (struct context *c, const char *str, int msglevel);
#define PIPV4_PASSTOS (1<<0)
-#define PIPV4_MSSFIX (1<<1)
+#define PIP_MSSFIX (1<<1) /* v4 and v6 */
#define PIPV4_OUTGOING (1<<2)
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
#define PIPV4_CLIENT_NAT (1<<4)
-void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf);
+void process_ip_header (struct context *c, unsigned int flags, struct buffer *buf);
#if P2MP
void schedule_exit (struct context *c, const int n_seconds, const int signal);
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index 1f06eaa5..fe70dd57 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -125,28 +125,19 @@ management_callback_proxy_cmd (void *arg, const char **p)
ret = true;
else if (p[2] && p[3])
{
- const int port = atoi(p[3]);
- if (!legal_ipv4_port (port))
- {
- msg (M_WARN, "Bad proxy port number: %s", p[3]);
- return false;
- }
-
if (streq (p[1], "HTTP"))
{
#ifndef ENABLE_HTTP_PROXY
msg (M_WARN, "HTTP proxy support is not available");
#else
struct http_proxy_options *ho;
- if (ce->proto != PROTO_TCPv4 && ce->proto != PROTO_TCPv4_CLIENT &&
- ce->proto != PROTO_TCPv6 && ce->proto != PROTO_TCPv6_CLIENT)
- {
+ if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT ) {
msg (M_WARN, "HTTP proxy support only works for TCP based connections");
return false;
}
ho = init_http_proxy_options_once (&ce->http_proxy_options, gc);
ho->server = string_alloc (p[2], gc);
- ho->port = port;
+ ho->port = p[3];
ho->retry = true;
ho->auth_retry = (p[4] && streq (p[4], "nct") ? PAR_NCT : PAR_ALL);
ret = true;
@@ -158,7 +149,7 @@ management_callback_proxy_cmd (void *arg, const char **p)
msg (M_WARN, "SOCKS proxy support is not available");
#else
ce->socks_proxy_server = string_alloc (p[2], gc);
- ce->socks_proxy_port = port;
+ ce->socks_proxy_port = p[3];
ret = true;
#endif
}
@@ -225,8 +216,7 @@ management_callback_remote_cmd (void *arg, const char **p)
}
else if (!strcmp(p[1], "MOD") && p[2] && p[3])
{
- const int port = atoi(p[3]);
- if (strlen(p[2]) < RH_HOST_LEN && legal_ipv4_port(port))
+ if (strlen(p[2]) < RH_HOST_LEN && strlen(p[3]) < RH_PORT_LEN)
{
struct remote_host_store *rhs = c->options.rh_store;
if (!rhs)
@@ -235,8 +225,10 @@ management_callback_remote_cmd (void *arg, const char **p)
c->options.rh_store = rhs;
}
strncpynt(rhs->host, p[2], RH_HOST_LEN);
+ strncpynt(rhs->port, p[3], RH_PORT_LEN);
+
ce->remote = rhs->host;
- ce->remote_port = port;
+ ce->remote_port = rhs->port;
flags = CE_MAN_QUERY_REMOTE_MOD;
ret = true;
}
@@ -251,7 +243,7 @@ management_callback_remote_cmd (void *arg, const char **p)
}
static bool
-ce_management_query_remote (struct context *c, const char *remote_ip_hint)
+ce_management_query_remote (struct context *c)
{
struct gc_arena gc = gc_new ();
volatile struct connection_entry *ce = &c->options.ce;
@@ -260,7 +252,7 @@ ce_management_query_remote (struct context *c, const char *remote_ip_hint)
if (management)
{
struct buffer out = alloc_buf_gc (256, &gc);
- buf_printf (&out, ">REMOTE:%s,%d,%s", np(ce->remote), ce->remote_port, proto2ascii(ce->proto, false));
+ buf_printf (&out, ">REMOTE:%s,%s,%s", np(ce->remote), ce->remote_port, proto2ascii(ce->proto, ce->af, false));
management_notify_generic(management, BSTR (&out));
ce->flags &= ~(CE_MAN_QUERY_REMOTE_MASK<<CE_MAN_QUERY_REMOTE_SHIFT);
ce->flags |= (CE_MAN_QUERY_REMOTE_QUERY<<CE_MAN_QUERY_REMOTE_SHIFT);
@@ -276,8 +268,6 @@ ce_management_query_remote (struct context *c, const char *remote_ip_hint)
}
{
const int flags = ((ce->flags>>CE_MAN_QUERY_REMOTE_SHIFT) & CE_MAN_QUERY_REMOTE_MASK);
- if (flags == CE_MAN_QUERY_REMOTE_ACCEPT && remote_ip_hint)
- ce->remote = remote_ip_hint;
ret = (flags != CE_MAN_QUERY_REMOTE_SKIP);
}
gc_free (&gc);
@@ -292,25 +282,34 @@ static void
init_connection_list (struct context *c)
{
struct connection_list *l = c->options.connection_list;
- if (l)
+ l->current = -1;
+ if (c->options.remote_random)
{
- l->current = -1;
- if (c->options.remote_random)
- {
- int i;
- for (i = 0; i < l->len; ++i)
- {
- const int j = get_random () % l->len;
- if (i != j)
- {
- struct connection_entry *tmp;
- tmp = l->array[i];
- l->array[i] = l->array[j];
- l->array[j] = tmp;
- }
- }
- }
+ int i;
+ for (i = 0; i < l->len; ++i)
+ {
+ const int j = get_random () % l->len;
+ if (i != j)
+ {
+ struct connection_entry *tmp;
+ tmp = l->array[i];
+ l->array[i] = l->array[j];
+ l->array[j] = tmp;
+ }
+ }
+ }
+}
+
+/*
+ * Clear the remote address list
+ */
+static void clear_remote_addrlist (struct link_socket_addr *lsa)
+{
+ if (lsa->remote_list) {
+ freeaddrinfo(lsa->remote_list);
}
+ lsa->remote_list = NULL;
+ lsa->current_remote = NULL;
}
/*
@@ -320,67 +319,84 @@ static void
next_connection_entry (struct context *c)
{
struct connection_list *l = c->options.connection_list;
- if (l)
- {
- bool ce_defined;
- struct connection_entry *ce;
- int n_cycles = 0;
-
- do {
- const char *remote_ip_hint = NULL;
- bool newcycle = false;
-
- ce_defined = true;
- if (l->no_advance && l->current >= 0)
- {
- l->no_advance = false;
- }
- else
- {
- if (++l->current >= l->len)
- {
- l->current = 0;
- ++l->n_cycles;
- if (++n_cycles >= 2)
- msg (M_FATAL, "No usable connection profiles are present");
- }
-
- if (l->current == 0)
- newcycle = true;
- }
-
- ce = l->array[l->current];
+ bool ce_defined;
+ struct connection_entry *ce;
+ int n_cycles = 0;
+
+ do {
+ ce_defined = true;
+ if (c->options.no_advance && l->current >= 0)
+ {
+ c->options.no_advance = false;
+ }
+ else
+ {
+ /* Check if there is another resolved address to try for
+ * the current connection */
+ if (c->c1.link_socket_addr.current_remote &&
+ c->c1.link_socket_addr.current_remote->ai_next)
+ {
+ c->c1.link_socket_addr.current_remote =
+ c->c1.link_socket_addr.current_remote->ai_next;
+ }
+ else
+ {
+ c->options.unsuccessful_attempts++;
+ if (++l->current >= l->len)
+ {
+ /* FIXME (schwabe) fix the persist-remote-ip option for real,
+ * this is broken probably ever since connection lists and multiple
+ * remote existed
+ */
+ /*
+ * Increase the number of connection attempts
+ * If this is connect-retry-max * size(l)
+ * OpenVPN will quit
+ */
+
+ if (!c->options.persist_remote_ip)
+ clear_remote_addrlist (&c->c1.link_socket_addr);
+
+ l->current = 0;
+ ++l->n_cycles;
+ if (++n_cycles >= 2)
+ msg (M_FATAL, "No usable connection profiles are present");
+ }
+ }
+ }
- if (c->options.remote_ip_hint && !l->n_cycles)
- remote_ip_hint = c->options.remote_ip_hint;
+ ce = l->array[l->current];
- if (ce->flags & CE_DISABLED)
- ce_defined = false;
+ if (ce->flags & CE_DISABLED)
+ ce_defined = false;
- c->options.ce = *ce;
+ c->options.ce = *ce;
#ifdef ENABLE_MANAGEMENT
- if (ce_defined && management && management_query_remote_enabled(management))
- {
- /* allow management interface to override connection entry details */
- ce_defined = ce_management_query_remote(c, remote_ip_hint);
- if (IS_SIG (c))
- break;
- }
- else
+ if (ce_defined && management && management_query_remote_enabled(management))
+ {
+ /* allow management interface to override connection entry details */
+ ce_defined = ce_management_query_remote(c);
+ if (IS_SIG (c))
+ break;
+ }
+ else
#endif
- if (remote_ip_hint)
- c->options.ce.remote = remote_ip_hint;
#ifdef ENABLE_MANAGEMENT
- if (ce_defined && management && management_query_proxy_enabled (management))
- {
- ce_defined = ce_management_query_proxy (c);
- if (IS_SIG (c))
- break;
- }
+ if (ce_defined && management && management_query_proxy_enabled (management))
+ {
+ ce_defined = ce_management_query_proxy (c);
+ if (IS_SIG (c))
+ break;
+ }
#endif
- } while (!ce_defined);
- }
+ } while (!ce_defined);
+
+ /* Check if this connection attempt would bring us over the limit */
+ if (c->options.connect_retry_max > 0 &&
+ c->options.unsuccessful_attempts > (l->len * c->options.connect_retry_max))
+ msg(M_FATAL, "All connections have been connect-retry-max (%d) times unsuccessful, exiting",
+ c->options.connect_retry_max);
update_options_ce_post (&c->options);
}
@@ -415,12 +431,6 @@ init_query_passwords (struct context *c)
#ifdef GENERAL_PROXY_SUPPORT
-static int
-proxy_scope (struct context *c)
-{
- return connection_list_defined (&c->options) ? 2 : 1;
-}
-
static void
uninit_proxy_dowork (struct context *c)
{
@@ -482,17 +492,15 @@ init_proxy_dowork (struct context *c)
}
static void
-init_proxy (struct context *c, const int scope)
+init_proxy (struct context *c)
{
- if (scope == proxy_scope (c))
- init_proxy_dowork (c);
+ init_proxy_dowork (c);
}
static void
uninit_proxy (struct context *c)
{
- if (c->sig->signal_received != SIGUSR1 || proxy_scope (c) == 2)
- uninit_proxy_dowork (c);
+ uninit_proxy_dowork (c);
}
#else
@@ -544,8 +552,6 @@ context_init_1 (struct context *c)
}
#endif
- /* initialize HTTP or SOCKS proxy object at scope level 1 */
- init_proxy (c, 1);
}
void
@@ -1240,6 +1246,9 @@ void
initialization_sequence_completed (struct context *c, const unsigned int flags)
{
static const char message[] = "Initialization Sequence Completed";
+
+ /* Reset the unsuccessful connection counter on complete initialisation */
+ c->options.unsuccessful_attempts=0;
/* If we delayed UID/GID downgrade or chroot, do it now */
do_uid_gid_chroot (c, true);
@@ -1258,9 +1267,9 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
else
msg (M_INFO, "%s", message);
- /* Flag connection_list that we initialized */
- if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && connection_list_defined (&c->options))
- connection_list_set_no_advance (&c->options);
+ /* Flag that we initialized */
+ if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0)
+ c->options.no_advance=true;
#ifdef WIN32
fork_register_dns_action (c->c1.tuntap);
@@ -1374,8 +1383,8 @@ do_init_tun (struct context *c)
c->options.ifconfig_ipv6_local,
c->options.ifconfig_ipv6_netbits,
c->options.ifconfig_ipv6_remote,
- addr_host (&c->c1.link_socket_addr.local),
- addr_host (&c->c1.link_socket_addr.remote),
+ c->c1.link_socket_addr.bind_local,
+ c->c1.link_socket_addr.remote_list,
!c->options.ifconfig_nowarn,
c->c2.es);
@@ -1853,17 +1862,11 @@ socket_restart_pause (struct context *c)
switch (c->options.ce.proto)
{
- case PROTO_UDPv4:
- case PROTO_UDPv6:
- if (proxy)
- sec = c->options.ce.connect_retry_seconds;
- break;
- case PROTO_TCPv4_SERVER:
- case PROTO_TCPv6_SERVER:
+ case PROTO_TCP_SERVER:
sec = 1;
break;
- case PROTO_TCPv4_CLIENT:
- case PROTO_TCPv6_CLIENT:
+ case PROTO_UDP:
+ case PROTO_TCP_CLIENT:
sec = c->options.ce.connect_retry_seconds;
break;
}
@@ -2219,7 +2222,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
/* should we not xmit any packets until we get an initial
response from client? */
- if (to.server && options->ce.proto == PROTO_TCPv4_SERVER)
+ if (to.server && options->ce.proto == PROTO_TCP_SERVER)
to.xmit_hold = true;
#ifdef ENABLE_OCC
@@ -2504,8 +2507,6 @@ do_option_warnings (struct context *c)
msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");
#endif
- 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");
}
static void
@@ -2628,12 +2629,12 @@ do_init_socket_1 (struct context *c, const int mode)
#endif
link_socket_init_phase1 (c->c2.link_socket,
- connection_list_defined (&c->options),
c->options.ce.local,
c->options.ce.local_port,
c->options.ce.remote,
c->options.ce.remote_port,
c->options.ce.proto,
+ c->options.ce.af,
mode,
c->c2.accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -2652,9 +2653,7 @@ do_init_socket_1 (struct context *c, const int mode)
c->options.ipchange,
c->plugins,
c->options.resolve_retry_seconds,
- c->options.ce.connect_retry_seconds,
c->options.ce.connect_timeout,
- c->options.ce.connect_retry_max,
c->options.ce.mtu_discover_type,
c->options.rcvbuf,
c->options.sndbuf,
@@ -2669,7 +2668,7 @@ static void
do_init_socket_2 (struct context *c)
{
link_socket_init_phase2 (c->c2.link_socket, &c->c2.frame,
- &c->sig->signal_received);
+ c->sig);
}
/*
@@ -2841,14 +2840,30 @@ do_close_link_socket (struct context *c)
c->c2.link_socket = NULL;
}
- if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip))
- {
- CLEAR (c->c1.link_socket_addr.remote);
+
+ /* Preserve the resolved list of remote if the user request to or if we want
+ * reconnect to the same host again or there are still addresses that need
+ * to be tried */
+ if (!(c->sig->signal_received == SIGUSR1 &&
+ ( (c->options.persist_remote_ip)
+ ||
+ ( c->sig->source != SIG_SOURCE_HARD &&
+ ((c->c1.link_socket_addr.current_remote && c->c1.link_socket_addr.current_remote->ai_next)
+ || c->options.no_advance))
+ )))
+ {
+ clear_remote_addrlist(&c->c1.link_socket_addr);
+ }
+
+ /* Clear the remote actual address when persist_remote_ip is not in use */
+ if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip))
CLEAR (c->c1.link_socket_addr.actual);
- }
- if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip))
- CLEAR (c->c1.link_socket_addr.local);
+ if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) {
+ if (c->c1.link_socket_addr.bind_local)
+ freeaddrinfo(c->c1.link_socket_addr.bind_local);
+ c->c1.link_socket_addr.bind_local=NULL;
+ }
}
/*
@@ -3271,7 +3286,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
/* signals caught here will abort */
c->sig->signal_received = 0;
c->sig->signal_text = NULL;
- c->sig->hard = false;
+ c->sig->source = SIG_SOURCE_SOFT;
if (c->mode == CM_P2P)
init_management_callback_p2p (c);
@@ -3290,8 +3305,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
/* link_socket_mode allows CM_CHILD_TCP
instances to inherit acceptable fds
from a top-level parent */
- if (c->options.ce.proto == PROTO_TCPv4_SERVER
- || c->options.ce.proto == PROTO_TCPv6_SERVER)
+ if (c->options.ce.proto == PROTO_TCP_SERVER)
{
if (c->mode == CM_TOP)
link_socket_mode = LS_MODE_TCP_LISTEN;
@@ -3358,7 +3372,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
do_event_set_init (c, false);
/* initialize HTTP or SOCKS proxy object at scope level 2 */
- init_proxy (c, 2);
+ init_proxy (c);
/* allocate our socket object */
if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
@@ -3689,7 +3703,7 @@ close_context (struct context *c, int sig, unsigned int flags)
if (c->sig->signal_received == SIGUSR1)
{
if ((flags & CC_USR1_TO_HUP)
- || (c->sig->hard && (flags & CC_HARD_USR1_TO_HUP)))
+ || (c->sig->source == SIG_SOURCE_HARD && (flags & CC_HARD_USR1_TO_HUP)))
c->sig->signal_received = SIGHUP;
}
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 45e0bd43..c4e834b2 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -287,13 +287,13 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
# define AF_DID_PUSH (1<<0)
# define AF_DID_RESET (1<<1)
- unsigned int action_flags = 0;
if (!recursive_level) /* don't allow recursion */
{
struct gc_arena gc = gc_new ();
struct log_entry e;
const char *out = NULL;
+ unsigned int action_flags = 0;
++recursive_level;
@@ -334,14 +334,15 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
}
}
- --recursive_level;
gc_free (&gc);
- }
- if (action_flags & AF_DID_PUSH)
- man_output_list_push_finalize (man);
- if (action_flags & AF_DID_RESET)
- man_reset_client_socket (man, true);
+ if (action_flags & AF_DID_PUSH)
+ man_output_list_push_finalize (man);
+ if (action_flags & AF_DID_RESET)
+ man_reset_client_socket (man, true);
+
+ --recursive_level;
+ }
}
/*
@@ -1460,7 +1461,7 @@ man_new_connection_post (struct management *man, const char *description)
#endif
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
description,
- print_sockaddr (&man->settings.local, &gc));
+ print_sockaddr (man->settings.local->ai_addr, &gc));
buffer_list_reset (man->connection.out);
@@ -1568,7 +1569,8 @@ man_listen (struct management *man)
#endif
{
man->connection.sd_top = create_socket_tcp (AF_INET);
- socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
+ socket_bind (man->connection.sd_top, man->settings.local,
+ AF_INET, "MANAGEMENT");
}
/*
@@ -1592,7 +1594,7 @@ man_listen (struct management *man)
else
#endif
msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
- print_sockaddr (&man->settings.local, &gc));
+ print_sockaddr (man->settings.local->ai_addr, &gc));
}
#ifdef WIN32
@@ -1635,7 +1637,7 @@ man_connect (struct management *man)
{
man->connection.sd_cli = create_socket_tcp (AF_INET);
status = openvpn_connect (man->connection.sd_cli,
- &man->settings.local,
+ man->settings.local->ai_addr,
5,
&signal_received);
}
@@ -1660,7 +1662,7 @@ man_connect (struct management *man)
#endif
msg (D_LINK_ERRORS,
"MANAGEMENT: connect to %s failed: %s",
- print_sockaddr (&man->settings.local, &gc),
+ print_sockaddr (man->settings.local->ai_addr, &gc),
strerror_ts (status, &gc));
throw_signal_soft (SIGTERM, "management-connect-failed");
goto done;
@@ -2044,7 +2046,7 @@ man_persist_close (struct man_persist *mp)
static void
man_settings_init (struct man_settings *ms,
const char *addr,
- const int port,
+ const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
@@ -2097,12 +2099,6 @@ man_settings_init (struct man_settings *ms,
else
#endif
{
- /*
- * Initialize socket address
- */
- ms->local.addr.in4.sin_family = AF_INET;
- ms->local.addr.in4.sin_addr.s_addr = 0;
- ms->local.addr.in4.sin_port = htons (port);
/*
* Run management over tunnel, or
@@ -2114,8 +2110,9 @@ man_settings_init (struct man_settings *ms,
}
else
{
- ms->local.addr.in4.sin_addr.s_addr = getaddr
- (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
+ int status = openvpn_getaddrinfo(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL,
+ addr, port, 0, NULL, AF_INET, &ms->local);
+ ASSERT(status==0);
}
}
@@ -2234,7 +2231,7 @@ management_init (void)
bool
management_open (struct management *man,
const char *addr,
- const int port,
+ const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
@@ -2600,7 +2597,13 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i
&& man->connection.state == MS_INITIAL)
{
/* listen on our local TUN/TAP IP address */
- man->settings.local.addr.in4.sin_addr.s_addr = htonl (tun_local_ip);
+ struct in_addr ia;
+ int ret;
+
+ ia.s_addr = htonl(tun_local_ip);
+ ret = openvpn_getaddrinfo(0, inet_ntoa(ia), NULL, 0, NULL,
+ AF_INET, &man->settings.local);
+ ASSERT (ret==0);
man_connection_init (man);
}
diff --git a/openvpn/src/openvpn/manage.h b/openvpn/src/openvpn/manage.h
index eec24a2e..d2790dd4 100644
--- a/openvpn/src/openvpn/manage.h
+++ b/openvpn/src/openvpn/manage.h
@@ -212,7 +212,7 @@ struct man_persist {
struct man_settings {
bool defined;
unsigned int flags; /* MF_x flags */
- struct openvpn_sockaddr local;
+ struct addrinfo* local;
#if UNIX_SOCK_SUPPORT
struct sockaddr_un local_unix;
#endif
@@ -341,7 +341,7 @@ struct management *management_init (void);
bool management_open (struct management *man,
const char *addr,
- const int port,
+ const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
diff --git a/openvpn/src/openvpn/misc.c b/openvpn/src/openvpn/misc.c
index d2882d81..fcc85526 100644
--- a/openvpn/src/openvpn/misc.c
+++ b/openvpn/src/openvpn/misc.c
@@ -53,9 +53,6 @@ const char *iproute_path = IPROUTE_PATH; /* GLOBAL */
/* contains an SSEC_x value defined in misc.h */
int script_security = SSEC_BUILT_IN; /* GLOBAL */
-/* contains SM_x value defined in misc.h */
-int script_method = SM_EXECVE; /* GLOBAL */
-
/*
* Pass tunnel endpoint and MTU parms to a user-supplied script.
* Used to execute the up/down script/plugins.
@@ -303,36 +300,25 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
#if defined(ENABLE_FEATURE_EXECVE)
if (openvpn_execve_allowed (flags))
{
- if (script_method == SM_EXECVE)
- {
- const char *cmd = a->argv[0];
- char *const *argv = a->argv;
- char *const *envp = (char *const *)make_env_array (es, true, &gc);
- pid_t pid;
-
- pid = fork ();
- if (pid == (pid_t)0) /* child side */
- {
- execve (cmd, argv, envp);
- exit (127);
- }
- else if (pid < (pid_t)0) /* fork failed */
- msg (M_ERR, "openvpn_execve: unable to fork");
- else /* parent side */
- {
- if (waitpid (pid, &ret, 0) != pid)
- ret = -1;
- }
- }
- else if (script_method == SM_SYSTEM)
- {
- ret = openvpn_system (argv_system_str (a), es, flags);
- }
- else
- {
- ASSERT (0);
- }
- }
+ const char *cmd = a->argv[0];
+ char *const *argv = a->argv;
+ char *const *envp = (char *const *)make_env_array (es, true, &gc);
+ pid_t pid;
+
+ pid = fork ();
+ if (pid == (pid_t)0) /* child side */
+ {
+ execve (cmd, argv, envp);
+ exit (127);
+ }
+ else if (pid < (pid_t)0) /* fork failed */
+ msg (M_ERR, "openvpn_execve: unable to fork");
+ else /* parent side */
+ {
+ if (waitpid (pid, &ret, 0) != pid)
+ ret = -1;
+ }
+ }
else if (!warn_shown && (script_security < SSEC_SCRIPTS))
{
msg (M_WARN, SCRIPT_SECURITY_WARNING);
@@ -353,52 +339,6 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
#endif
/*
- * Wrapper around the system() call.
- */
-int
-openvpn_system (const char *command, const struct env_set *es, unsigned int flags)
-{
-#ifdef HAVE_SYSTEM
- int ret;
-
- perf_push (PERF_SCRIPT);
-
- /*
- * add env_set to environment.
- */
- if (flags & S_SCRIPT)
- env_set_add_to_environment (es);
-
-
- /* debugging */
- dmsg (D_SCRIPT, "SYSTEM[%u] '%s'", flags, command);
- if (flags & S_SCRIPT)
- env_set_print (D_SCRIPT, es);
-
- /*
- * execute the command
- */
- ret = platform_system(command);
-
- /* debugging */
- dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
-
- /*
- * remove env_set from environment
- */
- if (flags & S_SCRIPT)
- env_set_remove_from_environment (es);
-
- perf_pop ();
- return ret;
-
-#else
- msg (M_FATAL, "Sorry but I can't execute the shell command '%s' because this operating system doesn't appear to support the system() call", command);
- return -1; /* NOTREACHED */
-#endif
-}
-
-/*
* Run execve() inside a fork(), duping stdout. Designed to replicate the semantics of popen() but
* in a safer way that doesn't require the invocation of a shell or the risks
* assocated with formatting and parsing a command line.
@@ -1056,7 +996,13 @@ hostname_randomize(const char *hostname, struct gc_arena *gc)
const char *
gen_path (const char *directory, const char *filename, struct gc_arena *gc)
{
- const char *safe_filename = string_mod_const (filename, CC_ALNUM|CC_UNDERBAR|CC_DASH|CC_DOT|CC_AT, 0, '_', gc);
+#if WIN32
+ const int CC_PATH_RESERVED = CC_LESS_THAN|CC_GREATER_THAN|CC_COLON|
+ CC_DOUBLE_QUOTE|CC_SLASH|CC_BACKSLASH|CC_PIPE|CC_QUESTION_MARK|CC_ASTERISK;
+#else
+ const int CC_PATH_RESERVED = CC_SLASH;
+#endif
+ const char *safe_filename = string_mod_const (filename, CC_PRINT, CC_PATH_RESERVED, '_', gc);
if (safe_filename
&& strcmp (safe_filename, ".")
diff --git a/openvpn/src/openvpn/misc.h b/openvpn/src/openvpn/misc.h
index b6da3f4b..183898e3 100644
--- a/openvpn/src/openvpn/misc.h
+++ b/openvpn/src/openvpn/misc.h
@@ -96,7 +96,6 @@ int openvpn_popen (const struct argv *a, const struct env_set *es);
int openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags);
bool openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message);
bool openvpn_execve_allowed (const unsigned int flags);
-int openvpn_system (const char *command, const struct env_set *es, unsigned int flags);
static inline bool
openvpn_run_script (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
@@ -322,10 +321,6 @@ extern const char *iproute_path;
#define SSEC_PW_ENV 3 /* allow calling of built-in programs and user-defined scripts that may receive a password as an environmental variable */
extern int script_security; /* GLOBAL */
-#define SM_EXECVE 0 /* call external programs with execve() or CreateProcess() */
-#define SM_SYSTEM 1 /* call external programs with system() */
-extern int script_method; /* GLOBAL */
-
/* return the next largest power of 2 */
size_t adjust_power_of_2 (size_t u);
diff --git a/openvpn/src/openvpn/mss.c b/openvpn/src/openvpn/mss.c
index 8981badc..64fd722f 100644
--- a/openvpn/src/openvpn/mss.c
+++ b/openvpn/src/openvpn/mss.c
@@ -38,8 +38,13 @@
* problems which arise from protocol
* encapsulation.
*/
+
+/*
+ * IPv4 packet: find TCP header, check flags for "SYN"
+ * if yes, hand to mss_fixup_dowork()
+ */
void
-mss_fixup (struct buffer *buf, int maxmss)
+mss_fixup_ipv4 (struct buffer *buf, int maxmss)
{
const struct openvpn_iphdr *pip;
int hlen;
@@ -69,6 +74,56 @@ mss_fixup (struct buffer *buf, int maxmss)
}
}
+/*
+ * IPv6 packet: find TCP header, check flags for "SYN"
+ * if yes, hand to mss_fixup_dowork()
+ * (IPv6 header structure is sufficiently different from IPv4...)
+ */
+void
+mss_fixup_ipv6 (struct buffer *buf, int maxmss)
+{
+ const struct openvpn_ipv6hdr *pip6;
+ struct buffer newbuf;
+
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ipv6hdr))
+ return;
+
+ verify_align_4 (buf);
+ pip6 = (struct openvpn_ipv6hdr *) BPTR (buf);
+
+ /* do we have the full IPv6 packet?
+ * "payload_len" does not include IPv6 header (+40 bytes)
+ */
+ if (BLEN (buf) != (int) ntohs(pip6->payload_len)+40 )
+ return;
+
+ /* follow header chain until we reach final header, then check for TCP
+ *
+ * An IPv6 packet could, theoretically, have a chain of multiple headers
+ * before the final header (TCP, UDP, ...), so we'd need to walk that
+ * chain (see RFC 2460 and RFC 6564 for details).
+ *
+ * In practice, "most typically used" extention headers (AH, routing,
+ * fragment, mobility) are very unlikely to be seen inside an OpenVPN
+ * tun, so for now, we only handle the case of "single next header = TCP"
+ */
+ if ( pip6->nexthdr != OPENVPN_IPPROTO_TCP )
+ return;
+
+ newbuf = *buf;
+ if ( buf_advance( &newbuf, 40 ) )
+ {
+ struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
+ if (tc->flags & OPENVPN_TCPH_SYN_MASK)
+ mss_fixup_dowork (&newbuf, (uint16_t) maxmss-20);
+ }
+}
+
+/*
+ * change TCP MSS option in SYN/SYN-ACK packets, if present
+ * this is generic for IPv4 and IPv6, as the TCP header is the same
+ */
+
void
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
{
diff --git a/openvpn/src/openvpn/mss.h b/openvpn/src/openvpn/mss.h
index 0b290c36..0d329432 100644
--- a/openvpn/src/openvpn/mss.h
+++ b/openvpn/src/openvpn/mss.h
@@ -28,7 +28,8 @@
#include "proto.h"
#include "error.h"
-void mss_fixup (struct buffer *buf, int maxmss);
+void mss_fixup_ipv4 (struct buffer *buf, int maxmss);
+void mss_fixup_ipv6 (struct buffer *buf, int maxmss);
void mss_fixup_dowork (struct buffer *buf, uint16_t maxmss);
#endif
diff --git a/openvpn/src/openvpn/multi.c b/openvpn/src/openvpn/multi.c
index 9876b80a..ab3f10cb 100644
--- a/openvpn/src/openvpn/multi.c
+++ b/openvpn/src/openvpn/multi.c
@@ -2411,13 +2411,13 @@ multi_get_queue (struct mbuf_set *ms)
if (mbuf_extract_item (ms, &item)) /* cleartext IP packet */
{
- unsigned int pipv4_flags = PIPV4_PASSTOS;
+ unsigned int pip_flags = PIPV4_PASSTOS;
set_prefix (item.instance);
item.instance->context.c2.buf = item.buffer->buf;
if (item.buffer->flags & MF_UNICAST) /* --mssfix doesn't make sense for broadcast or multicast */
- pipv4_flags |= PIPV4_MSSFIX;
- process_ipv4_header (&item.instance->context, pipv4_flags, &item.instance->context.c2.buf);
+ pip_flags |= PIP_MSSFIX;
+ process_ip_header (&item.instance->context, pip_flags, &item.instance->context.c2.buf);
encrypt_sign (&item.instance->context, true);
mbuf_free_buf (item.buffer);
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 47aaffcb..dabc7577 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -167,8 +167,8 @@ static const char usage_message[] =
"--ipchange cmd : Run command cmd on remote ip address initial\n"
" setting or change -- execute as: cmd ip-address port#\n"
"--port port : TCP/UDP port # for both local and remote.\n"
- "--lport port : TCP/UDP port # for local (default=%d). Implies --bind.\n"
- "--rport port : TCP/UDP port # for remote (default=%d).\n"
+ "--lport port : TCP/UDP port # for local (default=%s). Implies --bind.\n"
+ "--rport port : TCP/UDP port # for remote (default=%s).\n"
"--bind : Bind to local address and port. (This is the default unless\n"
" --proto tcp-client"
#ifdef ENABLE_HTTP_PROXY
@@ -248,7 +248,7 @@ static const char usage_message[] =
"--setenv name value : Set a custom environmental variable to pass to script.\n"
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
" directives for future OpenVPN versions to be ignored.\n"
- "--script-security level mode : mode='execve' (default) or 'system', level=\n"
+ "--script-security level: Where level can be:\n"
" 0 -- strictly no calling of external programs\n"
" 1 -- (default) only call built-ins such as ifconfig\n"
" 2 -- allow calling of built-ins and scripts\n"
@@ -767,10 +767,11 @@ init_options (struct options *o, const bool init_gc)
}
o->mode = MODE_POINT_TO_POINT;
o->topology = TOP_NET30;
- o->ce.proto = PROTO_UDPv4;
+ o->ce.proto = PROTO_UDP;
+ o->ce.af = AF_UNSPEC;
o->ce.connect_retry_seconds = 5;
o->ce.connect_timeout = 10;
- o->ce.connect_retry_max = 0;
+ o->connect_retry_max = 0;
o->ce.local_port = o->ce.remote_port = OPENVPN_PORT;
o->verbosity = 1;
o->status_file_update_freq = 60;
@@ -897,24 +898,24 @@ setenv_connection_entry (struct env_set *es,
const struct connection_entry *e,
const int i)
{
- setenv_str_i (es, "proto", proto2ascii (e->proto, false), i);
+ setenv_str_i (es, "proto", proto2ascii (e->proto, e->af, false), i);
setenv_str_i (es, "local", e->local, i);
- setenv_int_i (es, "local_port", e->local_port, i);
+ setenv_str_i (es, "local_port", e->local_port, i);
setenv_str_i (es, "remote", e->remote, i);
- setenv_int_i (es, "remote_port", e->remote_port, i);
+ setenv_str_i (es, "remote_port", e->remote_port, i);
#ifdef ENABLE_HTTP_PROXY
if (e->http_proxy_options)
{
setenv_str_i (es, "http_proxy_server", e->http_proxy_options->server, i);
- setenv_int_i (es, "http_proxy_port", e->http_proxy_options->port, i);
+ setenv_str_i (es, "http_proxy_port", e->http_proxy_options->port, i);
}
#endif
#ifdef ENABLE_SOCKS
if (e->socks_proxy_server)
{
setenv_str_i (es, "socks_proxy_server", e->socks_proxy_server, i);
- setenv_int_i (es, "socks_proxy_port", e->socks_proxy_port, i);
+ setenv_str_i (es, "socks_proxy_port", e->socks_proxy_port, i);
}
#endif
}
@@ -1216,7 +1217,7 @@ show_p2mp_parms (const struct options *o)
SHOW_BOOL (auth_user_pass_verify_script_via_file);
#if PORT_SHARE
SHOW_STR (port_share_host);
- SHOW_INT (port_share_port);
+ SHOW_STR (port_share_port);
#endif
#endif /* P2MP_SERVER */
@@ -1287,7 +1288,7 @@ show_http_proxy_options (const struct http_proxy_options *o)
{
msg (D_SHOW_PARMS, "BEGIN http_proxy");
SHOW_STR (server);
- SHOW_INT (port);
+ SHOW_STR (port);
SHOW_STR (auth_method_string);
SHOW_STR (auth_file);
SHOW_BOOL (retry);
@@ -1338,17 +1339,16 @@ cnol_check_alloc (struct options *options)
static void
show_connection_entry (const struct connection_entry *o)
{
- msg (D_SHOW_PARMS, " proto = %s", proto2ascii (o->proto, false));
+ msg (D_SHOW_PARMS, " proto = %s", proto2ascii (o->proto, o->af, false));
SHOW_STR (local);
- SHOW_INT (local_port);
+ SHOW_STR (local_port);
SHOW_STR (remote);
- SHOW_INT (remote_port);
+ SHOW_STR (remote_port);
SHOW_BOOL (remote_float);
SHOW_BOOL (bind_defined);
SHOW_BOOL (bind_local);
SHOW_INT (connect_retry_seconds);
SHOW_INT (connect_timeout);
- SHOW_INT (connect_retry_max);
#ifdef ENABLE_HTTP_PROXY
if (o->http_proxy_options)
@@ -1356,7 +1356,7 @@ show_connection_entry (const struct connection_entry *o)
#endif
#ifdef ENABLE_SOCKS
SHOW_STR (socks_proxy_server);
- SHOW_INT (socks_proxy_port);
+ SHOW_STR (socks_proxy_port);
SHOW_BOOL (socks_proxy_retry);
#endif
SHOW_INT (tun_mtu);
@@ -1425,6 +1425,7 @@ show_settings (const struct options *o)
#endif
#endif
+ SHOW_INT (connect_retry_max);
show_connection_entries (o);
SHOW_BOOL (remote_random);
@@ -1536,7 +1537,7 @@ show_settings (const struct options *o)
#ifdef ENABLE_MANAGEMENT
SHOW_STR (management_addr);
- SHOW_INT (management_port);
+ SHOW_STR (management_port);
SHOW_STR (management_user_pass);
SHOW_INT (management_log_history_cache);
SHOW_INT (management_echo_buffer_size);
@@ -1683,17 +1684,9 @@ parse_http_proxy_override (const char *server,
if (server && port)
{
struct http_proxy_options *ho;
- const int int_port = atoi(port);
-
- if (!legal_ipv4_port (int_port))
- {
- msg (msglevel, "Bad http-proxy port number: %s", port);
- return NULL;
- }
-
ALLOC_OBJ_CLEAR_GC (ho, struct http_proxy_options, gc);
ho->server = string_alloc(server, gc);
- ho->port = int_port;
+ ho->port = port;
ho->retry = true;
ho->timeout = 5;
if (flags && !strcmp(flags, "nct"))
@@ -1712,32 +1705,31 @@ void
options_postprocess_http_proxy_override (struct options *o)
{
const struct connection_list *l = o->connection_list;
- if (l)
+ int i;
+ bool succeed = false;
+ for (i = 0; i < l->len; ++i)
+ {
+ struct connection_entry *ce = l->array[i];
+ if (ce->proto == PROTO_TCP_CLIENT || ce->proto == PROTO_TCP)
+ {
+ ce->http_proxy_options = o->http_proxy_override;
+ succeed = true;
+ }
+ }
+ if (succeed)
{
- int i;
- bool succeed = false;
for (i = 0; i < l->len; ++i)
- {
- struct connection_entry *ce = l->array[i];
- if (ce->proto == PROTO_TCPv4_CLIENT || ce->proto == PROTO_TCPv4)
- {
- ce->http_proxy_options = o->http_proxy_override;
- succeed = true;
- }
- }
- if (succeed)
- {
- for (i = 0; i < l->len; ++i)
- {
- struct connection_entry *ce = l->array[i];
- if (ce->proto == PROTO_UDPv4)
- {
- ce->flags |= CE_DISABLED;
- }
- }
- }
- else
- msg (M_WARN, "Note: option http-proxy-override ignored because no TCP-based connection profiles are defined");
+ {
+ struct connection_entry *ce = l->array[i];
+ if (ce->proto == PROTO_UDP)
+ {
+ ce->flags |= CE_DISABLED;
+ }
+ }
+ }
+ else
+ {
+ msg (M_WARN, "Note: option http-proxy-override ignored because no TCP-based connection profiles are defined");
}
}
@@ -1796,10 +1788,12 @@ connection_entry_load_re (struct connection_entry *ce, const struct remote_entry
{
if (re->remote)
ce->remote = re->remote;
- if (re->remote_port >= 0)
+ if (re->remote_port)
ce->remote_port = re->remote_port;
if (re->proto >= 0)
ce->proto = re->proto;
+ if (re->af > 0)
+ ce->af = re->af;
}
static void
@@ -1829,7 +1823,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
* If "proto tcp" is specified, make sure we know whether it is
* tcp-client or tcp-server.
*/
- if (ce->proto == PROTO_TCPv4)
+ if (ce->proto == PROTO_TCP)
msg (M_USAGE, "--proto tcp is ambiguous in this context. Please specify --proto tcp-server or --proto tcp-client");
/*
@@ -1842,10 +1836,10 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (options->inetd && (ce->local || ce->remote))
msg (M_USAGE, "--local or --remote cannot be used with --inetd");
- if (options->inetd && ce->proto == PROTO_TCPv4_CLIENT)
+ if (options->inetd && ce->proto == PROTO_TCP_CLIENT)
msg (M_USAGE, "--proto tcp-client cannot be used with --inetd");
- if (options->inetd == INETD_NOWAIT && ce->proto != PROTO_TCPv4_SERVER)
+ if (options->inetd == INETD_NOWAIT && ce->proto != PROTO_TCP_SERVER)
msg (M_USAGE, "--inetd nowait can only be used with --proto tcp-server");
if (options->inetd == INETD_NOWAIT
@@ -1866,13 +1860,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
* Sanity check on TCP mode options
*/
- if (ce->connect_retry_defined && ce->proto != PROTO_TCPv4_CLIENT
- && ce->proto != PROTO_TCPv6_CLIENT)
+ if (ce->connect_retry_defined && ce->proto != PROTO_TCP_CLIENT)
msg (M_USAGE, "--connect-retry doesn't make sense unless also used with "
"--proto tcp-client or tcp6-client");
- if (ce->connect_timeout_defined && ce->proto != PROTO_TCPv4_CLIENT
- && ce->proto != PROTO_TCPv6_CLIENT)
+ if (ce->connect_timeout_defined && ce->proto != PROTO_TCP_CLIENT)
msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with "
"--proto tcp-client or tcp6-client");
@@ -1898,7 +1890,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (proto_is_net(ce->proto)
&& string_defined_equal (ce->local, ce->remote)
- && ce->local_port == ce->remote_port)
+ && string_defined_equal (ce->local_port, ce->remote_port))
msg (M_USAGE, "--remote and --local addresses are the same");
if (string_defined_equal (ce->remote, options->ifconfig_local)
@@ -1971,12 +1963,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
msg (M_USAGE, "--explicit-exit-notify can only be used with --proto udp");
#endif
- if (!ce->remote && (ce->proto == PROTO_TCPv4_CLIENT
- || ce->proto == PROTO_TCPv6_CLIENT))
+ if (!ce->remote && ce->proto == PROTO_TCP_CLIENT)
msg (M_USAGE, "--remote MUST be used in TCP Client mode");
#ifdef ENABLE_HTTP_PROXY
- if ((ce->http_proxy_options) && ce->proto != PROTO_TCPv4_CLIENT)
+ if ((ce->http_proxy_options) && ce->proto != PROTO_TCP_CLIENT)
msg (M_USAGE, "--http-proxy MUST be used in TCP Client mode (i.e. --proto tcp-client)");
#endif
@@ -1986,12 +1977,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#endif
#ifdef ENABLE_SOCKS
- if (ce->socks_proxy_server && ce->proto == PROTO_TCPv4_SERVER)
+ if (ce->socks_proxy_server && ce->proto == PROTO_TCP_SERVER)
msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode");
#endif
- if ((ce->proto == PROTO_TCPv4_SERVER || ce->proto == PROTO_TCPv6_SERVER)
- && connection_list_defined (options))
+ if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1))
msg (M_USAGE, "TCP server mode allows at most one --remote address");
#if P2MP_SERVER
@@ -2005,13 +1995,12 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
msg (M_USAGE, "--mode server only works with --dev tun or --dev tap");
if (options->pull)
msg (M_USAGE, "--pull cannot be used with --mode server");
- if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCPv4_SERVER
- || ce->proto == PROTO_TCPv6_SERVER))
+ if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCP_SERVER))
msg (M_USAGE, "--mode server currently only supports "
"--proto udp or --proto tcp-server or proto tcp6-server");
#if PORT_SHARE
if ((options->port_share_host || options->port_share_port) &&
- (ce->proto != PROTO_TCPv4_SERVER && ce->proto != PROTO_TCPv6_SERVER))
+ (ce->proto != PROTO_TCP_SERVER))
msg (M_USAGE, "--port-share only works in TCP server mode "
"(--proto tcp-server or tcp6-server)");
#endif
@@ -2041,8 +2030,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
msg (M_USAGE, "--inetd cannot be used with --mode server");
if (options->ipchange)
msg (M_USAGE, "--ipchange cannot be used with --mode server (use --client-connect instead)");
- if (!(proto_is_dgram(ce->proto) || ce->proto == PROTO_TCPv4_SERVER
- || ce->proto == PROTO_TCPv6_SERVER))
+ if (!(proto_is_dgram(ce->proto) || ce->proto == PROTO_TCP_SERVER))
msg (M_USAGE, "--mode server currently only supports "
"--proto udp or --proto tcp-server or --proto tcp6-server");
if (!proto_is_udp(ce->proto) && (options->cf_max || options->cf_per))
@@ -2194,13 +2182,15 @@ 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) && options->priv_key_file)
- msg (M_USAGE, "--key and --management-external-key are mutually exclusive");
+ {
+ msg (M_USAGE, "--key and --management-external-key are mutually exclusive");
+ }
+ else
#endif
-
- if (options->cryptoapi_cert)
+#ifdef ENABLE_CRYPTOAPI
+ if (options->cryptoapi_cert)
{
if ((!(options->ca_file)) && (!(options->ca_path)))
msg(M_USAGE, "You must define CA file (--ca) or CA path (--capath)");
@@ -2274,7 +2264,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
{
notnull (options->cert_file, "certificate file (--cert) or PKCS#12 file (--pkcs12)");
#ifdef MANAGMENT_EXTERNAL_KEY
- if (!options->management_flags & MF_EXTERNAL_KEY)
+ if (!(options->management_flags & MF_EXTERNAL_KEY))
#endif
notnull (options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)");
}
@@ -2350,35 +2340,33 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
#if P2MP_SERVER
if (o->server_defined || o->server_bridge_defined || o->server_bridge_proxy_dhcp)
{
- if (ce->proto == PROTO_TCPv4)
- ce->proto = PROTO_TCPv4_SERVER;
+ if (ce->proto == PROTO_TCP)
+ ce->proto = PROTO_TCP_SERVER;
}
#endif
#if P2MP
if (o->client)
{
- if (ce->proto == PROTO_TCPv4)
- ce->proto = PROTO_TCPv4_CLIENT;
- else if (ce->proto == PROTO_TCPv6)
- ce->proto = PROTO_TCPv6_CLIENT;
+ if (ce->proto == PROTO_TCP)
+ ce->proto = PROTO_TCP_CLIENT;
}
#endif
- if (ce->proto == PROTO_TCPv4_CLIENT && !ce->local && !ce->local_port_defined && !ce->bind_defined)
+ if (ce->proto == PROTO_TCP_CLIENT && !ce->local && !ce->local_port_defined && !ce->bind_defined)
ce->bind_local = false;
#ifdef ENABLE_SOCKS
- if (ce->proto == PROTO_UDPv4 && ce->socks_proxy_server && !ce->local && !ce->local_port_defined && !ce->bind_defined)
+ if (ce->proto == PROTO_UDP && ce->socks_proxy_server && !ce->local && !ce->local_port_defined && !ce->bind_defined)
ce->bind_local = false;
#endif
if (!ce->bind_local)
- ce->local_port = 0;
+ ce->local_port = NULL;
/* if protocol forcing is enabled, disable all protocols except for the forced one */
- if (o->proto_force >= 0 && proto_is_tcp(o->proto_force) != proto_is_tcp(ce->proto))
+ if (o->proto_force >= 0 && o->proto_force != ce->proto)
ce->flags |= CE_DISABLED;
-
+
/*
* If --mssfix is supplied without a parameter, default
* it to --fragment value, if --fragment is specified.
@@ -2488,48 +2476,33 @@ options_postprocess_mutate (struct options *o)
if (o->remote_list && !o->connection_list)
{
/*
- * For compatibility with 2.0.x, map multiple --remote options
- * into connection list (connection lists added in 2.1).
+ * Convert remotes into connection list
*/
- if (o->remote_list->len > 1 || o->force_connection_list)
- {
- const struct remote_list *rl = o->remote_list;
- int i;
- for (i = 0; i < rl->len; ++i)
- {
- const struct remote_entry *re = rl->array[i];
- struct connection_entry ce = o->ce;
- struct connection_entry *ace;
-
- ASSERT (re->remote);
- connection_entry_load_re (&ce, re);
- ace = alloc_connection_entry (o, M_USAGE);
- ASSERT (ace);
- *ace = ce;
- }
- }
- else if (o->remote_list->len == 1) /* one --remote option specified */
- {
- connection_entry_load_re (&o->ce, o->remote_list->array[0]);
- }
- else
- {
- ASSERT (0);
- }
- }
- if (o->connection_list)
- {
+ const struct remote_list *rl = o->remote_list;
int i;
- for (i = 0; i < o->connection_list->len; ++i)
- options_postprocess_mutate_ce (o, o->connection_list->array[i]);
+ for (i = 0; i < rl->len; ++i)
+ {
+ const struct remote_entry *re = rl->array[i];
+ struct connection_entry ce = o->ce;
+ struct connection_entry *ace;
+
+ ASSERT (re->remote);
+ connection_entry_load_re (&ce, re);
+ ace = alloc_connection_entry (o, M_USAGE);
+ ASSERT (ace);
+ *ace = ce;
+ }
+ }
+ ASSERT (o->connection_list);
+ int i;
+ for (i = 0; i < o->connection_list->len; ++i)
+ options_postprocess_mutate_ce (o, o->connection_list->array[i]);
+
#if HTTP_PROXY_OVERRIDE
- if (o->http_proxy_override)
+ if (o->http_proxy_override)
options_postprocess_http_proxy_override(o);
#endif
- }
- else
- options_postprocess_mutate_ce (o, &o->ce);
#if P2MP
/*
@@ -2666,7 +2639,7 @@ options_postprocess_filechecks (struct options *options)
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK,
"--extra-certs");
#ifdef MANAGMENT_EXTERNAL_KEY
- if(!options->management_flags & MF_EXTERNAL_KEY)
+ if(!(options->management_flags & MF_EXTERNAL_KEY))
#endif
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK,
"--key");
@@ -2916,7 +2889,7 @@ options_string (const struct options *o,
buf_printf (&out, ",dev-type %s", dev_type_string (o->dev, o->dev_type));
buf_printf (&out, ",link-mtu %d", EXPANDED_SIZE (frame));
buf_printf (&out, ",tun-mtu %d", PAYLOAD_SIZE (frame));
- buf_printf (&out, ",proto %s", proto2ascii (proto_remote (o->ce.proto, remote), true));
+ buf_printf (&out, ",proto %s", proto2ascii (proto_remote (o->ce.proto, remote),o->ce.af, true));
if (o->tun_ipv6)
buf_printf (&out, ",tun-ipv6");
@@ -4096,8 +4069,6 @@ add_option (struct options *options,
#ifdef ENABLE_MANAGEMENT
else if (streq (p[0], "management") && p[1] && p[2])
{
- int port = 0;
-
VERIFY_PERMISSION (OPT_P_GENERAL);
if (streq (p[2], "unix"))
{
@@ -4108,18 +4079,9 @@ add_option (struct options *options,
goto err;
#endif
}
- else
- {
- port = atoi (p[2]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "port number associated with --management directive is out of range");
- goto err;
- }
- }
options->management_addr = p[1];
- options->management_port = port;
+ options->management_port = p[2];
if (p[3])
{
options->management_user_pass = p[3];
@@ -4149,7 +4111,6 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL);
options->management_flags |= MF_QUERY_PROXY;
- options->force_connection_list = true;
}
else if (streq (p[0], "management-hold"))
{
@@ -4378,11 +4339,6 @@ add_option (struct options *options,
uninit_options (&sub);
}
}
- else if (streq (p[0], "remote-ip-hint") && p[1])
- {
- VERIFY_PERMISSION (OPT_P_GENERAL);
- options->remote_ip_hint = p[1];
- }
#if HTTP_PROXY_OVERRIDE
else if (streq (p[0], "http-proxy-override") && p[1] && p[2])
{
@@ -4390,35 +4346,31 @@ add_option (struct options *options,
options->http_proxy_override = parse_http_proxy_override(p[1], p[2], p[3], msglevel, &options->gc);
if (!options->http_proxy_override)
goto err;
- options->force_connection_list = true;
}
#endif
else if (streq (p[0], "remote") && p[1])
{
struct remote_entry re;
- re.remote = NULL;
- re.remote_port = re.proto = -1;
+ re.remote = re.remote_port= NULL;
+ re.proto = -1;
+ re.af=0;
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
re.remote = p[1];
if (p[2])
{
- const int port = atoi (p[2]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "remote: port number associated with host %s is out of range", p[1]);
- goto err;
- }
- re.remote_port = port;
+ re.remote_port = p[2];
if (p[3])
{
const int proto = ascii2proto (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;
}
}
if (permission_mask & OPT_P_GENERAL)
@@ -4456,7 +4408,7 @@ add_option (struct options *options,
else if (streq (p[0], "connect-retry-max") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
- options->ce.connect_retry_max = positive_atoi (p[1]);
+ options->connect_retry_max = positive_atoi (p[1]);
}
else if (streq (p[0], "ipchange") && p[1])
{
@@ -4811,43 +4763,19 @@ add_option (struct options *options,
}
else if (streq (p[0], "port") && p[1])
{
- int port;
-
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
- port = atoi (p[1]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "Bad port number: %s", p[1]);
- goto err;
- }
- options->ce.local_port = options->ce.remote_port = port;
+ options->ce.local_port = options->ce.remote_port = p[1];
}
else if (streq (p[0], "lport") && p[1])
{
- int port;
-
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
- port = atoi (p[1]);
- if ((port != 0) && !legal_ipv4_port (port))
- {
- msg (msglevel, "Bad local port number: %s", p[1]);
- goto err;
- }
options->ce.local_port_defined = true;
- options->ce.local_port = port;
+ options->ce.local_port = p[1];
}
else if (streq (p[0], "rport") && p[1])
{
- int port;
-
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
- port = atoi (p[1]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "Bad remote port number: %s", p[1]);
- goto err;
- }
- options->ce.remote_port = port;
+ options->ce.remote_port = p[1];
}
else if (streq (p[0], "bind"))
{
@@ -4874,8 +4802,10 @@ add_option (struct options *options,
else if (streq (p[0], "proto") && p[1])
{
int proto;
+ sa_family_t af;
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
proto = ascii2proto (p[1]);
+ af = ascii2af(p[1]);
if (proto < 0)
{
msg (msglevel, "Bad protocol: '%s'. Allowed protocols with --proto option: %s",
@@ -4884,6 +4814,7 @@ add_option (struct options *options,
goto err;
}
options->ce.proto = proto;
+ options->ce.af = af;
}
else if (streq (p[0], "proto-force") && p[1])
{
@@ -4896,7 +4827,6 @@ add_option (struct options *options,
goto err;
}
options->proto_force = proto_force;
- options->force_connection_list = true;
}
#ifdef ENABLE_HTTP_PROXY
else if (streq (p[0], "http-proxy") && p[1])
@@ -4906,23 +4836,16 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
{
- int port;
if (!p[2])
{
msg (msglevel, "http-proxy port number not defined");
goto err;
}
- port = atoi (p[2]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "Bad http-proxy port number: %s", p[2]);
- goto err;
- }
ho = init_http_proxy_options_once (&options->ce.http_proxy_options, &options->gc);
ho->server = p[1];
- ho->port = port;
+ ho->port = p[2];
}
if (p[3])
@@ -4992,19 +4915,12 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
if (p[2])
- {
- int port;
- port = atoi (p[2]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "Bad socks-proxy port number: %s", p[2]);
- goto err;
- }
- options->ce.socks_proxy_port = port;
+ {
+ options->ce.socks_proxy_port = p[2];
}
else
{
- options->ce.socks_proxy_port = 1080;
+ options->ce.socks_proxy_port = "1080";
}
options->ce.socks_proxy_server = p[1];
options->ce.socks_proxy_authfile = p[3]; /* might be NULL */
@@ -5141,6 +5057,11 @@ add_option (struct options *options,
msg (msglevel, "--max-routes parameter is out of range");
goto err;
}
+ if (options->routes || options->routes_ipv6)
+ {
+ msg (msglevel, "--max-routes must to be specifed before any route/route-ipv6/redirect-gateway option");
+ goto err;
+ }
options->max_routes = max_routes;
}
else if (streq (p[0], "route-gateway") && p[1])
@@ -5293,20 +5214,6 @@ add_option (struct options *options,
{
VERIFY_PERMISSION (OPT_P_GENERAL);
script_security = atoi (p[1]);
- if (p[2])
- {
- if (streq (p[2], "execve"))
- script_method = SM_EXECVE;
- else if (streq (p[2], "system"))
- script_method = SM_SYSTEM;
- else
- {
- msg (msglevel, "unknown --script-security method: %s", p[2]);
- goto err;
- }
- }
- else
- script_method = SM_EXECVE;
}
else if (streq (p[0], "mssfix"))
{
@@ -5652,18 +5559,9 @@ add_option (struct options *options,
#if PORT_SHARE
else if (streq (p[0], "port-share") && p[1] && p[2])
{
- int port;
-
VERIFY_PERMISSION (OPT_P_GENERAL);
- port = atoi (p[2]);
- if (!legal_ipv4_port (port))
- {
- msg (msglevel, "port number associated with --port-share directive is out of range");
- goto err;
- }
-
options->port_share_host = p[1];
- options->port_share_port = port;
+ options->port_share_port = p[2];
options->port_share_journal_dir = p[3];
}
#endif
diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h
index 306520b0..62b1cbf3 100644
--- a/openvpn/src/openvpn/options.h
+++ b/openvpn/src/openvpn/options.h
@@ -87,9 +87,10 @@ struct options_pre_pull
struct connection_entry
{
int proto;
- int local_port;
+ sa_family_t af;
+ const char* local_port;
bool local_port_defined;
- int remote_port;
+ const char* remote_port;
const char *local;
const char *remote;
bool remote_float;
@@ -97,7 +98,6 @@ struct connection_entry
bool bind_local;
int connect_retry_seconds;
bool connect_retry_defined;
- int connect_retry_max;
int connect_timeout;
bool connect_timeout_defined;
#ifdef ENABLE_HTTP_PROXY
@@ -105,7 +105,7 @@ struct connection_entry
#endif
#ifdef ENABLE_SOCKS
const char *socks_proxy_server;
- int socks_proxy_port;
+ const char *socks_proxy_port;
const char *socks_proxy_authfile;
bool socks_proxy_retry;
#endif
@@ -143,8 +143,9 @@ struct connection_entry
struct remote_entry
{
const char *remote;
- int remote_port;
+ const char *remote_port;
int proto;
+ sa_family_t af;
};
#define CONNECTION_LIST_SIZE 64
@@ -154,7 +155,6 @@ struct connection_list
int len;
int current;
int n_cycles;
- bool no_advance;
struct connection_entry *array[CONNECTION_LIST_SIZE];
};
@@ -168,6 +168,8 @@ struct remote_host_store
{
# define RH_HOST_LEN 80
char host[RH_HOST_LEN];
+#define RH_PORT_LEN 20
+ char port[RH_PORT_LEN];
};
/* Command line options */
@@ -203,11 +205,15 @@ struct options
#endif
/* Networking parms */
+ int connect_retry_max;
struct connection_entry ce;
- char *remote_ip_hint;
struct connection_list *connection_list;
+
struct remote_list *remote_list;
- bool force_connection_list;
+ /* Do not advanced the connection or remote addr list*/
+ bool no_advance;
+ /* Counts the number of unsuccessful connection attempts */
+ unsigned int unsuccessful_attempts;
#if HTTP_PROXY_OVERRIDE
struct http_proxy_options *http_proxy_override;
@@ -354,7 +360,7 @@ struct options
#ifdef ENABLE_MANAGEMENT
const char *management_addr;
- int management_port;
+ const char *management_port;
const char *management_user_pass;
int management_log_history_cache;
int management_echo_buffer_size;
@@ -449,7 +455,7 @@ struct options
bool auth_user_pass_verify_script_via_file;
#if PORT_SHARE
char *port_share_host;
- int port_share_port;
+ char *port_share_port;
const char *port_share_journal_dir;
#endif
#endif
@@ -769,20 +775,5 @@ bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
unsigned int * netbits, char ** printable_ipv6,
int msglevel );
-/*
- * inline functions
- */
-static inline bool
-connection_list_defined (const struct options *o)
-{
- return o->connection_list != NULL;
-}
-
-static inline void
-connection_list_set_no_advance (struct options *o)
-{
- if (o->connection_list)
- o->connection_list->no_advance = true;
-}
#endif
diff --git a/openvpn/src/openvpn/pf.c b/openvpn/src/openvpn/pf.c
index 3c468019..aafe9ff0 100644
--- a/openvpn/src/openvpn/pf.c
+++ b/openvpn/src/openvpn/pf.c
@@ -606,7 +606,6 @@ pf_destroy_context (struct pf_context *pfc)
if (pfc->filename)
{
platform_unlink (pfc->filename);
- free (pfc->filename);
}
#endif
if (pfc->pfs)
diff --git a/openvpn/src/openvpn/pkcs11.c b/openvpn/src/openvpn/pkcs11.c
index 645f1f48..3a15ef68 100644
--- a/openvpn/src/openvpn/pkcs11.c
+++ b/openvpn/src/openvpn/pkcs11.c
@@ -887,7 +887,7 @@ show_pkcs11_ids (
(dn = pkcs11_certificate_dn (
certificate,
&gc
- ))
+ )) == NULL
) {
goto cleanup1;
}
diff --git a/openvpn/src/openvpn/platform.c b/openvpn/src/openvpn/platform.c
index c79f6807..e79de7a7 100644
--- a/openvpn/src/openvpn/platform.c
+++ b/openvpn/src/openvpn/platform.c
@@ -205,7 +205,7 @@ platform_chdir (const char* dir)
}
/*
- * convert system() return into a success/failure value
+ * convert execve() return into a success/failure value
*/
bool
platform_system_ok (int stat)
@@ -217,19 +217,6 @@ platform_system_ok (int stat)
#endif
}
-/*
- * did system() call execute the given command?
- */
-bool
-platform_system_executed (int stat)
-{
-#ifdef WIN32
- return stat != -1;
-#else
- return stat != -1 && WEXITSTATUS (stat) != 127;
-#endif
-}
-
int
platform_access (const char *path, int mode)
{
@@ -288,18 +275,6 @@ platform_unlink (const char *filename)
#endif
}
-int platform_system(const char *command) {
- int ret;
-#ifdef WIN32
- struct gc_arena gc = gc_new ();
- ret = _wsystem (wide_string (command, &gc));
- gc_free (&gc);
-#else
- ret = system (command);
-#endif
- return ret;
-}
-
int platform_putenv(char *string)
{
int status;
diff --git a/openvpn/src/openvpn/platform.h b/openvpn/src/openvpn/platform.h
index 7bd20671..7c0a4d72 100644
--- a/openvpn/src/openvpn/platform.h
+++ b/openvpn/src/openvpn/platform.h
@@ -113,10 +113,8 @@ void platform_mlockall (bool print_msg); /* Disable paging */
int platform_chdir (const char* dir);
-/* interpret the status code returned by system()/execve() */
+/* interpret the status code returned by execve() */
bool platform_system_ok (int stat);
-bool platform_system_executed (int stat);
-int platform_system(const char *command);
int platform_access (const char *path, int mode);
diff --git a/openvpn/src/openvpn/plugin.c b/openvpn/src/openvpn/plugin.c
index d785daec..83f79e4f 100644
--- a/openvpn/src/openvpn/plugin.c
+++ b/openvpn/src/openvpn/plugin.c
@@ -98,7 +98,9 @@ plugin_type_name (const int type)
case OPENVPN_PLUGIN_TLS_FINAL:
return "PLUGIN_TLS_FINAL";
case OPENVPN_PLUGIN_ENABLE_PF:
- return "OPENVPN_PLUGIN_ENABLE_PF";
+ return "PLUGIN_ENABLE_PF";
+ case OPENVPN_PLUGIN_ROUTE_PREDOWN:
+ return "PLUGIN_ROUTE_PREDOWN";
default:
return "PLUGIN_???";
}
@@ -376,10 +378,10 @@ plugin_open_item (struct plugin *p,
struct openvpn_plugin_args_open_return retargs;
CLEAR(retargs);
+ retargs.return_list = retlist;
if ((*p->open3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs) == OPENVPN_PLUGIN_FUNC_SUCCESS) {
p->plugin_type_mask = retargs.type_mask;
p->plugin_handle = retargs.handle;
- retlist = retargs.return_list;
} else {
p->plugin_handle = NULL;
}
@@ -458,8 +460,8 @@ plugin_call_item (const struct plugin *p,
struct openvpn_plugin_args_func_return retargs;
CLEAR(retargs);
+ retargs.return_list = retlist;
status = (*p->func3)(OPENVPN_PLUGINv3_STRUCTVER, &args, &retargs);
- retlist = retargs.return_list;
} else if (p->func2)
status = (*p->func2)(p->plugin_handle, type, (const char **)a.argv, envp, per_client_context, retlist);
else if (p->func1)
diff --git a/openvpn/src/openvpn/proto.c b/openvpn/src/openvpn/proto.c
index 2cf8314b..b437f1ad 100644
--- a/openvpn/src/openvpn/proto.c
+++ b/openvpn/src/openvpn/proto.c
@@ -36,11 +36,12 @@
#include "memdbg.h"
/*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv<X>, return true and increment
* buffer offset to start of IP header.
*/
+static
bool
-is_ipv4 (int tunnel_type, struct buffer *buf)
+is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver )
{
int offset;
const struct openvpn_iphdr *ih;
@@ -68,12 +69,24 @@ is_ipv4 (int tunnel_type, struct buffer *buf)
ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset);
- if (OPENVPN_IPH_GET_VER (ih->version_len) == 4)
+ /* IP version is stored in the same bits for IPv4 or IPv6 header */
+ if (OPENVPN_IPH_GET_VER (ih->version_len) == ip_ver)
return buf_advance (buf, offset);
else
return false;
}
+bool
+is_ipv4 (int tunnel_type, struct buffer *buf)
+{
+ return is_ipv_X( tunnel_type, buf, 4 );
+}
+bool
+is_ipv6 (int tunnel_type, struct buffer *buf)
+{
+ return is_ipv_X( tunnel_type, buf, 6 );
+}
+
#ifdef PACKET_TRUNCATION_CHECK
void
diff --git a/openvpn/src/openvpn/proto.h b/openvpn/src/openvpn/proto.h
index 8cd4edec..f91e787e 100644
--- a/openvpn/src/openvpn/proto.h
+++ b/openvpn/src/openvpn/proto.h
@@ -219,10 +219,11 @@ struct ip_tcp_udp_hdr {
- sizeof(struct openvpn_tcphdr))
/*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv4 or IPv6, return true and increment
* buffer offset to start of IP header.
*/
bool is_ipv4 (int tunnel_type, struct buffer *buf);
+bool is_ipv6 (int tunnel_type, struct buffer *buf);
#ifdef PACKET_TRUNCATION_CHECK
void ipv4_packet_size_verify (const uint8_t *data,
diff --git a/openvpn/src/openvpn/proxy.c b/openvpn/src/openvpn/proxy.c
index 363d8a73..17748504 100644
--- a/openvpn/src/openvpn/proxy.c
+++ b/openvpn/src/openvpn/proxy.c
@@ -444,7 +444,7 @@ http_proxy_new (const struct http_proxy_options *o)
if (!o || !o->server)
msg (M_FATAL, "HTTP_PROXY: server not specified");
- ASSERT (legal_ipv4_port (o->port));
+ ASSERT ( o->port);
ALLOC_OBJ_CLEAR (p, struct http_proxy_info);
p->options = *o;
@@ -493,7 +493,7 @@ bool
establish_http_proxy_passthru (struct http_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */
const char *host, /* openvpn server remote */
- const int port, /* openvpn server port */
+ const char *port, /* openvpn server port */
struct buffer *lookahead,
volatile int *signal_received)
{
@@ -521,7 +521,7 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
else
{
/* format HTTP CONNECT message */
- openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
+ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
host,
port,
p->options.http_version);
@@ -642,7 +642,7 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
/* now send the phase 3 reply */
/* format HTTP CONNECT message */
- openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
+ openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
host,
port,
p->options.http_version);
@@ -730,7 +730,7 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
/* build the digest response */
- openvpn_snprintf (uri, sizeof(uri), "%s:%d",
+ openvpn_snprintf (uri, sizeof(uri), "%s:%s",
host,
port);
diff --git a/openvpn/src/openvpn/proxy.h b/openvpn/src/openvpn/proxy.h
index 5e476f16..9d75e063 100644
--- a/openvpn/src/openvpn/proxy.h
+++ b/openvpn/src/openvpn/proxy.h
@@ -40,7 +40,7 @@
struct http_proxy_options {
const char *server;
- int port;
+ const char *port;
bool retry;
int timeout;
@@ -57,7 +57,7 @@ struct http_proxy_options {
struct http_proxy_options_simple {
const char *server;
- int port;
+ const char *port;
int auth_retry;
};
@@ -80,7 +80,7 @@ void http_proxy_close (struct http_proxy_info *hp);
bool establish_http_proxy_passthru (struct http_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */
const char *host, /* openvpn server remote */
- const int port, /* openvpn server port */
+ const char *port, /* openvpn server port */
struct buffer *lookahead,
volatile int *signal_received);
diff --git a/openvpn/src/openvpn/ps.c b/openvpn/src/openvpn/ps.c
index 6495dc71..c1868642 100644
--- a/openvpn/src/openvpn/ps.c
+++ b/openvpn/src/openvpn/ps.c
@@ -330,8 +330,8 @@ journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_
if (!getpeername (pc->sd, (struct sockaddr *) &from.addr.sa, &slen)
&& !getsockname (cp->sd, (struct sockaddr *) &to.addr.sa, &dlen))
{
- const char *f = print_sockaddr_ex (&from, ":", PS_SHOW_PORT, &gc);
- const char *t = print_sockaddr_ex (&to, ":", PS_SHOW_PORT, &gc);
+ const char *f = print_openvpn_sockaddr (&from, &gc);
+ const char *t = print_openvpn_sockaddr (&to, &gc);
fnlen = strlen(journal_dir) + strlen(t) + 2;
jfn = (char *) malloc(fnlen);
check_malloc_return (jfn);
@@ -403,8 +403,7 @@ proxy_connection_io_requeue (struct proxy_connection *pc, const int rwflags_new,
static bool
proxy_entry_new (struct proxy_connection **list,
struct event_set *es,
- const in_addr_t server_addr,
- const int server_port,
+ const struct sockaddr_in server_addr,
const socket_descriptor_t sd_client,
struct buffer *initial_data,
const char *journal_dir)
@@ -416,7 +415,7 @@ proxy_entry_new (struct proxy_connection **list,
struct proxy_connection *cp;
/* connect to port share server */
- sock_addr_set (&osaddr, server_addr, server_port);
+ 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");
@@ -482,8 +481,7 @@ static bool
control_message_from_parent (const socket_descriptor_t sd_control,
struct proxy_connection **list,
struct event_set *es,
- const in_addr_t server_addr,
- const int server_port,
+ const struct sockaddr_in server_addr,
const int max_initial_buf,
const char *journal_dir)
{
@@ -539,7 +537,6 @@ control_message_from_parent (const socket_descriptor_t sd_control,
if (proxy_entry_new (list,
es,
server_addr,
- server_port,
received_fd,
&buf,
journal_dir))
@@ -716,8 +713,7 @@ proxy_connection_io_dispatch (struct proxy_connection *pc,
* This is the main function for the port share proxy background process.
*/
static void
-port_share_proxy (const in_addr_t hostaddr,
- const int port,
+port_share_proxy (const struct sockaddr_in hostaddr,
const socket_descriptor_t sd_control,
const int max_initial_buf,
const char *journal_dir)
@@ -754,7 +750,7 @@ port_share_proxy (const in_addr_t hostaddr,
const struct event_set_return *e = &esr[i];
if (e->arg == sd_control_marker)
{
- if (!control_message_from_parent (sd_control, &list, es, hostaddr, port, max_initial_buf, journal_dir))
+ if (!control_message_from_parent (sd_control, &list, es, hostaddr, max_initial_buf, journal_dir))
goto done;
}
else
@@ -789,14 +785,16 @@ port_share_proxy (const in_addr_t hostaddr,
*/
struct port_share *
port_share_open (const char *host,
- const int port,
+ const char *port,
const int max_initial_buf,
const char *journal_dir)
{
pid_t pid;
socket_descriptor_t fd[2];
- in_addr_t hostaddr;
+ struct sockaddr_in hostaddr;
struct port_share *ps;
+ int status;
+ struct addrinfo* ai;
ALLOC_OBJ_CLEAR (ps, struct port_share);
ps->foreground_fd = -1;
@@ -805,7 +803,12 @@ port_share_open (const char *host,
/*
* Get host's IP address
*/
- hostaddr = getaddr (GETADDR_RESOLVE|GETADDR_HOST_ORDER|GETADDR_FATAL, host, 0, NULL, NULL);
+
+ status = openvpn_getaddrinfo (GETADDR_RESOLVE|GETADDR_HOST_ORDER|GETADDR_FATAL,
+ host, port, 0, NULL, AF_INET, &ai);
+ ASSERT (status==0);
+ hostaddr = *((struct sockaddr_in*) ai->ai_addr);
+ freeaddrinfo(ai);
/*
* Make a socket for foreground and background processes
@@ -881,7 +884,7 @@ port_share_open (const char *host,
prng_init (NULL, 0);
/* execute the event loop */
- port_share_proxy (hostaddr, port, fd[1], max_initial_buf, journal_dir);
+ port_share_proxy (hostaddr, fd[1], max_initial_buf, journal_dir);
openvpn_close_socket (fd[1]);
diff --git a/openvpn/src/openvpn/ps.h b/openvpn/src/openvpn/ps.h
index 4280635d..e8919d48 100644
--- a/openvpn/src/openvpn/ps.h
+++ b/openvpn/src/openvpn/ps.h
@@ -44,7 +44,7 @@ struct port_share {
extern struct port_share *port_share;
struct port_share *port_share_open (const char *host,
- const int port,
+ const char *port,
const int max_initial_buf,
const char *journal_dir);
diff --git a/openvpn/src/openvpn/push.c b/openvpn/src/openvpn/push.c
index 05a38e0d..929a2f24 100644
--- a/openvpn/src/openvpn/push.c
+++ b/openvpn/src/openvpn/push.c
@@ -49,7 +49,7 @@ void
receive_auth_failed (struct context *c, const struct buffer *buffer)
{
msg (M_VERB0, "AUTH: Received control message: %s", BSTR(buffer));
- connection_list_set_no_advance(&c->options);
+ c->options.no_advance=true;
if (c->options.pull)
{
switch (auth_retry_get ())
diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c
index caa2459b..8a778884 100644
--- a/openvpn/src/openvpn/route.c
+++ b/openvpn/src/openvpn/route.c
@@ -294,12 +294,12 @@ init_route (struct route *r,
if(get_special_addr (rl, ro->network, &special.s_addr, &status))
{
special.s_addr = htonl(special.s_addr);
- ret = openvpn_getaddrinfo(0, inet_ntoa(special), 0, NULL,
+ ret = openvpn_getaddrinfo(0, inet_ntoa(special), NULL, 0, NULL,
AF_INET, network_list);
}
else
ret = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL,
- ro->network, 0, NULL, AF_INET, network_list);
+ ro->network, NULL, 0, NULL, AF_INET, network_list);
status = (ret == 0);
@@ -2722,7 +2722,7 @@ get_default_gateway (struct route_gateway_info *rgi)
if (write(s, (char *)&m_rtmsg, l) < 0)
{
- warn("writing to routing socket");
+ msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
gc_free (&gc);
close(s);
return;
@@ -3088,7 +3088,7 @@ get_default_gateway (struct route_gateway_info *rgi)
if (write(s, (char *)&m_rtmsg, l) < 0)
{
- warn("writing to routing socket");
+ msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
gc_free (&gc);
close(s);
return;
diff --git a/openvpn/src/openvpn/sig.c b/openvpn/src/openvpn/sig.c
index 0ebde245..7ddfd0ed 100644
--- a/openvpn/src/openvpn/sig.c
+++ b/openvpn/src/openvpn/sig.c
@@ -97,14 +97,14 @@ void
throw_signal (const int signum)
{
siginfo_static.signal_received = signum;
- siginfo_static.hard = true;
+ siginfo_static.source = SIG_SOURCE_HARD;
}
void
throw_signal_soft (const int signum, const char *signal_text)
{
siginfo_static.signal_received = signum;
- siginfo_static.hard = false;
+ siginfo_static.source = SIG_SOURCE_SOFT;
siginfo_static.signal_text = signal_text;
}
@@ -115,7 +115,7 @@ signal_reset (struct signal_info *si)
{
si->signal_received = 0;
si->signal_text = NULL;
- si->hard = false;
+ si->source = SIG_SOURCE_SOFT;
}
}
@@ -124,9 +124,23 @@ print_signal (const struct signal_info *si, const char *title, int msglevel)
{
if (si)
{
- const char *hs = (si->hard ? "hard" : "soft");
const char *type = (si->signal_text ? si->signal_text : "");
const char *t = (title ? title : "process");
+ const char *hs;
+ switch (si->source)
+ {
+ case SIG_SOURCE_SOFT:
+ hs= "soft";
+ break;
+ case SIG_SOURCE_HARD:
+ hs = "hard";
+ break;
+ case SIG_SOURCE_CONNECTION_FAILED:
+ hs = "connection failed(soft)";
+ break;
+ default:
+ ASSERT(0);
+ }
switch (si->signal_received)
{
diff --git a/openvpn/src/openvpn/sig.h b/openvpn/src/openvpn/sig.h
index 987efef5..c2c7b54e 100644
--- a/openvpn/src/openvpn/sig.h
+++ b/openvpn/src/openvpn/sig.h
@@ -28,6 +28,15 @@
#include "status.h"
#include "win32.h"
+
+
+#define SIG_SOURCE_SOFT 0
+#define SIG_SOURCE_HARD 1
+/* CONNECTION_FAILED is also a "soft" status,
+ * It is thrown if a connection attempt fails
+ */
+#define SIG_SOURCE_CONNECTION_FAILED 2
+
/*
* Signal information, including signal code
* and descriptive text.
@@ -35,7 +44,7 @@
struct signal_info
{
volatile int signal_received;
- volatile bool hard;
+ volatile int source;
const char *signal_text;
};
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 1e38e82c..c861fdd2 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -101,8 +101,8 @@ getaddr (unsigned int flags,
{
struct addrinfo *ai;
int status;
- status = openvpn_getaddrinfo(flags, hostname, resolve_retry_seconds,
- signal_received, AF_INET, &ai);
+ status = openvpn_getaddrinfo (flags & ~GETADDR_HOST_ORDER, hostname, NULL,
+ resolve_retry_seconds, signal_received, AF_INET, &ai);
if(status==0) {
struct in_addr ia;
if(succeeded)
@@ -125,6 +125,7 @@ getaddr (unsigned int flags,
int
openvpn_getaddrinfo (unsigned int flags,
const char *hostname,
+ const char *servname,
int resolve_retry_seconds,
volatile int *signal_received,
int ai_family,
@@ -135,6 +136,8 @@ openvpn_getaddrinfo (unsigned int flags,
int sigrec = 0;
int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
struct gc_arena gc = gc_new ();
+ const char *print_hostname;
+ const char *print_servname;
ASSERT(res);
@@ -142,8 +145,19 @@ openvpn_getaddrinfo (unsigned int flags,
res_init ();
#endif
- if (!hostname)
- hostname = "::";
+ ASSERT (hostname || servname);
+ ASSERT (!(flags & GETADDR_HOST_ORDER));
+
+ if(hostname)
+ print_hostname = hostname;
+ else
+ print_hostname = "undefined";
+
+ if(servname)
+ print_servname = servname;
+ else
+ print_servname = "";
+
if (flags & GETADDR_RANDOMIZE)
hostname = hostname_randomize(hostname, &gc);
@@ -159,25 +173,36 @@ openvpn_getaddrinfo (unsigned int flags,
CLEAR(hints);
hints.ai_family = ai_family;
hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = dnsflags_to_socktype(flags);
+ hints.ai_socktype = SOCK_STREAM;
+
+ if(flags & GETADDR_PASSIVE)
+ hints.ai_flags |= AI_PASSIVE;
+
+ if(flags & GETADDR_DATAGRAM)
+ hints.ai_socktype = SOCK_DGRAM;
+ else
+ hints.ai_socktype = SOCK_STREAM;
- status = getaddrinfo(hostname, NULL, &hints, res);
+ status = getaddrinfo(hostname, servname, &hints, res);
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);
+ /* Add +4 to cause integer division rounding up (1 + 4) = 5, (0+4)/5=0 */
+ int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 :
+ ((resolve_retry_seconds + 4)/ fail_wait_interval);
const char *fmt;
int level = 0;
-
- fmt = "RESOLVE: Cannot resolve host address: %s: %s";
+
+ fmt = "RESOLVE: Cannot resolve host address: %s:%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.)";
+ fmt = "RESOLVE: Cannot resolve host address: %s:%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 IP address: %s", hostname);
+ msg (msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)",
+ print_hostname,print_servname, gai_strerror(status));
goto done;
}
@@ -199,10 +224,10 @@ openvpn_getaddrinfo (unsigned int flags,
while (true)
{
/* try hostname lookup */
- hints.ai_flags = 0;
+ hints.ai_flags &= ~AI_NUMERICHOST;
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);
+ status = getaddrinfo(hostname, servname, &hints, res);
if (signal_received)
{
@@ -236,7 +261,8 @@ openvpn_getaddrinfo (unsigned int flags,
msg (level,
fmt,
- hostname,
+ print_hostname,
+ print_servname,
gai_strerror(status));
if (--resolve_retries <= 0)
@@ -249,7 +275,8 @@ openvpn_getaddrinfo (unsigned int flags,
/* hostname resolve succeeded */
- /* Do not chose an IP Addresse by random or change the order *
+ /*
+ * Do not chose an IP Addresse by random or change the order *
* of IP addresses, doing so will break RFC 3484 address selection *
*/
}
@@ -419,59 +446,6 @@ mac_addr_safe (const char *mac_addr)
return true;
}
-static void
-update_remote (const char* host,
- struct openvpn_sockaddr *addr,
- bool *changed,
- const unsigned int sockflags)
-{
- switch(addr->addr.sa.sa_family)
- {
- case AF_INET:
- if (host && addr)
- {
- const in_addr_t new_addr = getaddr (
- sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags),
- host,
- 1,
- NULL,
- NULL);
- if (new_addr && addr->addr.in4.sin_addr.s_addr != new_addr)
- {
- addr->addr.in4.sin_addr.s_addr = new_addr;
- *changed = true;
- }
- }
- break;
- case AF_INET6:
- if (host && addr)
- {
- 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;
- /* ipv6 requires also eg. sin6_scope_id => easier to fully copy and override port */
- addr->addr.in6 = sin6;
- addr->addr.in6.sin6_port = port;
- }
- freeaddrinfo(ai);
- }
- }
- break;
- default:
- ASSERT(0);
- }
-}
-
static int
socket_get_sndbuf (int sd)
{
@@ -643,51 +617,41 @@ create_socket_tcp (int af)
}
static socket_descriptor_t
-create_socket_udp (const unsigned int flags)
+create_socket_udp (const int af, const unsigned int flags)
{
socket_descriptor_t sd;
- if ((sd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
- msg (M_ERR, "UDP: Cannot create UDP socket");
+ if ((sd = socket (af, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ msg (M_ERR, "UDP: Cannot create UDP/UDP6 socket");
#if ENABLE_IP_PKTINFO
else if (flags & SF_USE_IP_PKTINFO)
{
int pad = 1;
+ if(af == AF_INET)
+ {
#ifdef IP_PKTINFO
- if (setsockopt (sd, SOL_IP, IP_PKTINFO,
- (void*)&pad, sizeof(pad)) < 0)
- msg(M_ERR, "UDP: failed setsockopt for IP_PKTINFO");
+ if (setsockopt (sd, SOL_IP, IP_PKTINFO,
+ (void*)&pad, sizeof(pad)) < 0)
+ msg(M_ERR, "UDP: failed setsockopt for IP_PKTINFO");
#elif defined(IP_RECVDSTADDR)
- if (setsockopt (sd, IPPROTO_IP, IP_RECVDSTADDR,
- (void*)&pad, sizeof(pad)) < 0)
- msg(M_ERR, "UDP: failed setsockopt for IP_RECVDSTADDR");
+ if (setsockopt (sd, IPPROTO_IP, IP_RECVDSTADDR,
+ (void*)&pad, sizeof(pad)) < 0)
+ msg(M_ERR, "UDP: failed setsockopt for IP_RECVDSTADDR");
#else
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
- }
-#endif
- return sd;
-}
-
-static socket_descriptor_t
-create_socket_udp6 (const unsigned int flags)
-{
- socket_descriptor_t sd;
-
- if ((sd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
- msg (M_ERR, "UDP: Cannot create UDP6 socket");
-#if ENABLE_IP_PKTINFO
- else if (flags & SF_USE_IP_PKTINFO)
- {
- int pad = 1;
+ }
+ else if (af == AF_INET6 )
+ {
#ifndef IPV6_RECVPKTINFO /* Some older Darwin platforms require this */
- if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO,
- (void*)&pad, sizeof(pad)) < 0)
+ if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO,
+ (void*)&pad, sizeof(pad)) < 0)
#else
- if (setsockopt (sd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- (void*)&pad, sizeof(pad)) < 0)
+ if (setsockopt (sd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (void*)&pad, sizeof(pad)) < 0)
#endif
- msg(M_ERR, "UDP: failed setsockopt for IPV6_RECVPKTINFO");
+ msg(M_ERR, "UDP: failed setsockopt for IPV6_RECVPKTINFO");
+ }
}
#endif
return sd;
@@ -696,10 +660,16 @@ create_socket_udp6 (const unsigned int flags)
static void
create_socket (struct link_socket *sock)
{
- /* create socket */
- if (sock->info.proto == PROTO_UDPv4)
+ /* 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);
+
+
+ if (ai_proto == IPPROTO_UDP)
{
- sock->sd = create_socket_udp (sock->sockflags);
+ sock->sd = create_socket_udp (ai_family, sock->sockflags);
sock->sockflags |= SF_GETADDRINFO_DGRAM;
#ifdef ENABLE_SOCKS
@@ -707,20 +677,9 @@ create_socket (struct link_socket *sock)
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 (AF_INET);
- }
- else if (sock->info.proto == PROTO_TCPv6_SERVER
- || sock->info.proto == PROTO_TCPv6_CLIENT)
+ else if (ai_proto == IPPROTO_TCP)
{
- sock->sd = create_socket_tcp (AF_INET6);
- }
- else if (sock->info.proto == PROTO_UDPv6)
- {
- sock->sd = create_socket_udp6 (sock->sockflags);
- sock->sockflags |= SF_GETADDRINFO_DGRAM;
+ sock->sd = create_socket_tcp (ai_family);
}
else
{
@@ -740,10 +699,9 @@ create_socket (struct link_socket *sock)
/*
* Functions used for establishing a TCP stream connection.
*/
-
static void
socket_do_listen (socket_descriptor_t sd,
- const struct openvpn_sockaddr *local,
+ const struct sockaddr *local,
bool do_listen,
bool do_set_nonblock)
{
@@ -833,8 +791,7 @@ static int
socket_listen_accept (socket_descriptor_t sd,
struct link_socket_actual *act,
const char *remote_dynamic,
- bool *remote_changed,
- const struct openvpn_sockaddr *local,
+ const struct addrinfo *local,
bool do_listen,
bool nowait,
volatile int *signal_received)
@@ -845,7 +802,7 @@ socket_listen_accept (socket_descriptor_t sd,
int new_sd = SOCKET_UNDEFINED;
CLEAR (*act);
- socket_do_listen (sd, local, do_listen, true);
+ socket_do_listen (sd, local->ai_addr, do_listen, true);
while (true)
{
@@ -880,18 +837,26 @@ socket_listen_accept (socket_descriptor_t sd,
if (socket_defined (new_sd))
{
- update_remote (remote_dynamic, &remote_verify, remote_changed, 0);
- if (addr_defined (&remote_verify)
- && !addr_match (&remote_verify, &act->dest))
- {
- msg (M_WARN,
- "TCP NOTE: Rejected connection attempt from %s due to --remote setting",
- print_link_socket_actual (act, &gc));
- if (openvpn_close_socket (new_sd))
- msg (M_ERR, "TCP: close socket failed (new_sd)");
- }
+ struct addrinfo* ai;
+ if(remote_dynamic)
+ openvpn_getaddrinfo(0, remote_dynamic, NULL, 1, NULL,
+ remote_verify.addr.sa.sa_family, &ai);
+
+ if(ai && !addrlist_match(&remote_verify, ai))
+ {
+ msg (M_WARN,
+ "TCP NOTE: Rejected connection attempt from %s due to --remote setting",
+ print_link_socket_actual (act, &gc));
+ if (openvpn_close_socket (new_sd))
+ msg (M_ERR, "TCP: close socket failed (new_sd)");
+ freeaddrinfo(ai);
+ }
else
- break;
+ {
+ if(ai)
+ freeaddrinfo(ai);
+ break;
+ }
}
openvpn_sleep (1);
}
@@ -907,17 +872,37 @@ socket_listen_accept (socket_descriptor_t sd,
void
socket_bind (socket_descriptor_t sd,
- struct openvpn_sockaddr *local,
+ struct addrinfo *local,
+ int ai_family,
const char *prefix)
{
struct gc_arena gc = gc_new ();
- if (bind (sd, &local->addr.sa, af_addr_size(local->addr.sa.sa_family)))
+ /* FIXME (schwabe)
+ * getaddrinfo for the bind address might return multiple AF_INET/AF_INET6
+ * entries for the requested protocol.
+ * For example if an address has multiple A records
+ * What is the correct way to deal with it?
+ */
+
+ ASSERT(local);
+ struct addrinfo* cur;
+
+ /* find the first addrinfo with correct ai_family */
+ for (cur = local; cur; cur=cur->ai_next)
+ {
+ if(cur->ai_family == ai_family)
+ break;
+ }
+ if (!cur)
+ msg (M_FATAL, "%s: Socket bind failed: No addr to bind has no v4/v6 record", prefix);
+
+ if (bind (sd, cur->ai_addr, cur->ai_addrlen))
{
const int errnum = openvpn_errno ();
msg (M_FATAL, "%s: Socket bind failed on local address %s: %s",
prefix,
- print_sockaddr (local, &gc),
+ print_sockaddr_ex (local->ai_addr, ":", PS_SHOW_PORT, &gc),
strerror_ts (errnum, &gc));
}
gc_free (&gc);
@@ -925,7 +910,7 @@ socket_bind (socket_descriptor_t sd,
int
openvpn_connect (socket_descriptor_t sd,
- struct openvpn_sockaddr *remote,
+ const struct sockaddr *remote,
int connect_timeout,
volatile int *signal_received)
{
@@ -933,7 +918,7 @@ openvpn_connect (socket_descriptor_t sd,
#ifdef CONNECT_NONBLOCK
set_nonblock (sd);
- status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family));
+ status = connect (sd, remote, af_addr_size(remote->sa_family));
if (status)
status = openvpn_errno ();
if (
@@ -1005,85 +990,76 @@ openvpn_connect (socket_descriptor_t sd,
return status;
}
+void set_actual_address (struct link_socket_actual* actual, struct addrinfo* ai)
+{
+ CLEAR (*actual);
+ ASSERT (ai);
+
+ if (ai->ai_family == AF_INET)
+ actual->dest.addr.in4 =
+ *((struct sockaddr_in*) ai->ai_addr);
+ else if (ai->ai_family == AF_INET6)
+ actual->dest.addr.in6 =
+ *((struct sockaddr_in6*) ai->ai_addr);
+ else
+ ASSERT(0);
+
+ /* Copy addrinfo sock parameters for socket creating */
+ actual->ai_family = ai->ai_family;
+ actual->ai_protocol = ai->ai_protocol;
+ actual->ai_socktype = ai->ai_socktype;
+}
+
void
socket_connect (socket_descriptor_t *sd,
- struct openvpn_sockaddr *local,
- bool bind_local,
- struct openvpn_sockaddr *remote,
- const bool connection_profiles_defined,
- const char *remote_dynamic,
- bool *remote_changed,
- const int connect_retry_seconds,
- const int connect_timeout,
- const int connect_retry_max,
- const unsigned int sockflags,
- volatile int *signal_received)
+ struct link_socket_addr *lsa,
+ const int connect_timeout,
+ struct signal_info* sig_info)
{
struct gc_arena gc = gc_new ();
- int retry = 0;
-
+ const struct sockaddr *dest = &lsa->actual.dest.addr.sa;
+
+ int status;
+
#ifdef CONNECT_NONBLOCK
- msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]",
- print_sockaddr (remote, &gc));
+ msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]",
+ print_sockaddr (dest, &gc));
#else
- msg (M_INFO, "Attempting to establish TCP connection with %s",
- print_sockaddr (remote, &gc));
+ msg (M_INFO, "Attempting to establish TCP connection with %s",
+ print_sockaddr (dest, &gc));
#endif
-
- while (true)
- {
- int status;
-
+
#ifdef ENABLE_MANAGEMENT
- if (management)
+ if (management)
management_set_state (management,
- OPENVPN_STATE_TCP_CONNECT,
- NULL,
- (in_addr_t)0,
- (in_addr_t)0);
+ OPENVPN_STATE_TCP_CONNECT,
+ NULL,
+ (in_addr_t)0,
+ (in_addr_t)0);
#endif
- status = openvpn_connect (*sd, remote, connect_timeout, signal_received);
+ /* Set the actual address */
+ status = openvpn_connect (*sd, dest, connect_timeout, &sig_info->signal_received);
- get_signal (signal_received);
- if (*signal_received)
+ get_signal (&sig_info->signal_received);
+ if (sig_info->signal_received)
goto done;
- if (!status)
- break;
-
- msg (D_LINK_ERRORS,
- "TCP: connect to %s failed, will try again in %d seconds: %s",
- print_sockaddr (remote, &gc),
- connect_retry_seconds,
- strerror_ts (status, &gc));
-
- gc_reset (&gc);
+ if (status) {
- openvpn_close_socket (*sd);
- *sd = SOCKET_UNDEFINED;
+ msg (D_LINK_ERRORS,
+ "TCP: connect to %s failed: %s",
+ print_sockaddr (dest, &gc),
+ strerror_ts (status, &gc));
- if ((connect_retry_max > 0 && ++retry >= connect_retry_max) || connection_profiles_defined)
- {
- *signal_received = SIGUSR1;
- goto done;
- }
-
- openvpn_sleep (connect_retry_seconds);
-
- get_signal (signal_received);
- if (*signal_received)
- goto done;
-
- *sd = create_socket_tcp (local->addr.sa.sa_family);
-
- if (bind_local)
- socket_bind (*sd, local, "TCP Client");
- update_remote (remote_dynamic, remote, remote_changed, sockflags);
- }
-
- msg (M_INFO, "TCP connection established with %s",
- print_sockaddr (remote, &gc));
+ openvpn_close_socket (*sd);
+ *sd = SOCKET_UNDEFINED;
+ sig_info->signal_received = SIGUSR1;
+ sig_info->source = SIG_SOURCE_CONNECTION_FAILED;
+ } else {
+ msg (M_INFO, "TCP connection established with %s",
+ print_sockaddr (dest, &gc));
+ }
done:
gc_free (&gc);
@@ -1134,72 +1110,47 @@ frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto)
}
static void
-resolve_bind_local (struct link_socket *sock)
+resolve_bind_local (struct link_socket *sock, const sa_family_t af)
{
struct gc_arena gc = gc_new ();
/* resolve local address if undefined */
- if (!addr_defined (&sock->info.lsa->local))
+ if (!sock->info.lsa->bind_local)
{
- /* may return AF_{INET|INET6} guessed from local_host */
- switch(addr_guess_family(sock->info.proto, sock->local_host))
- {
- case AF_INET:
- sock->info.lsa->local.addr.in4.sin_family = AF_INET;
- sock->info.lsa->local.addr.in4.sin_addr.s_addr =
- (sock->local_host ? getaddr (GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL,
- sock->local_host,
- 0,
- NULL,
- NULL)
- : htonl (INADDR_ANY));
- sock->info.lsa->local.addr.in4.sin_port = htons (sock->local_port);
- break;
- case AF_INET6:
- {
- int status;
- int err;
- CLEAR(sock->info.lsa->local.addr.in6);
- if (sock->local_host)
- {
- 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;
- status = 0;
- }
- if (!status == 0)
- {
- msg (M_FATAL, "getaddr6() failed for local \"%s\": %s",
- sock->local_host,
- gai_strerror(err));
- }
- sock->info.lsa->local.addr.in6.sin6_port = htons (sock->local_port);
- }
- break;
- }
+ int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL |
+ GETADDR_FATAL | GETADDR_PASSIVE;
+ int status;
+
+ if(proto_is_dgram(sock->info.proto))
+ 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);
+ if(status !=0) {
+ msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s",
+ sock->local_host, sock->local_port,
+ gai_strerror(status));
+ }
}
-
- /* bind to local address/port */
- if (sock->bind_local)
- {
+
+ gc_free (&gc);
+}
+
+static void bind_local (struct link_socket *sock)
+{
+ /* bind to local address/port */
+ if (sock->bind_local)
+ {
#ifdef ENABLE_SOCKS
- if (sock->socks_proxy && sock->info.proto == PROTO_UDPv4)
- socket_bind (sock->ctrl_sd, &sock->info.lsa->local, "SOCKS");
- else
+ if (sock->socks_proxy && sock->info.proto == PROTO_UDP && sock->info.af == AF_INET)
+ socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
+ sock->info.lsa->actual.ai_family, "SOCKS");
+ else
#endif
- socket_bind (sock->sd, &sock->info.lsa->local, "TCP/UDP");
- }
- gc_free (&gc);
+ socket_bind (sock->sd, sock->info.lsa->bind_local,
+ sock->info.lsa->actual.ai_family, "TCP/UDP");
+ }
}
static void
@@ -1209,34 +1160,22 @@ resolve_remote (struct link_socket *sock,
volatile int *signal_received)
{
struct gc_arena gc = gc_new ();
- int af;
if (!sock->did_resolve_remote)
{
/* resolve remote address if undefined */
- if (!addr_defined (&sock->info.lsa->remote))
+ if (!sock->info.lsa->remote_list)
{
- af = addr_guess_family(sock->info.proto, sock->remote_host);
- switch(af)
- {
- case AF_INET:
- sock->info.lsa->remote.addr.in4.sin_family = AF_INET;
- sock->info.lsa->remote.addr.in4.sin_addr.s_addr = 0;
- break;
- case AF_INET6:
- CLEAR(sock->info.lsa->remote.addr.in6);
- sock->info.lsa->remote.addr.in6.sin6_family = AF_INET6;
- sock->info.lsa->remote.addr.in6.sin6_addr = in6addr_any;
- break;
- }
-
if (sock->remote_host)
{
unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
int retry = 0;
int status = -1;
+
+ if (proto_is_dgram(sock->info.proto))
+ flags |= GETADDR_DATAGRAM;
- if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
+ if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
{
if (phase == 2)
flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
@@ -1272,12 +1211,11 @@ resolve_remote (struct link_socket *sock,
}
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);
+ status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port,
+ retry, signal_received, sock->info.af, &ai);
if(status == 0) {
- sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr));
- freeaddrinfo(ai);
+ sock->info.lsa->remote_list = ai;
+ sock->info.lsa->current_remote = ai;
dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d",
flags,
@@ -1298,15 +1236,6 @@ resolve_remote (struct link_socket *sock,
goto done;
}
}
- switch(af)
- {
- case AF_INET:
- sock->info.lsa->remote.addr.in4.sin_port = htons (sock->remote_port);
- break;
- case AF_INET6:
- sock->info.lsa->remote.addr.in6.sin6_port = htons (sock->remote_port);
- break;
- }
}
/* should we re-use previous active remote address? */
@@ -1319,8 +1248,12 @@ resolve_remote (struct link_socket *sock,
}
else
{
- CLEAR (sock->info.lsa->actual);
- sock->info.lsa->actual.dest = sock->info.lsa->remote;
+ CLEAR (sock->info.lsa->actual);
+ if(sock->info.lsa->current_remote)
+ {
+ set_actual_address (&sock->info.lsa->actual,
+ sock->info.lsa->current_remote);
+ }
}
/* remember that we finished */
@@ -1331,6 +1264,8 @@ resolve_remote (struct link_socket *sock,
gc_free (&gc);
}
+
+
struct link_socket *
link_socket_new (void)
{
@@ -1344,15 +1279,36 @@ link_socket_new (void)
return sock;
}
+void
+create_new_socket (struct link_socket* sock, int mark)
+{
+ if (sock->bind_local) {
+ resolve_bind_local (sock, sock->info.af);
+ }
+ resolve_remote (sock, 1, NULL, NULL);
+ create_socket (sock);
+
+ /* set socket buffers based on --sndbuf and --rcvbuf options */
+ socket_set_buffers (sock->sd, &sock->socket_buffer_sizes);
+
+ /* set socket to --mark packets with given value */
+ socket_set_mark (sock->sd, mark);
+
+ if (sock->bind_local)
+ bind_local(sock);
+
+}
+
+
/* bind socket if necessary */
void
link_socket_init_phase1 (struct link_socket *sock,
- const bool connection_profiles_defined,
const char *local_host,
- int local_port,
+ const char *local_port,
const char *remote_host,
- int remote_port,
+ const char *remote_port,
int proto,
+ sa_family_t af,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -1371,9 +1327,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *ipchange_command,
const struct plugin_list *plugins,
int resolve_retry_seconds,
- int connect_retry_seconds,
int connect_timeout,
- int connect_retry_max,
int mtu_discover_type,
int rcvbuf,
int sndbuf,
@@ -1382,8 +1336,6 @@ link_socket_init_phase1 (struct link_socket *sock,
{
ASSERT (sock);
- sock->connection_profiles_defined = connection_profiles_defined;
-
sock->local_host = local_host;
sock->local_port = local_port;
sock->remote_host = remote_host;
@@ -1400,9 +1352,7 @@ link_socket_init_phase1 (struct link_socket *sock,
sock->bind_local = bind_local;
sock->inetd = inetd;
sock->resolve_retry_seconds = resolve_retry_seconds;
- sock->connect_retry_seconds = connect_retry_seconds;
sock->connect_timeout = connect_timeout;
- sock->connect_retry_max = connect_retry_max;
sock->mtu_discover_type = mtu_discover_type;
#ifdef ENABLE_DEBUG
@@ -1415,6 +1365,7 @@ link_socket_init_phase1 (struct link_socket *sock,
sock->sockflags = sockflags;
sock->info.proto = proto;
+ sock->info.af = af;
sock->info.remote_float = remote_float;
sock->info.lsa = lsa;
sock->info.ipchange_command = ipchange_command;
@@ -1424,20 +1375,18 @@ link_socket_init_phase1 (struct link_socket *sock,
if (mode == LS_MODE_TCP_ACCEPT_FROM)
{
ASSERT (accept_from);
- ASSERT (sock->info.proto == PROTO_TCPv4_SERVER
- || sock->info.proto == PROTO_TCPv6_SERVER
- );
+ ASSERT (sock->info.proto == PROTO_TCP_SERVER);
ASSERT (!sock->inetd);
sock->sd = accept_from->sd;
}
-
+
if (false)
;
#ifdef ENABLE_HTTP_PROXY
/* are we running in HTTP proxy mode? */
else if (sock->http_proxy)
{
- ASSERT (sock->info.proto == PROTO_TCPv4_CLIENT);
+ ASSERT (sock->info.proto == PROTO_TCP_CLIENT && sock->info.af == AF_INET);
ASSERT (!sock->inetd);
/* the proxy server */
@@ -1453,7 +1402,7 @@ link_socket_init_phase1 (struct link_socket *sock,
/* or in Socks proxy mode? */
else if (sock->socks_proxy)
{
- ASSERT (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == PROTO_UDPv4);
+ ASSERT (sock->info.af == AF_INET);
ASSERT (!sock->inetd);
/* the proxy server */
@@ -1472,7 +1421,7 @@ link_socket_init_phase1 (struct link_socket *sock,
}
/* bind behavior for TCP server vs. client */
- if (sock->info.proto == PROTO_TCPv4_SERVER)
+ if (sock->info.proto == PROTO_TCP_SERVER && sock->info.af==AF_INET)
{
if (sock->mode == LS_MODE_TCP_ACCEPT_FROM)
sock->bind_local = false;
@@ -1483,248 +1432,59 @@ link_socket_init_phase1 (struct link_socket *sock,
/* were we started by inetd or xinetd? */
if (sock->inetd)
{
- ASSERT (sock->info.proto != PROTO_TCPv4_CLIENT
- && sock->info.proto != PROTO_TCPv6_CLIENT);
+ ASSERT (sock->info.proto != PROTO_TCP_CLIENT);
ASSERT (socket_defined (inetd_socket_descriptor));
sock->sd = inetd_socket_descriptor;
}
else if (mode != LS_MODE_TCP_ACCEPT_FROM)
{
- create_socket (sock);
-
- /* set socket buffers based on --sndbuf and --rcvbuf options */
- socket_set_buffers (sock->sd, &sock->socket_buffer_sizes);
-
- /* set socket to --mark packets with given value */
- socket_set_mark (sock->sd, mark);
-
- resolve_bind_local (sock);
- resolve_remote (sock, 1, NULL, NULL);
+ create_new_socket (sock, mark);
}
}
-/* finalize socket initialization */
-void
-link_socket_init_phase2 (struct link_socket *sock,
- const struct frame *frame,
- volatile int *signal_received)
+static
+void phase2_inetd (struct link_socket* sock, const struct frame *frame,
+ const char *remote_dynamic, volatile int *signal_received)
{
- struct gc_arena gc = gc_new ();
- const char *remote_dynamic = NULL;
bool remote_changed = false;
- int sig_save = 0;
- ASSERT (sock);
-
- if (signal_received && *signal_received)
- {
- sig_save = *signal_received;
- *signal_received = 0;
- }
-
- /* initialize buffers */
- socket_frame_init (frame, sock);
-
- /*
- * Pass a remote name to connect/accept so that
- * they can test for dynamic IP address changes
- * and throw a SIGUSR1 if appropriate.
- */
- if (sock->resolve_retry_seconds)
- remote_dynamic = sock->remote_host;
-
- /* were we started by inetd or xinetd? */
- if (sock->inetd)
- {
- if (sock->info.proto == PROTO_TCPv4_SERVER
- || sock->info.proto == PROTO_TCPv6_SERVER) {
- /* AF_INET as default (and fallback) for inetd */
- sock->info.lsa->actual.dest.addr.sa.sa_family = AF_INET;
+ if (sock->info.proto == PROTO_TCP_SERVER) {
+ /* AF_INET as default (and fallback) for inetd */
+ sock->info.lsa->actual.dest.addr.sa.sa_family = AF_INET;
#ifdef HAVE_GETSOCKNAME
- {
- /* inetd: hint family type for dest = local's */
- struct openvpn_sockaddr local_addr;
- socklen_t addrlen = sizeof(local_addr);
- if (getsockname (sock->sd, (struct sockaddr *)&local_addr, &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, 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, 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));
-#endif
- sock->sd =
- socket_listen_accept (sock->sd,
- &sock->info.lsa->actual,
- remote_dynamic,
- &remote_changed,
- &sock->info.lsa->local,
- false,
- sock->inetd == INETD_NOWAIT,
- signal_received);
- }
- ASSERT (!remote_changed);
- if (*signal_received)
- goto done;
- }
- else
{
- resolve_remote (sock, 2, &remote_dynamic, signal_received);
-
- if (*signal_received)
- goto done;
-
- /* TCP client/server */
- if (sock->info.proto == PROTO_TCPv4_SERVER
- ||sock->info.proto == PROTO_TCPv6_SERVER)
- {
- switch (sock->mode)
- {
- case LS_MODE_DEFAULT:
- sock->sd = socket_listen_accept (sock->sd,
- &sock->info.lsa->actual,
- remote_dynamic,
- &remote_changed,
- &sock->info.lsa->local,
- true,
- false,
- signal_received);
- break;
- case LS_MODE_TCP_LISTEN:
- socket_do_listen (sock->sd,
- &sock->info.lsa->local,
- true,
- false);
- break;
- case LS_MODE_TCP_ACCEPT_FROM:
- sock->sd = socket_do_accept (sock->sd,
- &sock->info.lsa->actual,
- false);
- if (!socket_defined (sock->sd))
- {
- *signal_received = SIGTERM;
- goto done;
- }
- tcp_connection_established (&sock->info.lsa->actual);
- break;
- default:
- ASSERT (0);
- }
- }
- else if (sock->info.proto == PROTO_TCPv4_CLIENT
- ||sock->info.proto == PROTO_TCPv6_CLIENT)
- {
-
-#ifdef GENERAL_PROXY_SUPPORT
- bool proxy_retry = false;
-#else
- const bool proxy_retry = false;
-#endif
- do {
- socket_connect (&sock->sd,
- &sock->info.lsa->local,
- sock->bind_local,
- &sock->info.lsa->actual.dest,
- sock->connection_profiles_defined,
- remote_dynamic,
- &remote_changed,
- sock->connect_retry_seconds,
- sock->connect_timeout,
- sock->connect_retry_max,
- sock->sockflags,
- signal_received);
-
- if (*signal_received)
- goto done;
-
- 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,
- 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,
- signal_received);
- }
-#endif
- if (proxy_retry)
- {
- openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp (AF_INET);
- }
- } while (proxy_retry);
- }
-#ifdef ENABLE_SOCKS
- else if (sock->info.proto == PROTO_UDPv4 && sock->socks_proxy)
- {
- socket_connect (&sock->ctrl_sd,
- &sock->info.lsa->local,
- sock->bind_local,
- &sock->info.lsa->actual.dest,
- sock->connection_profiles_defined,
- remote_dynamic,
- &remote_changed,
- sock->connect_retry_seconds,
- sock->connect_timeout,
- sock->connect_retry_max,
- sock->sockflags,
- signal_received);
-
- if (*signal_received)
- goto done;
-
- establish_socks_proxy_udpassoc (sock->socks_proxy,
- sock->ctrl_sd,
- sock->sd,
- &sock->socks_relay.dest,
- signal_received);
-
- if (*signal_received)
- goto done;
-
- 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);
- addr_zero_host(&sock->info.lsa->remote);
-
- resolve_remote (sock, 1, NULL, signal_received);
-
- if (*signal_received)
- goto done;
- }
-#endif
-
- if (*signal_received)
- goto done;
-
- if (remote_changed)
- {
- msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment");
- addr_copy_host(&sock->info.lsa->remote, &sock->info.lsa->actual.dest);
- }
+ /* inetd: hint family type for dest = local's */
+ 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);
+ } else
+ 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));
+#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);
+ }
+ ASSERT (!remote_changed);
+}
+static void
+phase2_set_socket_flags (struct link_socket* sock)
+{
/* set misc socket parameters */
socket_set_flags (sock->sd, sock->sockflags);
@@ -1747,35 +1507,245 @@ link_socket_init_phase2 (struct link_socket *sock,
/* if the OS supports it, enable extended error passing on the socket */
set_sock_extended_error_passing (sock->sd);
#endif
+}
+
+
+static void
+linksock_print_addr (struct link_socket *sock)
+{
+ struct gc_arena gc = gc_new ();
/* 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, true));
+ 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));
+ }
else
- msg (msglevel, "%s link local%s: %s",
- proto2ascii (sock->info.proto, true),
- (sock->bind_local ? " (bound)" : ""),
- print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? PS_SHOW_PORT : 0, &gc));
-
+ 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, 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)
+{
+ 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);
+ break;
+ case LS_MODE_TCP_LISTEN:
+ socket_do_listen (sock->sd,
+ 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);
+ if (!socket_defined (sock->sd))
+ {
+ *signal_received = SIGTERM;
+ return;
+ }
+ tcp_connection_established (&sock->info.lsa->actual);
+ break;
+ default:
+ ASSERT (0);
+ }
+
+}
+
+
+static void
+phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)
+{
+#ifdef GENERAL_PROXY_SUPPORT
+ 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)
+ ;
+#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);
+ }
+#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);
+ }
+#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);
+
+}
+
+#ifdef ENABLE_SOCKS
+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);
+
+ if (sig_info->signal_received)
+ return;
+
+ establish_socks_proxy_udpassoc (sock->socks_proxy,
+ sock->ctrl_sd,
+ sock->sd,
+ &sock->socks_relay.dest,
+ &sig_info->signal_received);
+
+ if (sig_info->signal_received)
+ 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);
+
+ 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 char *remote_dynamic = NULL;
+ int sig_save = 0;
+
+ ASSERT (sock);
+
+ if (sig_info && sig_info->signal_received)
+ {
+ sig_save = sig_info->signal_received;
+ sig_info->signal_received = 0;
+ }
+
+ /* initialize buffers */
+ socket_frame_init (frame, sock);
+
+ /*
+ * Pass a remote name to connect/accept so that
+ * they can test for dynamic IP address changes
+ * and throw a SIGUSR1 if appropriate.
+ */
+ if (sock->resolve_retry_seconds)
+ remote_dynamic = sock->remote_host;
+
+ /* were we started by inetd or xinetd? */
+ if (sock->inetd)
+ {
+ phase2_inetd (sock, frame, remote_dynamic, &sig_info->signal_received);
+ if (sig_info && sig_info->signal_received)
+ goto done;
+
+ }
+ else
+ {
+ resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received);
+
+ if (sig_info && sig_info->signal_received)
+ goto done;
+
+ if (sock->info.proto == PROTO_TCP_SERVER)
+ {
+ phase2_tcp_server (sock, remote_dynamic,
+ &sig_info->signal_received);
+ }
+ else if (sock->info.proto == PROTO_TCP_CLIENT)
+ {
+ phase2_tcp_client (sock, sig_info);
+
+ }
+#ifdef ENABLE_SOCKS
+ else if (sock->info.proto == PROTO_UDP && sock->socks_proxy && sock->info.af == AF_INET)
+ {
+ phase2_socks_client (sock, sig_info);
+#endif
+ }
+ if (sig_info && sig_info->signal_received)
+ goto done;
+ }
+
+ phase2_set_socket_flags(sock);
+ linksock_print_addr(sock);
+
done:
- if (sig_save && signal_received)
+ if (sig_save && sig_info)
{
- if (!*signal_received)
- *signal_received = sig_save;
+ if (!sig_info->signal_received)
+ sig_info->signal_received = sig_save;
}
- gc_free (&gc);
}
void
@@ -1843,17 +1813,14 @@ setenv_trusted (struct env_set *es, const struct link_socket_info *info)
static void
ipchange_fmt (const bool include_cmd, struct argv *argv, const struct link_socket_info *info, struct gc_arena *gc)
{
- const char *ip = print_sockaddr_ex (&info->lsa->actual.dest, NULL, 0, gc);
- const char *port = print_sockaddr_ex (&info->lsa->actual.dest, NULL, PS_DONT_SHOW_ADDR|PS_SHOW_PORT, gc);
+ const char *host = print_sockaddr_ex (&info->lsa->actual.dest.addr.sa, " ", PS_SHOW_PORT , gc);
if (include_cmd)
- argv_printf (argv, "%sc %s %s",
+ argv_printf (argv, "%sc %s",
info->ipchange_command,
- ip,
- port);
+ host);
else
- argv_printf (argv, "%s %s",
- ip,
- port);
+ argv_printf (argv, "%s", host);
+
}
void
@@ -1910,6 +1877,7 @@ link_socket_bad_incoming_addr (struct buffer *buf,
const struct link_socket_actual *from_addr)
{
struct gc_arena gc = gc_new ();
+ struct addrinfo* ai;
switch(from_addr->dest.addr.sa.sa_family)
{
@@ -1919,7 +1887,12 @@ link_socket_bad_incoming_addr (struct buffer *buf,
"TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)",
print_link_socket_actual (from_addr, &gc),
(int)from_addr->dest.addr.sa.sa_family,
- print_sockaddr (&info->lsa->remote, &gc));
+ print_sockaddr_ex (info->lsa->remote_list->ai_addr,":" ,PS_SHOW_PORT, &gc));
+ /* print additional remote addresses */
+ for(ai=info->lsa->remote_list->ai_next;ai;ai=ai->ai_next) {
+ msg(D_LINK_ERRORS,"or from peer address: %s",
+ print_sockaddr_ex(ai->ai_addr,":",PS_SHOW_PORT, &gc));
+ }
break;
}
buf->len = 0;
@@ -1944,14 +1917,17 @@ link_socket_current_remote (const struct link_socket_info *info)
* Maybe in the future consider PF_INET6 endpoints also ...
* by now just ignore it
*
+ * For --remote entries with multiple addresses this
+ * only return the actual endpoint we have sucessfully connected to
*/
if (lsa->actual.dest.addr.sa.sa_family != AF_INET)
return IPV4_INVALID_ADDR;
if (link_socket_actual_defined (&lsa->actual))
return ntohl (lsa->actual.dest.addr.in4.sin_addr.s_addr);
- else if (addr_defined (&lsa->remote))
- return ntohl (lsa->remote.addr.in4.sin_addr.s_addr);
+ else if (lsa->current_remote)
+ return ntohl (((struct sockaddr_in*)lsa->current_remote->ai_addr)
+ ->sin_addr.s_addr);
else
return 0;
}
@@ -2018,7 +1994,7 @@ stream_buf_init (struct stream_buf *sb,
sb->residual = alloc_buf (sb->maxlen);
sb->error = false;
#if PORT_SHARE
- sb->port_share_state = ((sockflags & SF_PORT_SHARE) && (proto == PROTO_TCPv4_SERVER))
+ sb->port_share_state = ((sockflags & SF_PORT_SHARE) && (proto == PROTO_TCP_SERVER))
? PS_ENABLED
: PS_DISABLED;
#endif
@@ -2167,67 +2143,58 @@ socket_listen_event_handle (struct link_socket *s)
*/
const char *
-print_sockaddr (const struct openvpn_sockaddr *addr, struct gc_arena *gc)
-{
- return print_sockaddr_ex (addr, ":", PS_SHOW_PORT, gc);
-}
-
-const char *
-print_sockaddr_ex (const struct openvpn_sockaddr *addr,
- const char* separator,
- const unsigned int flags,
- struct gc_arena *gc)
+print_sockaddr_ex (const struct sockaddr *sa,
+ const char* separator,
+ const unsigned int flags,
+ struct gc_arena *gc)
{
struct buffer out = alloc_buf_gc (128, gc);
bool addr_is_defined;
- addr_is_defined = addr_defined (addr);
- if (!addr_is_defined) {
- return "[undef]";
- }
- switch(addr->addr.sa.sa_family)
+ char hostaddr[NI_MAXHOST] = "";
+ char servname[NI_MAXSERV] = "";
+ int status;
+
+ socklen_t salen;
+ switch(sa->sa_family)
{
case AF_INET:
- {
- const int port= ntohs (addr->addr.in4.sin_port);
- buf_puts (&out, "[AF_INET]");
-
- if (!(flags & PS_DONT_SHOW_ADDR))
- buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->addr.in4.sin_addr) : "[undef]"));
-
- if (((flags & PS_SHOW_PORT) || (addr_defined (addr) && (flags & PS_SHOW_PORT_IF_DEFINED)))
- && port)
- {
- if (separator)
- buf_printf (&out, "%s", separator);
-
- buf_printf (&out, "%d", port);
- }
- }
+ buf_puts (&out, "[AF_INET]");
+ salen = sizeof (struct sockaddr_in);
+ addr_is_defined = ((struct sockaddr_in*) sa)->sin_addr.s_addr != 0;
break;
case AF_INET6:
- {
- const int port= ntohs (addr->addr.in6.sin6_port);
- char buf[INET6_ADDRSTRLEN] = "";
- buf_puts (&out, "[AF_INET6]");
- if (addr_is_defined)
- {
- getnameinfo(&addr->addr.sa, sizeof (struct sockaddr_in6),
- buf, sizeof (buf), NULL, 0, NI_NUMERICHOST);
- buf_puts (&out, buf);
- }
- if (((flags & PS_SHOW_PORT) || (addr_is_defined && (flags & PS_SHOW_PORT_IF_DEFINED)))
- && port)
- {
- if (separator)
- buf_puts (&out, separator);
-
- buf_printf (&out, "%d", port);
- }
- }
+ buf_puts (&out, "[AF_INET6]");
+ salen = sizeof (struct sockaddr_in6);
+ addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6*) sa)->sin6_addr);
break;
default:
ASSERT(0);
}
+
+ status = getnameinfo(sa, salen, hostaddr, sizeof (hostaddr),
+ servname, sizeof(servname), NI_NUMERICHOST | NI_NUMERICSERV);
+
+ if(status!=0) {
+ buf_printf(&out,"[nameinfo() err: %s]",gai_strerror(status));
+ return BSTR(&out);
+ }
+
+ if (!(flags & PS_DONT_SHOW_ADDR))
+ {
+ if (addr_is_defined)
+ buf_puts (&out, hostaddr);
+ else
+ buf_puts (&out, "[undef]");
+ }
+
+ if ((flags & PS_SHOW_PORT) || (flags & PS_SHOW_PORT_IF_DEFINED))
+ {
+ if (separator)
+ buf_puts (&out, separator);
+
+ buf_puts (&out, servname);
+ }
+
return BSTR (&out);
}
@@ -2251,7 +2218,7 @@ print_link_socket_actual_ex (const struct link_socket_actual *act,
{
char ifname[IF_NAMESIZE] = "[undef]";
struct buffer out = alloc_buf_gc (128, gc);
- buf_printf (&out, "%s", print_sockaddr_ex (&act->dest, separator, flags, gc));
+ buf_printf (&out, "%s", print_sockaddr_ex (&act->dest.addr.sa, separator, flags, gc));
#if ENABLE_IP_PKTINFO
if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act))
{
@@ -2272,7 +2239,7 @@ print_link_socket_actual_ex (const struct link_socket_actual *act,
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
buf_printf (&out, " (via %s%%%s)",
- print_sockaddr_ex (&sa, separator, 0, gc),
+ print_sockaddr_ex (&sa.addr.sa, separator, 0, gc),
ifname);
}
break;
@@ -2434,22 +2401,23 @@ setenv_link_socket_actual (struct env_set *es,
struct proto_names {
const char *short_form;
const char *display_form;
- bool is_dgram;
- bool is_net;
- unsigned short proto_af;
+ sa_family_t proto_af;
+ int proto;
};
/* Indexed by PROTO_x */
-static const struct proto_names proto_names[PROTO_N] = {
- {"proto-uninitialized", "proto-NONE",0,0, AF_UNSPEC},
- {"udp", "UDPv4",1,1, AF_INET},
- {"tcp-server", "TCPv4_SERVER",0,1, AF_INET},
- {"tcp-client", "TCPv4_CLIENT",0,1, AF_INET},
- {"tcp", "TCPv4",0,1, AF_INET},
- {"udp6" ,"UDPv6",1,1, AF_INET6},
- {"tcp6-server","TCPv6_SERVER",0,1, AF_INET6},
- {"tcp6-client","TCPv6_CLIENT",0,1, AF_INET6},
- {"tcp6" ,"TCPv6",0,1, AF_INET6},
+static const struct proto_names proto_names[] = {
+ {"proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE},
+ {"udp", "UDP", AF_UNSPEC, PROTO_UDP},
+ {"udp4", "UDPv4", AF_INET, PROTO_UDP},
+ {"tcp-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER},
+ {"tcp-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT},
+ {"tcp", "TCP", AF_UNSPEC, PROTO_TCP},
+ {"tcp4", "TCPv4", AF_INET, PROTO_TCP},
+ {"udp6" ,"UDPv6", AF_INET6, PROTO_UDP},
+ {"tcp6-server","TCPv6_SERVER", AF_INET6, PROTO_TCP_SERVER},
+ {"tcp6-client","TCPv6_CLIENT", AF_INET6, PROTO_TCP_CLIENT},
+ {"tcp6" ,"TCPv6", AF_INET6, PROTO_TCP},
};
bool
@@ -2457,59 +2425,66 @@ proto_is_net(int proto)
{
if (proto < 0 || proto >= PROTO_N)
ASSERT(0);
- return proto_names[proto].is_net;
+ return proto != PROTO_NONE;
}
bool
proto_is_dgram(int proto)
{
- if (proto < 0 || proto >= PROTO_N)
- ASSERT(0);
- return proto_names[proto].is_dgram;
+ return proto_is_udp(proto);
}
+
bool
proto_is_udp(int proto)
{
if (proto < 0 || proto >= PROTO_N)
ASSERT(0);
- return proto_names[proto].is_dgram&&proto_names[proto].is_net;
+ return proto == PROTO_UDP;
}
+
bool
proto_is_tcp(int proto)
{
if (proto < 0 || proto >= PROTO_N)
ASSERT(0);
- return (!proto_names[proto].is_dgram)&&proto_names[proto].is_net;
-}
-
-unsigned short
-proto_sa_family(int proto)
-{
- if (proto < 0 || proto >= PROTO_N)
- ASSERT(0);
- return proto_names[proto].proto_af;
+ return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER || proto == PROTO_TCP_CLIENT;
}
int
ascii2proto (const char* proto_name)
{
int i;
- ASSERT (PROTO_N == SIZE (proto_names));
- for (i = 0; i < PROTO_N; ++i)
+ for (i = 0; i < SIZE (proto_names); ++i)
if (!strcmp (proto_name, proto_names[i].short_form))
- return i;
+ return proto_names[i].proto;
return -1;
}
+sa_family_t
+ascii2af (const char* proto_name)
+{
+ int i;
+ for (i = 0; i < SIZE (proto_names); ++i)
+ if (!strcmp (proto_name, proto_names[i].short_form))
+ return proto_names[i].proto_af;
+ return 0;
+}
+
const char *
-proto2ascii (int proto, bool display_form)
+proto2ascii (int proto, sa_family_t af, bool display_form)
{
- ASSERT (PROTO_N == SIZE (proto_names));
- if (proto < 0 || proto >= PROTO_N)
- return "[unknown protocol]";
- else if (display_form)
- return proto_names[proto].display_form;
- else
- return proto_names[proto].short_form;
+ unsigned int i;
+ for (i = 0; i < SIZE (proto_names); ++i)
+ {
+ if(proto_names[i].proto_af == af && proto_names[i].proto == proto)
+ {
+ if(display_form)
+ return proto_names[i].display_form;
+ else
+ return proto_names[i].short_form;
+ }
+ }
+
+ return "[unknown protocol]";
}
const char *
@@ -2518,23 +2493,22 @@ proto2ascii_all (struct gc_arena *gc)
struct buffer out = alloc_buf_gc (256, gc);
int i;
- ASSERT (PROTO_N == SIZE (proto_names));
- for (i = 0; i < PROTO_N; ++i)
+ for (i = 0; i < SIZE (proto_names); ++i)
{
if (i)
buf_printf(&out, " ");
- buf_printf(&out, "[%s]", proto2ascii(i, false));
+ buf_printf(&out, "[%s]", proto_names[i].short_form);
}
return BSTR (&out);
}
int
-addr_guess_family(int proto, const char *name)
+addr_guess_family(sa_family_t af, const char *name)
{
unsigned short ret;
- if (proto)
+ if (af)
{
- return proto_sa_family(proto); /* already stamped */
+ return af; /* already stamped */
}
else
{
@@ -2570,6 +2544,10 @@ addr_family_name (int af)
*
* This is used for options compatibility
* checking.
+ *
+ * IPv6 and IPv4 protocols are comptabile but OpenVPN
+ * has always sent UDPv4, TCPv4 over the wire. Keep these
+ * strings for backward compatbility
*/
int
proto_remote (int proto, bool remote)
@@ -2579,10 +2557,8 @@ proto_remote (int proto, bool remote)
{
switch (proto)
{
- case PROTO_TCPv4_SERVER: return PROTO_TCPv4_CLIENT;
- case PROTO_TCPv4_CLIENT: return PROTO_TCPv4_SERVER;
- case PROTO_TCPv6_SERVER: return PROTO_TCPv6_CLIENT;
- case PROTO_TCPv6_CLIENT: return PROTO_TCPv6_SERVER;
+ case PROTO_TCP_SERVER: return PROTO_TCP_CLIENT;
+ case PROTO_TCP_CLIENT: return PROTO_TCP_SERVER;
}
}
return proto;
@@ -2733,7 +2709,7 @@ link_socket_read_udp_posix (struct link_socket *sock,
struct link_socket_actual *from)
{
socklen_t fromlen = sizeof (from->dest.addr);
- socklen_t expectedlen = af_addr_size(proto_sa_family(sock->info.proto));
+ socklen_t expectedlen = af_addr_size(sock->info.af);
addr_zero_host(&from->dest);
ASSERT (buf_safe (buf, maxsize));
#if ENABLE_IP_PKTINFO
@@ -2774,7 +2750,7 @@ link_socket_write_tcp (struct link_socket *sock,
#if ENABLE_IP_PKTINFO
-int
+size_t
link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to)
@@ -2787,7 +2763,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
iov.iov_len = BLEN (buf);
mesg.msg_iov = &iov;
mesg.msg_iovlen = 1;
- switch (sock->info.lsa->remote.addr.sa.sa_family)
+ switch (to->ai_family)
{
case AF_INET:
{
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index 44f1098b..ae6cb9bc 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -39,7 +39,7 @@
/*
* OpenVPN's default port number as assigned by IANA.
*/
-#define OPENVPN_PORT 1194
+#define OPENVPN_PORT "1194"
/*
* Maximum size passed passed to setsockopt SNDBUF/RCVBUF
@@ -81,6 +81,11 @@ struct openvpn_sockaddr
struct link_socket_actual
{
/*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+
+
struct openvpn_sockaddr dest;
#if ENABLE_IP_PKTINFO
union {
@@ -97,8 +102,10 @@ struct link_socket_actual
/* IP addresses which are persistant across SIGUSR1s */
struct link_socket_addr
{
- struct openvpn_sockaddr local;
- struct openvpn_sockaddr remote; /* initial remote */
+ struct addrinfo* bind_local;
+ struct addrinfo* remote_list; /* complete remote list */
+ struct addrinfo* current_remote; /* remote used in the
+ current connection attempt */
struct link_socket_actual actual; /* reply to this address */
};
@@ -110,6 +117,7 @@ struct link_socket_info
const struct plugin_list *plugins;
bool remote_float;
int proto; /* Protocol (PROTO_x defined below) */
+ sa_family_t af; /* Address family like AF_INET, AF_INET6 or AF_UNSPEC*/
int mtu_changed; /* Set to true when mtu value is changed */
};
@@ -175,13 +183,10 @@ struct link_socket
/* used for long-term queueing of pre-accepted socket listen */
bool listen_persistent_queued;
- /* Does config file contain any <connection> ... </connection> blocks? */
- bool connection_profiles_defined;
-
const char *remote_host;
- int remote_port;
+ const char *remote_port;
const char *local_host;
- int local_port;
+ const char *local_port;
bool bind_local;
# define INETD_NONE 0
@@ -195,9 +200,7 @@ struct link_socket
int mode;
int resolve_retry_seconds;
- int connect_retry_seconds;
int connect_timeout;
- int connect_retry_max;
int mtu_discover_type;
struct socket_buffer_size socket_buffer_sizes;
@@ -232,7 +235,7 @@ struct link_socket
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_SOCKS)
/* The OpenVPN server we will use the proxy to connect to */
const char *proxy_dest_host;
- int proxy_dest_port;
+ const char *proxy_dest_port;
#endif
#if PASSTOS_CAPABILITY
@@ -279,11 +282,12 @@ int socket_finalize (
struct link_socket *link_socket_new (void);
void socket_bind (socket_descriptor_t sd,
- struct openvpn_sockaddr *local,
+ struct addrinfo *local,
+ int af_family,
const char *prefix);
int openvpn_connect (socket_descriptor_t sd,
- struct openvpn_sockaddr *remote,
+ const struct sockaddr *remote,
int connect_timeout,
volatile int *signal_received);
@@ -293,12 +297,12 @@ int openvpn_connect (socket_descriptor_t sd,
void
link_socket_init_phase1 (struct link_socket *sock,
- const bool connection_profiles_defined,
const char *local_host,
- int local_port,
+ const char *local_port,
const char *remote_host,
- int remote_port,
+ const char *remote_port,
int proto,
+ sa_family_t af,
int mode,
const struct link_socket *accept_from,
#ifdef ENABLE_HTTP_PROXY
@@ -317,9 +321,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *ipchange_command,
const struct plugin_list *plugins,
int resolve_retry_seconds,
- int connect_retry_seconds,
int connect_timeout,
- int connect_retry_max,
int mtu_discover_type,
int rcvbuf,
int sndbuf,
@@ -328,7 +330,7 @@ link_socket_init_phase1 (struct link_socket *sock,
void link_socket_init_phase2 (struct link_socket *sock,
const struct frame *frame,
- volatile int *signal_received);
+ struct signal_info *sig_info);
void socket_adjust_frame_parameters (struct frame *frame, int proto);
@@ -343,14 +345,35 @@ void sd_close (socket_descriptor_t *sd);
#define PS_SHOW_PKTINFO (1<<2)
#define PS_DONT_SHOW_ADDR (1<<3)
-const char *print_sockaddr_ex (const struct openvpn_sockaddr *addr,
+const char *print_sockaddr_ex (const struct sockaddr *addr,
const char* separator,
const unsigned int flags,
struct gc_arena *gc);
+static inline
+const char *print_openvpn_sockaddr_ex (const struct openvpn_sockaddr *addr,
+ const char* separator,
+ const unsigned int flags,
+ struct gc_arena *gc)
+{
+ return print_sockaddr_ex(&addr->addr.sa, separator, flags, gc);
+}
+
+static inline
+const char *print_openvpn_sockaddr (const struct openvpn_sockaddr *addr,
+ struct gc_arena *gc)
+{
+ return print_sockaddr_ex (&addr->addr.sa, ":", PS_SHOW_PORT, gc);
+}
+
+static inline
+const char *print_sockaddr (const struct sockaddr *addr,
+ struct gc_arena *gc)
+{
+ return print_sockaddr_ex (addr, ":", PS_SHOW_PORT, gc);
+}
+
-const char *print_sockaddr (const struct openvpn_sockaddr *addr,
- struct gc_arena *gc);
const char *print_link_socket_actual_ex (const struct link_socket_actual *act,
const char* separator,
@@ -402,6 +425,9 @@ void link_socket_bad_incoming_addr (struct buffer *buf,
const struct link_socket_info *info,
const struct link_socket_actual *from_addr);
+void set_actual_address (struct link_socket_actual* actual,
+ struct addrinfo* ai);
+
void link_socket_bad_outgoing_addr (void);
void setenv_trusted (struct env_set *es, const struct link_socket_info *info);
@@ -477,11 +503,8 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
#define GETADDR_TRY_ONCE (1<<7)
#define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8)
#define GETADDR_RANDOMIZE (1<<9)
-
-/* [ab]use flags bits to get socktype info downstream */
-/* TODO(jjo): resolve tradeoff between hackiness|args-overhead */
-#define GETADDR_DGRAM (1<<10)
-#define dnsflags_to_socktype(flags) ((flags & GETADDR_DGRAM) ? SOCK_DGRAM : SOCK_STREAM)
+#define GETADDR_PASSIVE (1<<10)
+#define GETADDR_DATAGRAM (1<<11)
in_addr_t getaddr (unsigned int flags,
const char *hostname,
@@ -491,6 +514,7 @@ in_addr_t getaddr (unsigned int flags,
int openvpn_getaddrinfo (unsigned int flags,
const char *hostname,
+ const char *servname,
int resolve_retry_seconds,
volatile int *signal_received,
int ai_family,
@@ -506,19 +530,16 @@ int openvpn_getaddrinfo (unsigned int flags,
*/
enum proto_num {
PROTO_NONE, /* catch for uninitialized */
- PROTO_UDPv4,
- PROTO_TCPv4_SERVER,
- PROTO_TCPv4_CLIENT,
- PROTO_TCPv4,
- PROTO_UDPv6,
- PROTO_TCPv6_SERVER,
- PROTO_TCPv6_CLIENT,
- PROTO_TCPv6,
+ PROTO_UDP,
+ PROTO_TCP,
+ PROTO_TCP_SERVER,
+ PROTO_TCP_CLIENT,
PROTO_N
};
int ascii2proto (const char* proto_name);
-const char *proto2ascii (int proto, bool display_form);
+sa_family_t ascii2af (const char* proto_name);
+const char *proto2ascii (int proto, sa_family_t af, bool display_form);
const char *proto2ascii_all (struct gc_arena *gc);
int proto_remote (int proto, bool remote);
const char *addr_family_name(int af);
@@ -545,12 +566,6 @@ datagram_overhead (int proto)
*/
static inline bool
-legal_ipv4_port (int port)
-{
- return port > 0 && port < 65536;
-}
-
-static inline bool
link_socket_proto_connection_oriented (int proto)
{
return !proto_is_dgram(proto);
@@ -604,13 +619,35 @@ link_socket_actual_defined (const struct link_socket_actual *act)
static inline bool
addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
{
- switch(a1->addr.sa.sa_family) {
+ switch(a1->addr.sa.sa_family) {
+ case AF_INET:
+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr;
+ case AF_INET6:
+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr);
+ }
+ ASSERT(0);
+ return false;
+}
+
+static inline bool
+addrlist_match (const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist)
+{
+ const struct addrinfo *curele;
+ for (curele = addrlist; curele; curele=curele->ai_next) {
+
+ switch(a1->addr.sa.sa_family) {
case AF_INET:
- return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr;
+ if (a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr)
+ return true;
+ break;
case AF_INET6:
- return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr);
+ if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr))
+ return true;
+ break;
+ default:
+ ASSERT(0);
+ }
}
- ASSERT(0);
return false;
}
@@ -627,6 +664,34 @@ addr_host (const struct openvpn_sockaddr *addr)
return ntohl (addr->addr.in4.sin_addr.s_addr);
}
+
+static inline bool
+addrlist_port_match (const struct openvpn_sockaddr *a1, const struct addrinfo *a2)
+{
+ const struct addrinfo *curele;
+ for(curele=a2;curele;curele = curele->ai_next) {
+ switch(a1->addr.sa.sa_family) {
+ case AF_INET:
+ if (curele->ai_family == AF_INET
+ && a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr
+ && a1->addr.in4.sin_port == ((struct sockaddr_in*)curele->ai_addr)->sin_port)
+ return true;
+ break;
+ case AF_INET6:
+ if (curele->ai_family == AF_INET6
+ && IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr)
+ && a1->addr.in6.sin6_port == ((struct sockaddr_in6*) curele->ai_addr)->sin6_port)
+ return true;
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+ return false;
+}
+
+
+
static inline bool
addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
{
@@ -644,14 +709,25 @@ addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockadd
static inline bool
addr_match_proto (const struct openvpn_sockaddr *a1,
- const struct openvpn_sockaddr *a2,
- const int proto)
+ const struct openvpn_sockaddr *a2,
+ const int proto)
{
- return link_socket_proto_connection_oriented (proto)
+ return link_socket_proto_connection_oriented (proto)
? addr_match (a1, a2)
: addr_port_match (a1, a2);
}
+
+static inline bool
+addrlist_match_proto (const struct openvpn_sockaddr *a1,
+ struct addrinfo *addr_list,
+ const int proto)
+{
+ return link_socket_proto_connection_oriented (proto)
+ ? addrlist_match (a1, addr_list)
+ : addrlist_port_match (a1, addr_list);
+}
+
static inline void
addr_zero_host(struct openvpn_sockaddr *addr)
{
@@ -671,28 +747,15 @@ addr_copy_sa(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src)
dst->addr = src->addr;
}
-static inline void
-addr_copy_host(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src)
-{
- switch(src->addr.sa.sa_family) {
- case AF_INET:
- dst->addr.in4.sin_addr.s_addr = src->addr.in4.sin_addr.s_addr;
- break;
- case AF_INET6:
- dst->addr.in6.sin6_addr = src->addr.in6.sin6_addr;
- break;
- }
-}
-
static inline bool
addr_inet4or6(struct sockaddr *addr)
{
return addr->sa_family == AF_INET || addr->sa_family == AF_INET6;
}
-int addr_guess_family(int proto, const char *name);
+int addr_guess_family(sa_family_t af,const char *name);
static inline int
-af_addr_size(unsigned short af)
+af_addr_size(sa_family_t af)
{
switch(af) {
case AF_INET: return sizeof (struct sockaddr_in);
@@ -768,9 +831,9 @@ link_socket_verify_incoming_addr (struct buffer *buf,
case AF_INET:
if (!link_socket_actual_defined (from_addr))
return false;
- if (info->remote_float || !addr_defined (&info->lsa->remote))
+ if (info->remote_float || !info->lsa->remote_list)
return true;
- if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto))
+ if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto))
return true;
}
}
@@ -812,8 +875,8 @@ link_socket_set_outgoing_addr (const struct buffer *buf,
|| !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
/* address undef or address == remote or --float */
&& (info->remote_float
- || !addr_defined (&lsa->remote)
- || addr_match_proto (&act->dest, &lsa->remote, info->proto))
+ || !lsa->remote_list)
+ || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)
)
{
link_socket_connection_initiated (buf, info, act, common_name, es);
@@ -937,13 +1000,13 @@ link_socket_write_win32 (struct link_socket *sock,
#else
-static inline int
+static inline size_t
link_socket_write_udp_posix (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to)
{
#if ENABLE_IP_PKTINFO
- int link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
+ size_t link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to);
@@ -957,7 +1020,7 @@ link_socket_write_udp_posix (struct link_socket *sock,
(socklen_t) af_addr_size(to->dest.addr.sa.sa_family));
}
-static inline int
+static inline size_t
link_socket_write_tcp_posix (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to)
@@ -967,7 +1030,7 @@ link_socket_write_tcp_posix (struct link_socket *sock,
#endif
-static inline int
+static inline size_t
link_socket_write_udp (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to)
diff --git a/openvpn/src/openvpn/socks.c b/openvpn/src/openvpn/socks.c
index 235982e4..804c9836 100644
--- a/openvpn/src/openvpn/socks.c
+++ b/openvpn/src/openvpn/socks.c
@@ -55,13 +55,13 @@
void
socks_adjust_frame_parameters (struct frame *frame, int proto)
{
- if (proto == PROTO_UDPv4)
+ if (proto == PROTO_UDP)
frame_add_to_extra_link (frame, 10);
}
struct socks_proxy_info *
socks_proxy_new (const char *server,
- int port,
+ const char *port,
const char *authfile,
bool retry)
{
@@ -70,7 +70,7 @@ socks_proxy_new (const char *server,
ALLOC_OBJ_CLEAR (p, struct socks_proxy_info);
ASSERT (server);
- ASSERT (legal_ipv4_port (port));
+ ASSERT (port);
strncpynt (p->server, server, sizeof (p->server));
p->port = port;
@@ -389,11 +389,27 @@ recv_socks_reply (socket_descriptor_t sd,
return true;
}
+static int
+port_from_servname(const char* servname)
+{
+ int port =0;
+ port = atoi(servname);
+ if(port >0 && port < 65536)
+ return port;
+
+ struct servent* service;
+ service = getservbyname(servname, NULL);
+ if(service)
+ return service->s_port;
+
+ return 0;
+}
+
void
establish_socks_proxy_passthru (struct socks_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */
const char *host, /* openvpn server remote */
- const int port, /* openvpn server port */
+ const char *servname, /* openvpn server port */
volatile int *signal_received)
{
char buf[128];
@@ -414,6 +430,13 @@ establish_socks_proxy_passthru (struct socks_proxy_info *p,
buf[4] = (char) len;
memcpy(buf + 5, host, len);
+ int port = port_from_servname (servname);
+ if (port ==0)
+ {
+ msg (D_LINK_ERRORS, "establish_socks_proxy_passthrough: Cannot convert %s to port number", servname);
+ goto error;
+ }
+
buf[5 + len] = (char) (port >> 8);
buf[5 + len + 1] = (char) (port & 0xff);
@@ -425,6 +448,7 @@ establish_socks_proxy_passthru (struct socks_proxy_info *p,
goto error;
}
}
+
/* receive reply from Socks proxy and discard */
if (!recv_socks_reply (sd, NULL, signal_received))
diff --git a/openvpn/src/openvpn/socks.h b/openvpn/src/openvpn/socks.h
index b55ff6fb..30b957d7 100644
--- a/openvpn/src/openvpn/socks.h
+++ b/openvpn/src/openvpn/socks.h
@@ -42,14 +42,14 @@ struct socks_proxy_info {
bool retry;
char server[128];
- int port;
+ const char *port;
char authfile[256];
};
void socks_adjust_frame_parameters (struct frame *frame, int proto);
struct socks_proxy_info *socks_proxy_new (const char *server,
- int port,
+ const char *port,
const char *authfile,
bool retry);
@@ -58,7 +58,7 @@ void socks_proxy_close (struct socks_proxy_info *sp);
void establish_socks_proxy_passthru (struct socks_proxy_info *p,
socket_descriptor_t sd, /* already open to proxy */
const char *host, /* openvpn server remote */
- const int port, /* openvpn server port */
+ const char *servname, /* openvpn server port */
volatile int *signal_received);
void establish_socks_proxy_udpassoc (struct socks_proxy_info *p,
diff --git a/openvpn/src/openvpn/ssl_polarssl.c b/openvpn/src/openvpn/ssl_polarssl.c
index 6995958b..12318b33 100644
--- a/openvpn/src/openvpn/ssl_polarssl.c
+++ b/openvpn/src/openvpn/ssl_polarssl.c
@@ -338,7 +338,7 @@ void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline)
{
- if (0 != x509parse_crt(ctx->ca_chain, ca_file_inline, strlen(ca_file_inline)));
+ if (0 != x509parse_crt(ctx->ca_chain, ca_file_inline, strlen(ca_file_inline)))
msg (M_FATAL, "Cannot load inline CA certificates");
}
else
diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c
index 1b2e5822..a0754427 100644
--- a/openvpn/src/openvpn/tun.c
+++ b/openvpn/src/openvpn/tun.c
@@ -413,8 +413,8 @@ init_tun (const char *dev, /* --dev option */
const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
int ifconfig_ipv6_netbits_parm,
const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
- in_addr_t local_public,
- in_addr_t remote_public,
+ struct addrinfo *local_public,
+ struct addrinfo *remote_public,
const bool strict_warn,
struct env_set *es)
{
@@ -468,24 +468,31 @@ init_tun (const char *dev, /* --dev option */
*/
if (strict_warn)
{
+ struct addrinfo *curele;
ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);
/*
* If local_public or remote_public addresses are defined,
* make sure they do not clash with our virtual subnet.
*/
-
- check_addr_clash ("local",
+
+ for(curele=remote_public;curele;curele=curele->ai_next) {
+ if(curele->ai_family == AF_INET)
+ check_addr_clash ("local",
tt->type,
- local_public,
+ ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr,
tt->local,
tt->remote_netmask);
+ }
- check_addr_clash ("remote",
- tt->type,
- remote_public,
- tt->local,
- tt->remote_netmask);
+ for(curele=remote_public;curele;curele=curele->ai_next) {
+ if(curele->ai_family == AF_INET)
+ check_addr_clash ("remote",
+ tt->type,
+ ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr,
+ tt->local,
+ tt->remote_netmask);
+ }
if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
check_subnet_conflict (tt->local, tt->remote_netmask, "TUN/TAP adapter");
@@ -1405,7 +1412,7 @@ close_tun_generic (struct tuntap *tt)
if (tt->fd >= 0)
close (tt->fd);
if (tt->actual_name)
- free (tt->actual_name);
+ free (tt->actual_name);
clear_tuntap (tt);
}
@@ -1439,8 +1446,8 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu
msg (M_ERR, "ERROR: Cannot open TUN");
}
/* Set the actual name to a dummy name to enable scripts */
- tt->actual_name = (char *) malloc(32);
- strncpy(tt->actual_name, "vpnservice-tun",32);
+ tt->actual_name = (char *) malloc(32);
+ strncpy(tt->actual_name, "vpnservice-tun",32);
gc_free (&gc);
}
diff --git a/openvpn/src/openvpn/tun.h b/openvpn/src/openvpn/tun.h
index c31ac001..e7d941ab 100644
--- a/openvpn/src/openvpn/tun.h
+++ b/openvpn/src/openvpn/tun.h
@@ -231,8 +231,8 @@ struct tuntap *init_tun (const char *dev, /* --dev option */
const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 / IPv6 */
int ifconfig_ipv6_netbits_parm, /* --ifconfig parm 1 / bits */
const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 / IPv6 */
- in_addr_t local_public,
- in_addr_t remote_public,
+ struct addrinfo *local_public,
+ struct addrinfo *remote_public,
const bool strict_warn,
struct env_set *es);
diff --git a/openvpn/src/openvpn/win32.c b/openvpn/src/openvpn/win32.c
index d00088eb..2db96a8d 100644
--- a/openvpn/src/openvpn/win32.c
+++ b/openvpn/src/openvpn/win32.c
@@ -82,51 +82,6 @@ struct semaphore netcmd_semaphore; /* GLOBAL */
*/
static char *win_sys_path = NULL; /* GLOBAL */
-/*
- * Configure PATH. On Windows, sometimes PATH is not set correctly
- * by default.
- */
-static void
-configure_win_path (void)
-{
- static bool done = false; /* GLOBAL */
- if (!done)
- {
- FILE *fp;
- fp = fopen ("c:\\windows\\system32\\route.exe", "rb");
- if (fp)
- {
- const int bufsiz = 4096;
- struct gc_arena gc = gc_new ();
- struct buffer oldpath = alloc_buf_gc (bufsiz, &gc);
- struct buffer newpath = alloc_buf_gc (bufsiz, &gc);
- const char* delim = ";";
- DWORD status;
- fclose (fp);
- status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
-#if 0
- status = 0;
-#endif
- if (!status)
- {
- *BPTR(&oldpath) = '\0';
- delim = "";
- }
- buf_printf (&newpath, "C:\\WINDOWS\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem%s%s",
- delim,
- BSTR(&oldpath));
- SetEnvironmentVariable ("PATH", BSTR(&newpath));
-#if 0
- status = GetEnvironmentVariable ("PATH", BPTR(&oldpath), (DWORD)BCAP(&oldpath));
- if (status > 0)
- printf ("PATH: %s\n", BSTR(&oldpath));
-#endif
- gc_free (&gc);
- done = true;
- }
- }
-}
-
void
init_win32 (void)
{
@@ -907,53 +862,41 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
{
if (openvpn_execve_allowed (flags))
{
- if (script_method == SM_EXECVE)
- {
- struct gc_arena gc = gc_new ();
- STARTUPINFOW start_info;
- PROCESS_INFORMATION proc_info;
-
- char *env = env_block (es);
- WCHAR *cl = wide_cmd_line (a, &gc);
- WCHAR *cmd = wide_string (a->argv[0], &gc);
-
- CLEAR (start_info);
- CLEAR (proc_info);
-
- /* fill in STARTUPINFO struct */
- GetStartupInfoW(&start_info);
- start_info.cb = sizeof(start_info);
- start_info.dwFlags = STARTF_USESHOWWINDOW;
- start_info.wShowWindow = SW_HIDE;
-
- if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
- {
- DWORD exit_status = 0;
- CloseHandle (proc_info.hThread);
- WaitForSingleObject (proc_info.hProcess, INFINITE);
- if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
- ret = (int)exit_status;
- else
- msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %S failed", cmd);
- CloseHandle (proc_info.hProcess);
- }
- else
- {
- msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %S failed", cmd);
- }
- free (env);
- gc_free (&gc);
- }
- else if (script_method == SM_SYSTEM)
- {
- configure_win_path ();
- ret = openvpn_system (argv_system_str (a), es, flags);
- }
- else
- {
- ASSERT (0);
- }
- }
+ struct gc_arena gc = gc_new ();
+ STARTUPINFOW start_info;
+ PROCESS_INFORMATION proc_info;
+
+ char *env = env_block (es);
+ WCHAR *cl = wide_cmd_line (a, &gc);
+ WCHAR *cmd = wide_string (a->argv[0], &gc);
+
+ CLEAR (start_info);
+ CLEAR (proc_info);
+
+ /* fill in STARTUPINFO struct */
+ GetStartupInfoW(&start_info);
+ start_info.cb = sizeof(start_info);
+ start_info.dwFlags = STARTF_USESHOWWINDOW;
+ start_info.wShowWindow = SW_HIDE;
+
+ if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info))
+ {
+ DWORD exit_status = 0;
+ CloseHandle (proc_info.hThread);
+ WaitForSingleObject (proc_info.hProcess, INFINITE);
+ if (GetExitCodeProcess (proc_info.hProcess, &exit_status))
+ ret = (int)exit_status;
+ else
+ msg (M_WARN|M_ERRNO, "openvpn_execve: GetExitCodeProcess %S failed", cmd);
+ CloseHandle (proc_info.hProcess);
+ }
+ else
+ {
+ msg (M_WARN|M_ERRNO, "openvpn_execve: CreateProcess %S failed", cmd);
+ }
+ free (env);
+ gc_free (&gc);
+ }
else if (!exec_warn && (script_security < SSEC_SCRIPTS))
{
msg (M_WARN, SCRIPT_SECURITY_WARNING);