summaryrefslogtreecommitdiff
path: root/src/openvpn/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/socket.c')
-rw-r--r--src/openvpn/socket.c5361
1 files changed, 2884 insertions, 2477 deletions
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index c233f2b..ae12832 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -45,14 +45,14 @@
#include "memdbg.h"
const int proto_overhead[] = { /* indexed by PROTO_x */
- 0,
- IPv4_UDP_HEADER_SIZE, /* IPv4 */
- IPv4_TCP_HEADER_SIZE,
- IPv4_TCP_HEADER_SIZE,
- IPv6_UDP_HEADER_SIZE, /* IPv6 */
- IPv6_TCP_HEADER_SIZE,
- IPv6_TCP_HEADER_SIZE,
- IPv6_TCP_HEADER_SIZE,
+ 0,
+ IPv4_UDP_HEADER_SIZE, /* IPv4 */
+ IPv4_TCP_HEADER_SIZE,
+ IPv4_TCP_HEADER_SIZE,
+ IPv6_UDP_HEADER_SIZE, /* IPv6 */
+ IPv6_TCP_HEADER_SIZE,
+ IPv6_TCP_HEADER_SIZE,
+ IPv6_TCP_HEADER_SIZE,
};
/*
@@ -62,10 +62,14 @@ static unsigned int
sf2gaf(const unsigned int getaddr_flags,
const unsigned int sockflags)
{
- if (sockflags & SF_HOST_RANDOMIZE)
- return getaddr_flags | GETADDR_RANDOMIZE;
- else
- return getaddr_flags;
+ if (sockflags & SF_HOST_RANDOMIZE)
+ {
+ return getaddr_flags | GETADDR_RANDOMIZE;
+ }
+ else
+ {
+ return getaddr_flags;
+ }
}
/*
@@ -78,201 +82,232 @@ sf2gaf(const unsigned int getaddr_flags,
* resolve_retry_seconds seconds.
*/
in_addr_t
-getaddr (unsigned int flags,
- const char *hostname,
- int resolve_retry_seconds,
- bool *succeeded,
- volatile int *signal_received)
-{
- struct addrinfo *ai;
- int status;
- 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)
- *succeeded=true;
- ia = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
- freeaddrinfo(ai);
- return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr;
- } else {
- if(succeeded)
- *succeeded =false;
- return 0;
- }
+getaddr(unsigned int flags,
+ const char *hostname,
+ int resolve_retry_seconds,
+ bool *succeeded,
+ volatile int *signal_received)
+{
+ struct addrinfo *ai;
+ int status;
+ 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)
+ {
+ *succeeded = true;
+ }
+ ia = ((struct sockaddr_in *)ai->ai_addr)->sin_addr;
+ freeaddrinfo(ai);
+ return (flags & GETADDR_HOST_ORDER) ? ntohl(ia.s_addr) : ia.s_addr;
+ }
+ else
+ {
+ if (succeeded)
+ {
+ *succeeded = false;
+ }
+ return 0;
+ }
}
static inline bool
-streqnull (const char* a, const char* b)
+streqnull(const char *a, const char *b)
{
- if (a == NULL && b == NULL)
- return true;
- else if (a == NULL || b == NULL)
- return false;
- else
- return streq (a, b);
+ if (a == NULL && b == NULL)
+ {
+ return true;
+ }
+ else if (a == NULL || b == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ return streq(a, b);
+ }
}
/*
- get_cached_dns_entry return 0 on success and -1
- otherwise. (like getaddrinfo)
+ * get_cached_dns_entry return 0 on success and -1
+ * otherwise. (like getaddrinfo)
*/
static int
-get_cached_dns_entry (struct cached_dns_entry* dns_cache,
- const char* hostname,
- const char* servname,
- int ai_family,
- int resolve_flags,
- struct addrinfo **ai)
+get_cached_dns_entry(struct cached_dns_entry *dns_cache,
+ const char *hostname,
+ const char *servname,
+ int ai_family,
+ int resolve_flags,
+ struct addrinfo **ai)
{
- struct cached_dns_entry *ph;
- int flags;
+ struct cached_dns_entry *ph;
+ int flags;
- /* Only use flags that are relevant for the structure */
- flags = resolve_flags & GETADDR_CACHE_MASK;
+ /* Only use flags that are relevant for the structure */
+ flags = resolve_flags & GETADDR_CACHE_MASK;
- for (ph = dns_cache; ph ; ph = ph->next)
+ for (ph = dns_cache; ph; ph = ph->next)
{
- if (streqnull (ph->hostname, hostname) &&
- streqnull (ph->servname, servname) &&
- ph->ai_family == ai_family &&
- ph->flags == flags)
- {
- *ai = ph->ai;
- return 0;
- }
+ if (streqnull(ph->hostname, hostname)
+ && streqnull(ph->servname, servname)
+ && ph->ai_family == ai_family
+ && ph->flags == flags)
+ {
+ *ai = ph->ai;
+ return 0;
+ }
}
- return -1;
+ return -1;
}
static int
-do_preresolve_host (struct context *c,
- const char *hostname,
- const char *servname,
- const int af,
- const int flags)
+do_preresolve_host(struct context *c,
+ const char *hostname,
+ const char *servname,
+ const int af,
+ const int flags)
{
- struct addrinfo *ai;
- int status;
+ struct addrinfo *ai;
+ int status;
- if (get_cached_dns_entry(c->c1.dns_cache,
- hostname,
- servname,
- af,
- flags,
- &ai) == 0 )
+ if (get_cached_dns_entry(c->c1.dns_cache,
+ hostname,
+ servname,
+ af,
+ flags,
+ &ai) == 0)
{
- /* entry already cached, return success */
- return 0;
+ /* entry already cached, return success */
+ return 0;
}
- status = openvpn_getaddrinfo (flags, hostname, servname,
- c->options.resolve_retry_seconds, NULL,
- af, &ai);
- if (status == 0)
+ status = openvpn_getaddrinfo(flags, hostname, servname,
+ c->options.resolve_retry_seconds, NULL,
+ af, &ai);
+ if (status == 0)
{
- struct cached_dns_entry *ph;
+ struct cached_dns_entry *ph;
- ALLOC_OBJ_CLEAR_GC (ph, struct cached_dns_entry, &c->gc);
- ph->ai = ai;
- ph->hostname = hostname;
- ph->servname = servname;
- ph->flags = flags & GETADDR_CACHE_MASK;
+ ALLOC_OBJ_CLEAR_GC(ph, struct cached_dns_entry, &c->gc);
+ ph->ai = ai;
+ ph->hostname = hostname;
+ ph->servname = servname;
+ ph->flags = flags & GETADDR_CACHE_MASK;
- if (!c->c1.dns_cache)
- c->c1.dns_cache = ph;
- else
- {
- struct cached_dns_entry *prev = c->c1.dns_cache;
- while (prev->next)
- prev = prev->next;
- prev->next = ph;
- }
+ if (!c->c1.dns_cache)
+ {
+ c->c1.dns_cache = ph;
+ }
+ else
+ {
+ struct cached_dns_entry *prev = c->c1.dns_cache;
+ while (prev->next)
+ prev = prev->next;
+ prev->next = ph;
+ }
- gc_addspecial (ai, &gc_freeaddrinfo_callback, &c->gc);
+ gc_addspecial(ai, &gc_freeaddrinfo_callback, &c->gc);
}
- return status;
+ return status;
}
void
-do_preresolve (struct context *c)
-{
- int i;
- struct connection_list *l = c->options.connection_list;
- const unsigned int preresolve_flags = GETADDR_RESOLVE|
- GETADDR_UPDATE_MANAGEMENT_STATE|
- GETADDR_MENTION_RESOLVE_RETRY|
- GETADDR_FATAL;
-
-
- for (i = 0; i < l->len; ++i)
- {
- int status;
- const char *remote;
- int flags = preresolve_flags;
-
- struct connection_entry* ce = c->options.connection_list->array[i];
-
- if (proto_is_dgram(ce->proto))
- flags |= GETADDR_DATAGRAM;
-
- if (c->options.sockflags & SF_HOST_RANDOMIZE)
- flags |= GETADDR_RANDOMIZE;
-
- if (c->options.ip_remote_hint)
- remote = c->options.ip_remote_hint;
- else
- remote = ce->remote;
-
- /* HTTP remote hostname does not need to be resolved */
- if (! ce->http_proxy_options)
- {
- status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags);
- if (status != 0)
- goto err;
- }
-
- /* Preresolve proxy */
- if (ce->http_proxy_options)
- {
- status = do_preresolve_host (c,
- ce->http_proxy_options->server,
- ce->http_proxy_options->port,
- ce->af,
- preresolve_flags);
-
- if (status != 0)
- goto err;
- }
-
- if (ce->socks_proxy_server)
- {
- status = do_preresolve_host (c,
- ce->socks_proxy_server,
- ce->socks_proxy_port,
- ce->af,
- flags);
- if (status != 0)
- goto err;
- }
-
- if (ce->bind_local)
- {
- flags |= GETADDR_PASSIVE;
- flags &= ~GETADDR_RANDOMIZE;
- status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags);
- if (status != 0)
- goto err;
-
- }
+do_preresolve(struct context *c)
+{
+ int i;
+ struct connection_list *l = c->options.connection_list;
+ const unsigned int preresolve_flags = GETADDR_RESOLVE
+ |GETADDR_UPDATE_MANAGEMENT_STATE
+ |GETADDR_MENTION_RESOLVE_RETRY
+ |GETADDR_FATAL;
+
+
+ for (i = 0; i < l->len; ++i)
+ {
+ int status;
+ const char *remote;
+ int flags = preresolve_flags;
+
+ struct connection_entry *ce = c->options.connection_list->array[i];
+
+ if (proto_is_dgram(ce->proto))
+ {
+ flags |= GETADDR_DATAGRAM;
+ }
+
+ if (c->options.sockflags & SF_HOST_RANDOMIZE)
+ {
+ flags |= GETADDR_RANDOMIZE;
+ }
+
+ if (c->options.ip_remote_hint)
+ {
+ remote = c->options.ip_remote_hint;
+ }
+ else
+ {
+ remote = ce->remote;
+ }
+
+ /* HTTP remote hostname does not need to be resolved */
+ if (!ce->http_proxy_options)
+ {
+ status = do_preresolve_host(c, remote, ce->remote_port, ce->af, flags);
+ if (status != 0)
+ {
+ goto err;
+ }
+ }
+
+ /* Preresolve proxy */
+ if (ce->http_proxy_options)
+ {
+ status = do_preresolve_host(c,
+ ce->http_proxy_options->server,
+ ce->http_proxy_options->port,
+ ce->af,
+ preresolve_flags);
+
+ if (status != 0)
+ {
+ goto err;
+ }
+ }
+
+ if (ce->socks_proxy_server)
+ {
+ status = do_preresolve_host(c,
+ ce->socks_proxy_server,
+ ce->socks_proxy_port,
+ ce->af,
+ flags);
+ if (status != 0)
+ {
+ goto err;
+ }
+ }
+
+ if (ce->bind_local)
+ {
+ flags |= GETADDR_PASSIVE;
+ flags &= ~GETADDR_RANDOMIZE;
+ status = do_preresolve_host(c, ce->local, ce->local_port, ce->af, flags);
+ if (status != 0)
+ {
+ goto err;
+ }
+
+ }
}
return;
- err:
- throw_signal_soft (SIGHUP, "Preresolving failed");
+err:
+ throw_signal_soft(SIGHUP, "Preresolving failed");
}
/*
@@ -280,185 +315,220 @@ do_preresolve (struct context *c)
* If resolve error, try again for resolve_retry_seconds seconds.
*/
int
-openvpn_getaddrinfo (unsigned int flags,
- const char *hostname,
- const char *servname,
- int resolve_retry_seconds,
- volatile int *signal_received,
- int ai_family,
- struct addrinfo **res)
+openvpn_getaddrinfo(unsigned int flags,
+ const char *hostname,
+ const char *servname,
+ int resolve_retry_seconds,
+ volatile int *signal_received,
+ int ai_family,
+ struct addrinfo **res)
{
- struct addrinfo hints;
- int status;
- int sigrec = 0;
- int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS;
- struct gc_arena gc = gc_new ();
- const char *print_hostname;
- const char *print_servname;
+ struct addrinfo hints;
+ int status;
+ 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);
+ ASSERT(res);
- ASSERT (hostname || servname);
- ASSERT (!(flags & GETADDR_HOST_ORDER));
+ ASSERT(hostname || servname);
+ ASSERT(!(flags & GETADDR_HOST_ORDER));
- if (hostname && (flags & GETADDR_RANDOMIZE))
- hostname = hostname_randomize(hostname, &gc);
+ if (hostname && (flags & GETADDR_RANDOMIZE))
+ {
+ hostname = hostname_randomize(hostname, &gc);
+ }
- if(hostname)
- print_hostname = hostname;
- else
- print_hostname = "undefined";
+ if (hostname)
+ {
+ print_hostname = hostname;
+ }
+ else
+ {
+ print_hostname = "undefined";
+ }
- if(servname)
- print_servname = servname;
- else
- print_servname = "";
+ if (servname)
+ {
+ print_servname = servname;
+ }
+ else
+ {
+ print_servname = "";
+ }
- if (flags & GETADDR_MSG_VIRT_OUT)
- msglevel |= M_MSG_VIRT_OUT;
+ if (flags & GETADDR_MSG_VIRT_OUT)
+ {
+ msglevel |= M_MSG_VIRT_OUT;
+ }
- if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL))
- && !signal_received)
- signal_received = &sigrec;
+ if ((flags & (GETADDR_FATAL_ON_SIGNAL|GETADDR_WARN_ON_SIGNAL))
+ && !signal_received)
+ {
+ signal_received = &sigrec;
+ }
- /* try numeric ipv6 addr first */
- CLEAR(hints);
- hints.ai_family = ai_family;
- hints.ai_flags = AI_NUMERICHOST;
+ /* try numeric ipv6 addr first */
+ CLEAR(hints);
+ hints.ai_family = ai_family;
+ hints.ai_flags = AI_NUMERICHOST;
- if(flags & GETADDR_PASSIVE)
- hints.ai_flags |= AI_PASSIVE;
+ if (flags & GETADDR_PASSIVE)
+ {
+ hints.ai_flags |= AI_PASSIVE;
+ }
- if(flags & GETADDR_DATAGRAM)
- hints.ai_socktype = SOCK_DGRAM;
- else
- hints.ai_socktype = SOCK_STREAM;
+ if (flags & GETADDR_DATAGRAM)
+ {
+ hints.ai_socktype = SOCK_DGRAM;
+ }
+ else
+ {
+ hints.ai_socktype = SOCK_STREAM;
+ }
- status = getaddrinfo(hostname, servname, &hints, res);
+ status = getaddrinfo(hostname, servname, &hints, res);
- if (status != 0) /* parse as numeric address failed? */
+ if (status != 0) /* parse as numeric address failed? */
{
- const int fail_wait_interval = 5; /* seconds */
- /* 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;
+ const int fail_wait_interval = 5; /* seconds */
+ /* 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 (%s)";
- if ((flags & GETADDR_MENTION_RESOLVE_RETRY)
- && !resolve_retry_seconds)
- fmt = "RESOLVE: Cannot resolve host address: %s:%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)";
+ if ((flags & GETADDR_MENTION_RESOLVE_RETRY)
+ && !resolve_retry_seconds)
+ {
+ 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)
+ if (!(flags & GETADDR_RESOLVE) || status == EAI_FAIL)
{
- msg (msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)",
- print_hostname,print_servname, gai_strerror(status));
- goto done;
+ msg(msglevel, "RESOLVE: Cannot parse IP address: %s:%s (%s)",
+ print_hostname,print_servname, gai_strerror(status));
+ goto done;
}
#ifdef ENABLE_MANAGEMENT
- if (flags & GETADDR_UPDATE_MANAGEMENT_STATE)
+ if (flags & GETADDR_UPDATE_MANAGEMENT_STATE)
{
- if (management)
- management_set_state (management,
- OPENVPN_STATE_RESOLVE,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
+ if (management)
+ {
+ management_set_state(management,
+ OPENVPN_STATE_RESOLVE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
}
#endif
- /*
- * Resolve hostname
- */
- while (true)
+ /*
+ * Resolve hostname
+ */
+ while (true)
{
#ifndef _WIN32
- res_init ();
+ res_init();
#endif
- /* try hostname lookup */
- 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, servname, &hints, res);
+ /* try hostname lookup */
+ 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, servname, &hints, res);
- if (signal_received)
+ if (signal_received)
{
- get_signal (signal_received);
- if (*signal_received) /* were we interrupted by a signal? */
+ get_signal(signal_received);
+ if (*signal_received) /* were we interrupted by a signal? */
{
- if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */
+ if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */
{
- msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt");
- *signal_received = 0;
+ msg(level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt");
+ *signal_received = 0;
}
- else
+ else
{
- /* turn success into failure (interrupted syscall) */
- if (0 == status) {
- ASSERT(res);
- freeaddrinfo(*res);
- *res = NULL;
- status = EAI_AGAIN; /* = temporary failure */
- errno = EINTR;
- }
- goto done;
+ /* turn success into failure (interrupted syscall) */
+ if (0 == status)
+ {
+ ASSERT(res);
+ freeaddrinfo(*res);
+ *res = NULL;
+ status = EAI_AGAIN; /* = temporary failure */
+ errno = EINTR;
+ }
+ goto done;
}
}
}
- /* success? */
- if (0 == status)
- break;
+ /* success? */
+ if (0 == status)
+ {
+ break;
+ }
- /* resolve lookup failed, should we
- continue or fail? */
- level = msglevel;
- if (resolve_retries > 0)
- level = D_RESOLVE_ERRORS;
+ /* resolve lookup failed, should we
+ * continue or fail? */
+ level = msglevel;
+ if (resolve_retries > 0)
+ {
+ level = D_RESOLVE_ERRORS;
+ }
- msg (level,
- fmt,
- print_hostname,
- print_servname,
- gai_strerror(status));
+ msg(level,
+ fmt,
+ print_hostname,
+ print_servname,
+ gai_strerror(status));
- if (--resolve_retries <= 0)
- goto done;
+ if (--resolve_retries <= 0)
+ {
+ goto done;
+ }
- openvpn_sleep (fail_wait_interval);
+ openvpn_sleep(fail_wait_interval);
}
- ASSERT(res);
+ ASSERT(res);
- /* hostname resolve succeeded */
+ /* hostname resolve succeeded */
- /*
- * Do not choose an IP Addresse by random or change the order *
- * of IP addresses, doing so will break RFC 3484 address selection *
- */
+ /*
+ * Do not choose an IP Addresse by random or change the order *
+ * of IP addresses, doing so will break RFC 3484 address selection *
+ */
}
- else
+ else
{
- /* IP address parse succeeded */
+ /* IP address parse succeeded */
}
- done:
- if (signal_received && *signal_received)
+done:
+ if (signal_received && *signal_received)
{
- int level = 0;
- if (flags & GETADDR_FATAL_ON_SIGNAL)
- level = M_FATAL;
- else if (flags & GETADDR_WARN_ON_SIGNAL)
- level = M_WARN;
- msg (level, "RESOLVE: signal received during DNS resolution attempt");
+ int level = 0;
+ if (flags & GETADDR_FATAL_ON_SIGNAL)
+ {
+ level = M_FATAL;
+ }
+ else if (flags & GETADDR_WARN_ON_SIGNAL)
+ {
+ level = M_WARN;
+ }
+ msg(level, "RESOLVE: signal received during DNS resolution attempt");
}
- gc_free (&gc);
- return status;
+ gc_free(&gc);
+ return status;
}
/*
@@ -466,220 +536,260 @@ openvpn_getaddrinfo (unsigned int flags,
* isn't very good about error checking.
*/
int
-openvpn_inet_aton (const char *dotted_quad, struct in_addr *addr)
+openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr)
{
- unsigned int a, b, c, d;
+ unsigned int a, b, c, d;
- CLEAR (*addr);
- if (sscanf (dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) == 4)
+ CLEAR(*addr);
+ if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) == 4)
+ {
+ if (a < 256 && b < 256 && c < 256 && d < 256)
+ {
+ addr->s_addr = htonl(a<<24 | b<<16 | c<<8 | d);
+ return OIA_IP; /* good dotted quad */
+ }
+ }
+ if (string_class(dotted_quad, CC_DIGIT|CC_DOT, 0))
+ {
+ return OIA_ERROR; /* probably a badly formatted dotted quad */
+ }
+ else
{
- if (a < 256 && b < 256 && c < 256 && d < 256)
- {
- addr->s_addr = htonl (a<<24 | b<<16 | c<<8 | d);
- return OIA_IP; /* good dotted quad */
- }
+ return OIA_HOSTNAME; /* probably a hostname */
}
- if (string_class (dotted_quad, CC_DIGIT|CC_DOT, 0))
- return OIA_ERROR; /* probably a badly formatted dotted quad */
- else
- return OIA_HOSTNAME; /* probably a hostname */
}
bool
-ip_addr_dotted_quad_safe (const char *dotted_quad)
+ip_addr_dotted_quad_safe(const char *dotted_quad)
{
- /* verify non-NULL */
- if (!dotted_quad)
- return false;
+ /* verify non-NULL */
+ if (!dotted_quad)
+ {
+ return false;
+ }
- /* verify length is within limits */
- if (strlen (dotted_quad) > 15)
- return false;
+ /* verify length is within limits */
+ if (strlen(dotted_quad) > 15)
+ {
+ return false;
+ }
+
+ /* verify that all chars are either numeric or '.' and that no numeric
+ * substring is greater than 3 chars */
+ {
+ int nnum = 0;
+ const char *p = dotted_quad;
+ int c;
+
+ while ((c = *p++))
+ {
+ if (c >= '0' && c <= '9')
+ {
+ ++nnum;
+ if (nnum > 3)
+ {
+ return false;
+ }
+ }
+ else if (c == '.')
+ {
+ nnum = 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
- /* verify that all chars are either numeric or '.' and that no numeric
- substring is greater than 3 chars */
- {
- int nnum = 0;
- const char *p = dotted_quad;
- int c;
-
- while ((c = *p++))
- {
- if (c >= '0' && c <= '9')
- {
- ++nnum;
- if (nnum > 3)
- return false;
- }
- else if (c == '.')
- {
- nnum = 0;
- }
- else
- return false;
- }
- }
-
- /* verify that string will convert to IP address */
- {
- struct in_addr a;
- return openvpn_inet_aton (dotted_quad, &a) == OIA_IP;
- }
+ /* verify that string will convert to IP address */
+ {
+ struct in_addr a;
+ return openvpn_inet_aton(dotted_quad, &a) == OIA_IP;
+ }
}
bool
-ipv6_addr_safe (const char *ipv6_text_addr)
+ipv6_addr_safe(const char *ipv6_text_addr)
{
- /* verify non-NULL */
- if (!ipv6_text_addr)
- return false;
+ /* verify non-NULL */
+ if (!ipv6_text_addr)
+ {
+ return false;
+ }
- /* verify length is within limits */
- if (strlen (ipv6_text_addr) > INET6_ADDRSTRLEN )
- return false;
+ /* verify length is within limits */
+ if (strlen(ipv6_text_addr) > INET6_ADDRSTRLEN)
+ {
+ return false;
+ }
- /* verify that string will convert to IPv6 address */
- {
- struct in6_addr a6;
- return inet_pton( AF_INET6, ipv6_text_addr, &a6 ) == 1;
- }
+ /* verify that string will convert to IPv6 address */
+ {
+ struct in6_addr a6;
+ return inet_pton( AF_INET6, ipv6_text_addr, &a6 ) == 1;
+ }
}
static bool
-dns_addr_safe (const char *addr)
+dns_addr_safe(const char *addr)
{
- if (addr)
+ if (addr)
{
- const size_t len = strlen (addr);
- return len > 0 && len <= 255 && string_class (addr, CC_ALNUM|CC_DASH|CC_DOT, 0);
+ const size_t len = strlen(addr);
+ return len > 0 && len <= 255 && string_class(addr, CC_ALNUM|CC_DASH|CC_DOT, 0);
+ }
+ else
+ {
+ return false;
}
- else
- return false;
}
bool
-ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn)
+ip_or_dns_addr_safe(const char *addr, const bool allow_fqdn)
{
- if (ip_addr_dotted_quad_safe (addr))
- return true;
- else if (allow_fqdn)
- return dns_addr_safe (addr);
- else
- return false;
+ if (ip_addr_dotted_quad_safe(addr))
+ {
+ return true;
+ }
+ else if (allow_fqdn)
+ {
+ return dns_addr_safe(addr);
+ }
+ else
+ {
+ return false;
+ }
}
bool
-mac_addr_safe (const char *mac_addr)
+mac_addr_safe(const char *mac_addr)
{
- /* verify non-NULL */
- if (!mac_addr)
- return false;
+ /* verify non-NULL */
+ if (!mac_addr)
+ {
+ return false;
+ }
- /* verify length is within limits */
- if (strlen (mac_addr) > 17)
- return false;
+ /* verify length is within limits */
+ if (strlen(mac_addr) > 17)
+ {
+ return false;
+ }
+
+ /* verify that all chars are either alphanumeric or ':' and that no
+ * alphanumeric substring is greater than 2 chars */
+ {
+ int nnum = 0;
+ const char *p = mac_addr;
+ int c;
+
+ while ((c = *p++))
+ {
+ if ( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
+ {
+ ++nnum;
+ if (nnum > 2)
+ {
+ return false;
+ }
+ }
+ else if (c == ':')
+ {
+ nnum = 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
- /* verify that all chars are either alphanumeric or ':' and that no
- alphanumeric substring is greater than 2 chars */
- {
- int nnum = 0;
- const char *p = mac_addr;
- int c;
-
- while ((c = *p++))
- {
- if ( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') )
- {
- ++nnum;
- if (nnum > 2)
- return false;
- }
- else if (c == ':')
- {
- nnum = 0;
- }
- else
- return false;
- }
- }
-
- /* error-checking is left to script invoked in lladdr.c */
- return true;
+ /* error-checking is left to script invoked in lladdr.c */
+ return true;
}
static int
-socket_get_sndbuf (int sd)
+socket_get_sndbuf(int sd)
{
#if defined(HAVE_GETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_SNDBUF)
- int val;
- socklen_t len;
+ int val;
+ socklen_t len;
- len = sizeof (val);
- if (getsockopt (sd, SOL_SOCKET, SO_SNDBUF, (void *) &val, &len) == 0
- && len == sizeof (val))
- return val;
+ len = sizeof(val);
+ if (getsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *) &val, &len) == 0
+ && len == sizeof(val))
+ {
+ return val;
+ }
#endif
- return 0;
+ return 0;
}
static void
-socket_set_sndbuf (int sd, int size)
+socket_set_sndbuf(int sd, int size)
{
#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_SNDBUF)
- if (setsockopt (sd, SOL_SOCKET, SO_SNDBUF, (void *) &size, sizeof (size)) != 0)
+ if (setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (void *) &size, sizeof(size)) != 0)
{
- msg (M_WARN, "NOTE: setsockopt SO_SNDBUF=%d failed", size);
+ msg(M_WARN, "NOTE: setsockopt SO_SNDBUF=%d failed", size);
}
#endif
}
static int
-socket_get_rcvbuf (int sd)
+socket_get_rcvbuf(int sd)
{
#if defined(HAVE_GETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_RCVBUF)
- int val;
- socklen_t len;
+ int val;
+ socklen_t len;
- len = sizeof (val);
- if (getsockopt (sd, SOL_SOCKET, SO_RCVBUF, (void *) &val, &len) == 0
- && len == sizeof (val))
- return val;
+ len = sizeof(val);
+ if (getsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *) &val, &len) == 0
+ && len == sizeof(val))
+ {
+ return val;
+ }
#endif
- return 0;
+ return 0;
}
static bool
-socket_set_rcvbuf (int sd, int size)
+socket_set_rcvbuf(int sd, int size)
{
#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_RCVBUF)
- if (setsockopt (sd, SOL_SOCKET, SO_RCVBUF, (void *) &size, sizeof (size)) != 0)
+ if (setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (void *) &size, sizeof(size)) != 0)
{
- msg (M_WARN, "NOTE: setsockopt SO_RCVBUF=%d failed", size);
- return false;
+ msg(M_WARN, "NOTE: setsockopt SO_RCVBUF=%d failed", size);
+ return false;
}
- return true;
+ return true;
#endif
}
static void
-socket_set_buffers (int fd, const struct socket_buffer_size *sbs)
+socket_set_buffers(int fd, const struct socket_buffer_size *sbs)
{
- if (sbs)
+ if (sbs)
{
- const int sndbuf_old = socket_get_sndbuf (fd);
- const int rcvbuf_old = socket_get_rcvbuf (fd);
+ const int sndbuf_old = socket_get_sndbuf(fd);
+ const int rcvbuf_old = socket_get_rcvbuf(fd);
- if (sbs->sndbuf)
- socket_set_sndbuf (fd, sbs->sndbuf);
+ if (sbs->sndbuf)
+ {
+ socket_set_sndbuf(fd, sbs->sndbuf);
+ }
+
+ if (sbs->rcvbuf)
+ {
+ socket_set_rcvbuf(fd, sbs->rcvbuf);
+ }
- if (sbs->rcvbuf)
- socket_set_rcvbuf (fd, sbs->rcvbuf);
-
- msg (D_OSBUF, "Socket Buffers: R=[%d->%d] S=[%d->%d]",
- rcvbuf_old,
- socket_get_rcvbuf (fd),
- sndbuf_old,
- socket_get_sndbuf (fd));
+ msg(D_OSBUF, "Socket Buffers: R=[%d->%d] S=[%d->%d]",
+ rcvbuf_old,
+ socket_get_rcvbuf(fd),
+ sndbuf_old,
+ socket_get_sndbuf(fd));
}
}
@@ -688,60 +798,70 @@ socket_set_buffers (int fd, const struct socket_buffer_size *sbs)
*/
static bool
-socket_set_tcp_nodelay (int sd, int state)
+socket_set_tcp_nodelay(int sd, int state)
{
#if defined(_WIN32) || (defined(HAVE_SETSOCKOPT) && defined(IPPROTO_TCP) && defined(TCP_NODELAY))
- if (setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (void *) &state, sizeof (state)) != 0)
+ if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (void *) &state, sizeof(state)) != 0)
{
- msg (M_WARN, "NOTE: setsockopt TCP_NODELAY=%d failed", state);
- return false;
+ msg(M_WARN, "NOTE: setsockopt TCP_NODELAY=%d failed", state);
+ return false;
}
- else
+ else
{
- dmsg (D_OSBUF, "Socket flags: TCP_NODELAY=%d succeeded", state);
- return true;
+ dmsg(D_OSBUF, "Socket flags: TCP_NODELAY=%d succeeded", state);
+ return true;
}
-#else
- msg (M_WARN, "NOTE: setsockopt TCP_NODELAY=%d failed (No kernel support)", state);
- return false;
+#else /* if defined(_WIN32) || (defined(HAVE_SETSOCKOPT) && defined(IPPROTO_TCP) && defined(TCP_NODELAY)) */
+ msg(M_WARN, "NOTE: setsockopt TCP_NODELAY=%d failed (No kernel support)", state);
+ return false;
#endif
}
static inline void
-socket_set_mark (int sd, int mark)
+socket_set_mark(int sd, int mark)
{
#if defined(TARGET_LINUX) && HAVE_DECL_SO_MARK
- if (mark && setsockopt (sd, SOL_SOCKET, SO_MARK, (void *) &mark, sizeof (mark)) != 0)
- msg (M_WARN, "NOTE: setsockopt SO_MARK=%d failed", mark);
+ if (mark && setsockopt(sd, SOL_SOCKET, SO_MARK, (void *) &mark, sizeof(mark)) != 0)
+ {
+ msg(M_WARN, "NOTE: setsockopt SO_MARK=%d failed", mark);
+ }
#endif
}
static bool
-socket_set_flags (int sd, unsigned int sockflags)
+socket_set_flags(int sd, unsigned int sockflags)
{
- if (sockflags & SF_TCP_NODELAY)
- return socket_set_tcp_nodelay (sd, 1);
- else
- return true;
+ if (sockflags & SF_TCP_NODELAY)
+ {
+ return socket_set_tcp_nodelay(sd, 1);
+ }
+ else
+ {
+ return true;
+ }
}
bool
-link_socket_update_flags (struct link_socket *ls, unsigned int sockflags)
+link_socket_update_flags(struct link_socket *ls, unsigned int sockflags)
{
- if (ls && socket_defined (ls->sd))
- return socket_set_flags (ls->sd, ls->sockflags = sockflags);
- else
- return false;
+ if (ls && socket_defined(ls->sd))
+ {
+ return socket_set_flags(ls->sd, ls->sockflags = sockflags);
+ }
+ else
+ {
+ return false;
+ }
}
void
-link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
+link_socket_update_buffer_sizes(struct link_socket *ls, int rcvbuf, int sndbuf)
{
- if (ls && socket_defined (ls->sd))
+ if (ls && socket_defined(ls->sd))
{
- ls->socket_buffer_sizes.sndbuf = sndbuf;
- ls->socket_buffer_sizes.rcvbuf = rcvbuf;
- socket_set_buffers (ls->sd, &ls->socket_buffer_sizes);
+ ls->socket_buffer_sizes.sndbuf = sndbuf;
+ ls->socket_buffer_sizes.rcvbuf = rcvbuf;
+ socket_set_buffers(ls->sd, &ls->socket_buffer_sizes);
}
}
@@ -751,140 +871,166 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
*/
socket_descriptor_t
-create_socket_tcp (struct addrinfo* addrinfo)
+create_socket_tcp(struct addrinfo *addrinfo)
{
- socket_descriptor_t sd;
+ socket_descriptor_t sd;
- ASSERT (addrinfo);
- ASSERT (addrinfo->ai_socktype == SOCK_STREAM);
+ ASSERT(addrinfo);
+ ASSERT(addrinfo->ai_socktype == SOCK_STREAM);
- if ((sd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0)
- msg (M_ERR, "Cannot create TCP socket");
+ if ((sd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0)
+ {
+ msg(M_ERR, "Cannot create TCP socket");
+ }
#ifndef _WIN32 /* using SO_REUSEADDR on Windows will cause bind to succeed on port conflicts! */
- /* set SO_REUSEADDR on socket */
- {
- int on = 1;
- if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR,
- (void *) &on, sizeof (on)) < 0)
- msg (M_ERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP socket");
- }
+ /* set SO_REUSEADDR on socket */
+ {
+ int on = 1;
+ if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR,
+ (void *) &on, sizeof(on)) < 0)
+ {
+ msg(M_ERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP socket");
+ }
+ }
#endif
- return sd;
+ /* set socket file descriptor to not pass across execs, so that
+ * scripts don't have access to it */
+ set_cloexec(sd);
+
+ return sd;
}
static socket_descriptor_t
-create_socket_udp (struct addrinfo* addrinfo, const unsigned int flags)
+create_socket_udp(struct addrinfo *addrinfo, const unsigned int flags)
{
- socket_descriptor_t sd;
+ socket_descriptor_t sd;
- ASSERT (addrinfo);
- ASSERT (addrinfo->ai_socktype == SOCK_DGRAM);
+ ASSERT(addrinfo);
+ ASSERT(addrinfo->ai_socktype == SOCK_DGRAM);
- if ((sd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0)
- msg (M_ERR, "UDP: Cannot create UDP/UDP6 socket");
+ if ((sd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0)
+ {
+ msg(M_ERR, "UDP: Cannot create UDP/UDP6 socket");
+ }
#if ENABLE_IP_PKTINFO
- else if (flags & SF_USE_IP_PKTINFO)
+ else if (flags & SF_USE_IP_PKTINFO)
{
- int pad = 1;
- if(addrinfo->ai_family == AF_INET)
+ int pad = 1;
+ if (addrinfo->ai_family == AF_INET)
{
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
- 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");
-#else
+ if (setsockopt(sd, IPPROTO_IP, IP_RECVDSTADDR,
+ (void *)&pad, sizeof(pad)) < 0)
+ {
+ msg(M_ERR, "UDP: failed setsockopt for IP_RECVDSTADDR");
+ }
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
}
- else if (addrinfo->ai_family == AF_INET6 )
+ else if (addrinfo->ai_family == 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;
+#endif /* if ENABLE_IP_PKTINFO */
+
+ /* set socket file descriptor to not pass across execs, so that
+ * scripts don't have access to it */
+ set_cloexec(sd);
+
+ return sd;
}
-static void bind_local (struct link_socket *sock, const sa_family_t ai_family)
+static void
+bind_local(struct link_socket *sock, const sa_family_t ai_family)
{
/* bind to local address/port */
if (sock->bind_local)
- {
+ {
if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
- socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
- ai_family, "SOCKS", false);
+ {
+ socket_bind(sock->ctrl_sd, sock->info.lsa->bind_local,
+ ai_family, "SOCKS", false);
+ }
else
- socket_bind (sock->sd, sock->info.lsa->bind_local,
- ai_family,
- "TCP/UDP", sock->info.bind_ipv6_only);
- }
+ {
+ socket_bind(sock->sd, sock->info.lsa->bind_local,
+ ai_family,
+ "TCP/UDP", sock->info.bind_ipv6_only);
+ }
+ }
}
static void
-create_socket (struct link_socket* sock, struct addrinfo* addr)
+create_socket(struct link_socket *sock, struct addrinfo *addr)
{
- if (addr->ai_protocol == IPPROTO_UDP || addr->ai_socktype == SOCK_DGRAM)
+ if (addr->ai_protocol == IPPROTO_UDP || addr->ai_socktype == SOCK_DGRAM)
{
- sock->sd = create_socket_udp (addr, sock->sockflags);
- sock->sockflags |= SF_GETADDRINFO_DGRAM;
+ sock->sd = create_socket_udp(addr, sock->sockflags);
+ sock->sockflags |= SF_GETADDRINFO_DGRAM;
- /* Assume that control socket and data socket to the socks proxy
- * are using the same IP family */
- if (sock->socks_proxy)
- {
- /* Construct a temporary addrinfo to create the socket,
- * currently resolve two remote addresses is not supported,
- * TODO: Rewrite the whole resolve_remote */
- struct addrinfo addrinfo_tmp = *addr;
- addrinfo_tmp.ai_socktype = SOCK_STREAM;
- addrinfo_tmp.ai_protocol = IPPROTO_TCP;
- sock->ctrl_sd = create_socket_tcp (&addrinfo_tmp);
- }
+ /* Assume that control socket and data socket to the socks proxy
+ * are using the same IP family */
+ if (sock->socks_proxy)
+ {
+ /* Construct a temporary addrinfo to create the socket,
+ * currently resolve two remote addresses is not supported,
+ * TODO: Rewrite the whole resolve_remote */
+ struct addrinfo addrinfo_tmp = *addr;
+ addrinfo_tmp.ai_socktype = SOCK_STREAM;
+ addrinfo_tmp.ai_protocol = IPPROTO_TCP;
+ sock->ctrl_sd = create_socket_tcp(&addrinfo_tmp);
+ }
}
- else if (addr->ai_protocol == IPPROTO_TCP || addr->ai_socktype == SOCK_STREAM)
+ else if (addr->ai_protocol == IPPROTO_TCP || addr->ai_socktype == SOCK_STREAM)
{
- sock->sd = create_socket_tcp (addr);
+ sock->sd = create_socket_tcp(addr);
}
- else
+ else
{
- ASSERT (0);
+ ASSERT(0);
}
/* set socket buffers based on --sndbuf and --rcvbuf options */
- socket_set_buffers (sock->sd, &sock->socket_buffer_sizes);
+ socket_set_buffers(sock->sd, &sock->socket_buffer_sizes);
/* set socket to --mark packets with given value */
- socket_set_mark (sock->sd, sock->mark);
+ socket_set_mark(sock->sd, sock->mark);
- bind_local (sock, addr->ai_family);
+ bind_local(sock, addr->ai_family);
}
#ifdef TARGET_ANDROID
-static void protect_fd_nonlocal (int fd, const struct sockaddr* addr)
+static void
+protect_fd_nonlocal(int fd, const struct sockaddr *addr)
{
- /* pass socket FD to management interface to pass on to VPNService API
- * as "protected socket" (exempt from being routed into tunnel)
- */
- if (addr_local (addr)) {
- msg(D_SOCKET_DEBUG, "Address is local, not protecting socket fd %d", fd);
- return;
- }
+ /* pass socket FD to management interface to pass on to VPNService API
+ * as "protected socket" (exempt from being routed into tunnel)
+ */
+ if (addr_local(addr))
+ {
+ msg(D_SOCKET_DEBUG, "Address is local, not protecting socket fd %d", fd);
+ return;
+ }
- msg(D_SOCKET_DEBUG, "Protecting socket fd %d", fd);
- management->connection.fdtosend = fd;
- management_android_control (management, "PROTECTFD", __func__);
+ msg(D_SOCKET_DEBUG, "Protecting socket fd %d", fd);
+ management->connection.fdtosend = fd;
+ management_android_control(management, "PROTECTFD", __func__);
}
#endif
@@ -892,434 +1038,488 @@ static void protect_fd_nonlocal (int fd, const struct sockaddr* addr)
* Functions used for establishing a TCP stream connection.
*/
static void
-socket_do_listen (socket_descriptor_t sd,
- const struct addrinfo *local,
- bool do_listen,
- bool do_set_nonblock)
-{
- struct gc_arena gc = gc_new ();
- if (do_listen)
- {
- ASSERT(local);
- msg (M_INFO, "Listening for incoming TCP connection on %s",
- print_sockaddr (local->ai_addr, &gc));
- if (listen (sd, 1))
- msg (M_ERR, "TCP: listen() failed");
+socket_do_listen(socket_descriptor_t sd,
+ const struct addrinfo *local,
+ bool do_listen,
+ bool do_set_nonblock)
+{
+ struct gc_arena gc = gc_new();
+ if (do_listen)
+ {
+ ASSERT(local);
+ msg(M_INFO, "Listening for incoming TCP connection on %s",
+ print_sockaddr(local->ai_addr, &gc));
+ if (listen(sd, 1))
+ {
+ msg(M_ERR, "TCP: listen() failed");
+ }
}
- /* set socket to non-blocking mode */
- if (do_set_nonblock)
- set_nonblock (sd);
+ /* set socket to non-blocking mode */
+ if (do_set_nonblock)
+ {
+ set_nonblock(sd);
+ }
- gc_free (&gc);
+ gc_free(&gc);
}
socket_descriptor_t
-socket_do_accept (socket_descriptor_t sd,
- struct link_socket_actual *act,
- const bool nowait)
+socket_do_accept(socket_descriptor_t sd,
+ struct link_socket_actual *act,
+ const bool nowait)
{
- /* af_addr_size WILL return 0 in this case if AFs other than AF_INET
- * are compiled because act is empty here.
- * could use getsockname() to support later remote_len check
- */
- socklen_t remote_len_af = af_addr_size(act->dest.addr.sa.sa_family);
- socklen_t remote_len = sizeof(act->dest.addr);
- socket_descriptor_t new_sd = SOCKET_UNDEFINED;
+ /* af_addr_size WILL return 0 in this case if AFs other than AF_INET
+ * are compiled because act is empty here.
+ * could use getsockname() to support later remote_len check
+ */
+ socklen_t remote_len_af = af_addr_size(act->dest.addr.sa.sa_family);
+ socklen_t remote_len = sizeof(act->dest.addr);
+ socket_descriptor_t new_sd = SOCKET_UNDEFINED;
- CLEAR (*act);
+ CLEAR(*act);
#ifdef HAVE_GETPEERNAME
- if (nowait)
+ if (nowait)
{
- new_sd = getpeername (sd, &act->dest.addr.sa, &remote_len);
+ new_sd = getpeername(sd, &act->dest.addr.sa, &remote_len);
- if (!socket_defined (new_sd))
- msg (D_LINK_ERRORS | M_ERRNO, "TCP: getpeername() failed");
- else
- new_sd = sd;
+ if (!socket_defined(new_sd))
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "TCP: getpeername() failed");
+ }
+ else
+ {
+ new_sd = sd;
+ }
+ }
+#else /* ifdef HAVE_GETPEERNAME */
+ if (nowait)
+ {
+ msg(M_WARN, "TCP: this OS does not provide the getpeername() function");
}
-#else
- if (nowait)
- msg (M_WARN, "TCP: this OS does not provide the getpeername() function");
#endif
- else
+ else
{
- new_sd = accept (sd, &act->dest.addr.sa, &remote_len);
+ new_sd = accept(sd, &act->dest.addr.sa, &remote_len);
}
#if 0 /* For debugging only, test the effect of accept() failures */
- {
- static int foo = 0;
- ++foo;
- if (foo & 1)
- new_sd = -1;
- }
+ {
+ static int foo = 0;
+ ++foo;
+ if (foo & 1)
+ {
+ new_sd = -1;
+ }
+ }
#endif
- if (!socket_defined (new_sd))
+ if (!socket_defined(new_sd))
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "TCP: accept(%d) failed", sd);
+ }
+ /* only valid if we have remote_len_af!=0 */
+ else if (remote_len_af && remote_len != remote_len_af)
{
- msg (D_LINK_ERRORS | M_ERRNO, "TCP: accept(%d) failed", sd);
+ msg(D_LINK_ERRORS, "TCP: Received strange incoming connection with unknown address length=%d", remote_len);
+ openvpn_close_socket(new_sd);
+ new_sd = SOCKET_UNDEFINED;
}
- /* only valid if we have remote_len_af!=0 */
- else if (remote_len_af && remote_len != remote_len_af)
+ else
{
- msg (D_LINK_ERRORS, "TCP: Received strange incoming connection with unknown address length=%d", remote_len);
- openvpn_close_socket (new_sd);
- new_sd = SOCKET_UNDEFINED;
+ /* set socket file descriptor to not pass across execs, so that
+ * scripts don't have access to it */
+ set_cloexec(sd);
}
- return new_sd;
+ return new_sd;
}
static void
-tcp_connection_established (const struct link_socket_actual *act)
+tcp_connection_established(const struct link_socket_actual *act)
{
- struct gc_arena gc = gc_new ();
- msg (M_INFO, "TCP connection established with %s",
- print_link_socket_actual (act, &gc));
- gc_free (&gc);
+ struct gc_arena gc = gc_new();
+ msg(M_INFO, "TCP connection established with %s",
+ print_link_socket_actual(act, &gc));
+ gc_free(&gc);
}
static int
-socket_listen_accept (socket_descriptor_t sd,
- struct link_socket_actual *act,
- const char *remote_dynamic,
- const struct addrinfo *local,
- bool do_listen,
- bool nowait,
- volatile int *signal_received)
-{
- struct gc_arena gc = gc_new ();
- /* struct openvpn_sockaddr *remote = &act->dest; */
- struct openvpn_sockaddr remote_verify = act->dest;
- int new_sd = SOCKET_UNDEFINED;
-
- CLEAR (*act);
- socket_do_listen (sd, local, do_listen, true);
-
- while (true)
- {
- int status;
- fd_set reads;
- struct timeval tv;
-
- FD_ZERO (&reads);
- openvpn_fd_set (sd, &reads);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- status = select (sd + 1, &reads, NULL, NULL, &tv);
-
- get_signal (signal_received);
- if (*signal_received)
- {
- gc_free (&gc);
- return sd;
- }
-
- if (status < 0)
- msg (D_LINK_ERRORS | M_ERRNO, "TCP: select() failed");
-
- if (status <= 0)
- {
- openvpn_sleep (1);
- continue;
- }
-
- new_sd = socket_do_accept (sd, act, nowait);
-
- if (socket_defined (new_sd))
- {
- struct addrinfo* ai = NULL;
- if(remote_dynamic)
- openvpn_getaddrinfo(0, remote_dynamic, NULL, 1, NULL,
+socket_listen_accept(socket_descriptor_t sd,
+ struct link_socket_actual *act,
+ const char *remote_dynamic,
+ const struct addrinfo *local,
+ bool do_listen,
+ bool nowait,
+ volatile int *signal_received)
+{
+ struct gc_arena gc = gc_new();
+ /* struct openvpn_sockaddr *remote = &act->dest; */
+ struct openvpn_sockaddr remote_verify = act->dest;
+ int new_sd = SOCKET_UNDEFINED;
+
+ CLEAR(*act);
+ socket_do_listen(sd, local, do_listen, true);
+
+ while (true)
+ {
+ int status;
+ fd_set reads;
+ struct timeval tv;
+
+ FD_ZERO(&reads);
+ openvpn_fd_set(sd, &reads);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ status = select(sd + 1, &reads, NULL, NULL, &tv);
+
+ get_signal(signal_received);
+ if (*signal_received)
+ {
+ gc_free(&gc);
+ return sd;
+ }
+
+ if (status < 0)
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "TCP: select() failed");
+ }
+
+ if (status <= 0)
+ {
+ openvpn_sleep(1);
+ continue;
+ }
+
+ new_sd = socket_do_accept(sd, act, nowait);
+
+ if (socket_defined(new_sd))
+ {
+ struct addrinfo *ai = NULL;
+ 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))
+ 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);
+ 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
+ else
{
- if(ai)
- freeaddrinfo(ai);
- break;
+ if (ai)
+ {
+ freeaddrinfo(ai);
+ }
+ break;
}
- }
- openvpn_sleep (1);
+ }
+ openvpn_sleep(1);
}
- if (!nowait && openvpn_close_socket (sd))
- msg (M_ERR, "TCP: close socket failed (sd)");
+ if (!nowait && openvpn_close_socket(sd))
+ {
+ msg(M_ERR, "TCP: close socket failed (sd)");
+ }
- tcp_connection_established (act);
+ tcp_connection_established(act);
- gc_free (&gc);
- return new_sd;
+ gc_free(&gc);
+ return new_sd;
}
/* older mingw versions and WinXP do not have this define,
* but Vista and up support the functionality - just define it here
*/
#ifdef _WIN32
-# ifndef IPV6_V6ONLY
-# define IPV6_V6ONLY 27
-# endif
+#ifndef IPV6_V6ONLY
+#define IPV6_V6ONLY 27
+#endif
#endif
void
-socket_bind (socket_descriptor_t sd,
- struct addrinfo *local,
- int ai_family,
- const char *prefix,
- bool ipv6only)
+socket_bind(socket_descriptor_t sd,
+ struct addrinfo *local,
+ int ai_family,
+ const char *prefix,
+ bool ipv6only)
{
- struct gc_arena gc = gc_new ();
+ struct gc_arena gc = gc_new();
- /* 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?
- */
+ /* 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?
+ */
- struct addrinfo* cur;
+ struct addrinfo *cur;
- ASSERT(local);
+ ASSERT(local);
- /* find the first addrinfo with correct ai_family */
- for (cur = local; cur; cur=cur->ai_next)
+ /* 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->ai_family == ai_family)
+ {
+ break;
+ }
+ }
+ if (!cur)
+ {
+ msg(M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
+ prefix, addr_family_name(ai_family));
}
- if (!cur)
- msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record",
- prefix, addr_family_name(ai_family));
- if (ai_family == AF_INET6)
+ if (ai_family == AF_INET6)
{
- int v6only = ipv6only ? 1: 0; /* setsockopt must have an "int" */
+ int v6only = ipv6only ? 1 : 0; /* setsockopt must have an "int" */
- msg (M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only);
- if (setsockopt (sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &v6only, sizeof(v6only)))
- {
- msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
- }
+ msg(M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only);
+ if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) &v6only, sizeof(v6only)))
+ {
+ msg(M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
+ }
}
- if (bind (sd, cur->ai_addr, cur->ai_addrlen))
+ 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_ex (local->ai_addr, ":", PS_SHOW_PORT, &gc),
- strerror_ts (errnum, &gc));
+ const int errnum = openvpn_errno();
+ msg(M_FATAL, "%s: Socket bind failed on local address %s: %s",
+ prefix,
+ print_sockaddr_ex(local->ai_addr, ":", PS_SHOW_PORT, &gc),
+ strerror_ts(errnum, &gc));
}
- gc_free (&gc);
+ gc_free(&gc);
}
int
-openvpn_connect (socket_descriptor_t sd,
- const struct sockaddr *remote,
- int connect_timeout,
- volatile int *signal_received)
+openvpn_connect(socket_descriptor_t sd,
+ const struct sockaddr *remote,
+ int connect_timeout,
+ volatile int *signal_received)
{
- int status = 0;
+ int status = 0;
#ifdef TARGET_ANDROID
- protect_fd_nonlocal(sd, remote);
+ protect_fd_nonlocal(sd, remote);
#endif
#ifdef CONNECT_NONBLOCK
- set_nonblock (sd);
- status = connect (sd, remote, af_addr_size(remote->sa_family));
- if (status)
- status = openvpn_errno ();
- if (
+ set_nonblock(sd);
+ status = connect(sd, remote, af_addr_size(remote->sa_family));
+ if (status)
+ {
+ status = openvpn_errno();
+ }
+ if (
#ifdef _WIN32
- status == WSAEWOULDBLOCK
+ status == WSAEWOULDBLOCK
#else
- status == EINPROGRESS
+ status == EINPROGRESS
#endif
- )
+ )
{
- while (true)
- {
+ while (true)
+ {
#if POLL
- struct pollfd fds[1];
- fds[0].fd = sd;
- fds[0].events = POLLOUT;
- status = poll(fds, 1, 0);
+ struct pollfd fds[1];
+ fds[0].fd = sd;
+ fds[0].events = POLLOUT;
+ status = poll(fds, 1, 0);
#else
- fd_set writes;
- struct timeval tv;
+ fd_set writes;
+ struct timeval tv;
- FD_ZERO (&writes);
- openvpn_fd_set (sd, &writes);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
+ FD_ZERO(&writes);
+ openvpn_fd_set(sd, &writes);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
- status = select (sd + 1, NULL, &writes, NULL, &tv);
+ status = select(sd + 1, NULL, &writes, NULL, &tv);
#endif
- if (signal_received)
- {
- get_signal (signal_received);
- if (*signal_received)
- {
- status = 0;
- break;
- }
- }
- if (status < 0)
- {
- status = openvpn_errno ();
- break;
- }
- if (status <= 0)
- {
- if (--connect_timeout < 0)
- {
+ if (signal_received)
+ {
+ get_signal(signal_received);
+ if (*signal_received)
+ {
+ status = 0;
+ break;
+ }
+ }
+ if (status < 0)
+ {
+ status = openvpn_errno();
+ break;
+ }
+ if (status <= 0)
+ {
+ if (--connect_timeout < 0)
+ {
#ifdef _WIN32
- status = WSAETIMEDOUT;
+ status = WSAETIMEDOUT;
#else
- status = ETIMEDOUT;
+ status = ETIMEDOUT;
#endif
- break;
- }
- openvpn_sleep (1);
- continue;
- }
-
- /* got it */
- {
- int val = 0;
- socklen_t len;
-
- len = sizeof (val);
- if (getsockopt (sd, SOL_SOCKET, SO_ERROR, (void *) &val, &len) == 0
- && len == sizeof (val))
- status = val;
- else
- status = openvpn_errno ();
- break;
- }
- }
+ break;
+ }
+ openvpn_sleep(1);
+ continue;
+ }
+
+ /* got it */
+ {
+ int val = 0;
+ socklen_t len;
+
+ len = sizeof(val);
+ if (getsockopt(sd, SOL_SOCKET, SO_ERROR, (void *) &val, &len) == 0
+ && len == sizeof(val))
+ {
+ status = val;
+ }
+ else
+ {
+ status = openvpn_errno();
+ }
+ break;
+ }
+ }
}
-#else
- status = connect (sd, remote, af_addr_size(remote->sa_family));
- if (status)
- status = openvpn_errno ();
-#endif
+#else /* ifdef CONNECT_NONBLOCK */
+ status = connect(sd, remote, af_addr_size(remote->sa_family));
+ if (status)
+ {
+ status = openvpn_errno();
+ }
+#endif /* ifdef CONNECT_NONBLOCK */
- return status;
+ return status;
}
-void set_actual_address (struct link_socket_actual* actual, struct addrinfo* ai)
+void
+set_actual_address(struct link_socket_actual *actual, struct addrinfo *ai)
{
- CLEAR (*actual);
- ASSERT (ai);
+ CLEAR(*actual);
+ ASSERT(ai);
if (ai->ai_family == AF_INET)
+ {
actual->dest.addr.in4 =
- *((struct sockaddr_in*) ai->ai_addr);
+ *((struct sockaddr_in *) ai->ai_addr);
+ }
else if (ai->ai_family == AF_INET6)
+ {
actual->dest.addr.in6 =
- *((struct sockaddr_in6*) ai->ai_addr);
+ *((struct sockaddr_in6 *) ai->ai_addr);
+ }
else
+ {
ASSERT(0);
+ }
}
void
-socket_connect (socket_descriptor_t* sd,
- const struct sockaddr* dest,
- const int connect_timeout,
- struct signal_info* sig_info)
+socket_connect(socket_descriptor_t *sd,
+ const struct sockaddr *dest,
+ const int connect_timeout,
+ struct signal_info *sig_info)
{
- struct gc_arena gc = gc_new ();
- int status;
+ struct gc_arena gc = gc_new();
+ int status;
#ifdef CONNECT_NONBLOCK
- msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]",
- print_sockaddr (dest, &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 (dest, &gc));
+ msg(M_INFO, "Attempting to establish TCP connection with %s",
+ print_sockaddr(dest, &gc));
#endif
#ifdef ENABLE_MANAGEMENT
- if (management)
- management_set_state (management,
- OPENVPN_STATE_TCP_CONNECT,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
+ if (management)
+ {
+ management_set_state(management,
+ OPENVPN_STATE_TCP_CONNECT,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
#endif
- /* Set the actual address */
- status = openvpn_connect (*sd, dest, connect_timeout, &sig_info->signal_received);
+ /* Set the actual address */
+ status = openvpn_connect(*sd, dest, connect_timeout, &sig_info->signal_received);
- get_signal (&sig_info->signal_received);
- if (sig_info->signal_received)
- goto done;
+ get_signal(&sig_info->signal_received);
+ if (sig_info->signal_received)
+ {
+ goto done;
+ }
- if (status) {
+ if (status)
+ {
- msg (D_LINK_ERRORS,
- "TCP: connect to %s failed: %s",
- print_sockaddr (dest, &gc),
- strerror_ts (status, &gc));
+ msg(D_LINK_ERRORS,
+ "TCP: connect to %s failed: %s",
+ print_sockaddr(dest, &gc),
+ strerror_ts(status, &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));
- }
+ 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);
+done:
+ gc_free(&gc);
}
/* For stream protocols, allocate a buffer to build up packet.
- Called after frame has been finalized. */
+ * Called after frame has been finalized. */
static void
-socket_frame_init (const struct frame *frame, struct link_socket *sock)
+socket_frame_init(const struct frame *frame, struct link_socket *sock)
{
#ifdef _WIN32
- overlapped_io_init (&sock->reads, frame, FALSE, false);
- overlapped_io_init (&sock->writes, frame, TRUE, false);
- sock->rw_handle.read = sock->reads.overlapped.hEvent;
- sock->rw_handle.write = sock->writes.overlapped.hEvent;
+ overlapped_io_init(&sock->reads, frame, FALSE, false);
+ overlapped_io_init(&sock->writes, frame, TRUE, false);
+ sock->rw_handle.read = sock->reads.overlapped.hEvent;
+ sock->rw_handle.write = sock->writes.overlapped.hEvent;
#endif
- if (link_socket_connection_oriented (sock))
+ if (link_socket_connection_oriented(sock))
{
#ifdef _WIN32
- stream_buf_init (&sock->stream_buf,
- &sock->reads.buf_init,
- sock->sockflags,
- sock->info.proto);
+ stream_buf_init(&sock->stream_buf,
+ &sock->reads.buf_init,
+ sock->sockflags,
+ sock->info.proto);
#else
- alloc_buf_sock_tun (&sock->stream_buf_data,
- frame,
- false,
- FRAME_HEADROOM_MARKER_READ_STREAM);
-
- stream_buf_init (&sock->stream_buf,
- &sock->stream_buf_data,
- sock->sockflags,
- sock->info.proto);
+ alloc_buf_sock_tun(&sock->stream_buf_data,
+ frame,
+ false,
+ FRAME_HEADROOM_MARKER_READ_STREAM);
+
+ stream_buf_init(&sock->stream_buf,
+ &sock->stream_buf_data,
+ sock->sockflags,
+ sock->info.proto);
#endif
}
}
@@ -1329,798 +1529,864 @@ socket_frame_init (const struct frame *frame, struct link_socket *sock)
* to us by the OS.
*/
void
-frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto)
+frame_adjust_path_mtu(struct frame *frame, int pmtu, int proto)
{
- frame_set_mtu_dynamic (frame, pmtu - datagram_overhead (proto), SET_MTU_UPPER_BOUND);
+ frame_set_mtu_dynamic(frame, pmtu - datagram_overhead(proto), SET_MTU_UPPER_BOUND);
}
static void
-resolve_bind_local (struct link_socket *sock, const sa_family_t af)
+resolve_bind_local(struct link_socket *sock, const sa_family_t af)
{
- struct gc_arena gc = gc_new ();
+ struct gc_arena gc = gc_new();
- /* resolve local address if undefined */
- if (!sock->info.lsa->bind_local)
+ /* resolve local address if undefined */
+ if (!sock->info.lsa->bind_local)
{
- int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL |
- GETADDR_FATAL | GETADDR_PASSIVE;
- int status;
+ int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL
+ |GETADDR_FATAL | GETADDR_PASSIVE;
+ int status;
- if(proto_is_dgram(sock->info.proto))
- flags |= GETADDR_DATAGRAM;
+ if (proto_is_dgram(sock->info.proto))
+ {
+ flags |= GETADDR_DATAGRAM;
+ }
- /* will return AF_{INET|INET6}from local_host */
- status = get_cached_dns_entry (sock->dns_cache,
- sock->local_host,
- sock->local_port,
- af,
- flags,
- &sock->info.lsa->bind_local);
+ /* will return AF_{INET|INET6}from local_host */
+ status = get_cached_dns_entry(sock->dns_cache,
+ sock->local_host,
+ sock->local_port,
+ af,
+ flags,
+ &sock->info.lsa->bind_local);
- if (status)
- status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0,
- NULL, af, &sock->info.lsa->bind_local);
+ if (status)
+ {
+ 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));
- }
+ if (status !=0)
+ {
+ msg(M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s",
+ sock->local_host, sock->local_port,
+ gai_strerror(status));
+ }
}
- gc_free (&gc);
+ gc_free(&gc);
}
static void
-resolve_remote (struct link_socket *sock,
- int phase,
- const char **remote_dynamic,
- volatile int *signal_received)
-{
- struct gc_arena gc = gc_new ();
-
- /* resolve remote address if undefined */
- if (!sock->info.lsa->remote_list)
- {
- if (sock->remote_host)
- {
- unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
- int retry = 0;
- int status = -1;
- struct addrinfo* ai;
- if (proto_is_dgram(sock->info.proto))
- flags |= GETADDR_DATAGRAM;
-
- if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
- {
- if (phase == 2)
- flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
- retry = 0;
- }
- else if (phase == 1)
- {
- if (sock->resolve_retry_seconds)
- {
- retry = 0;
- }
- else
- {
- flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY);
- retry = 0;
- }
- }
- else if (phase == 2)
- {
- if (sock->resolve_retry_seconds)
- {
- flags |= GETADDR_FATAL;
- retry = sock->resolve_retry_seconds;
- }
- else
- {
- ASSERT (0);
- }
- }
- else
- {
- ASSERT (0);
- }
-
-
- status = get_cached_dns_entry (sock->dns_cache,
- sock->remote_host,
- sock->remote_port,
- sock->info.af,
- flags, &ai);
- if (status)
- status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port,
- retry, signal_received, sock->info.af, &ai);
-
- if(status == 0) {
- 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,
- phase,
- retry,
- signal_received ? *signal_received : -1,
- status);
- }
- if (signal_received)
- {
- if (*signal_received)
- goto done;
- }
- if (status!=0)
- {
- if (signal_received)
- *signal_received = SIGUSR1;
- goto done;
- }
- }
- }
-
- /* should we re-use previous active remote address? */
- if (link_socket_actual_defined (&sock->info.lsa->actual))
- {
- msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s",
- print_link_socket_actual (&sock->info.lsa->actual, &gc));
- if (remote_dynamic)
- *remote_dynamic = NULL;
- }
- else
- {
- CLEAR (sock->info.lsa->actual);
- if(sock->info.lsa->current_remote)
- {
- set_actual_address (&sock->info.lsa->actual,
- sock->info.lsa->current_remote);
- }
- }
-
- done:
- gc_free (&gc);
+resolve_remote(struct link_socket *sock,
+ int phase,
+ const char **remote_dynamic,
+ volatile int *signal_received)
+{
+ struct gc_arena gc = gc_new();
+
+ /* resolve remote address if undefined */
+ if (!sock->info.lsa->remote_list)
+ {
+ if (sock->remote_host)
+ {
+ unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags);
+ int retry = 0;
+ int status = -1;
+ struct addrinfo *ai;
+ if (proto_is_dgram(sock->info.proto))
+ {
+ flags |= GETADDR_DATAGRAM;
+ }
+
+ if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
+ {
+ if (phase == 2)
+ {
+ flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
+ }
+ retry = 0;
+ }
+ else if (phase == 1)
+ {
+ if (sock->resolve_retry_seconds)
+ {
+ retry = 0;
+ }
+ else
+ {
+ flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY);
+ retry = 0;
+ }
+ }
+ else if (phase == 2)
+ {
+ if (sock->resolve_retry_seconds)
+ {
+ flags |= GETADDR_FATAL;
+ retry = sock->resolve_retry_seconds;
+ }
+ else
+ {
+ ASSERT(0);
+ }
+ }
+ else
+ {
+ ASSERT(0);
+ }
+
+
+ status = get_cached_dns_entry(sock->dns_cache,
+ sock->remote_host,
+ sock->remote_port,
+ sock->info.af,
+ flags, &ai);
+ if (status)
+ {
+ status = openvpn_getaddrinfo(flags, sock->remote_host, sock->remote_port,
+ retry, signal_received, sock->info.af, &ai);
+ }
+
+ if (status == 0)
+ {
+ 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,
+ phase,
+ retry,
+ signal_received ? *signal_received : -1,
+ status);
+ }
+ if (signal_received)
+ {
+ if (*signal_received)
+ {
+ goto done;
+ }
+ }
+ if (status!=0)
+ {
+ if (signal_received)
+ {
+ *signal_received = SIGUSR1;
+ }
+ goto done;
+ }
+ }
+ }
+
+ /* should we re-use previous active remote address? */
+ if (link_socket_actual_defined(&sock->info.lsa->actual))
+ {
+ msg(M_INFO, "TCP/UDP: Preserving recently used remote address: %s",
+ print_link_socket_actual(&sock->info.lsa->actual, &gc));
+ if (remote_dynamic)
+ {
+ *remote_dynamic = NULL;
+ }
+ }
+ else
+ {
+ CLEAR(sock->info.lsa->actual);
+ if (sock->info.lsa->current_remote)
+ {
+ set_actual_address(&sock->info.lsa->actual,
+ sock->info.lsa->current_remote);
+ }
+ }
+
+done:
+ gc_free(&gc);
}
struct link_socket *
-link_socket_new (void)
+link_socket_new(void)
{
- struct link_socket *sock;
+ struct link_socket *sock;
- ALLOC_OBJ_CLEAR (sock, struct link_socket);
- sock->sd = SOCKET_UNDEFINED;
- sock->ctrl_sd = SOCKET_UNDEFINED;
- return sock;
+ ALLOC_OBJ_CLEAR(sock, struct link_socket);
+ sock->sd = SOCKET_UNDEFINED;
+ sock->ctrl_sd = SOCKET_UNDEFINED;
+ return sock;
}
void
-link_socket_init_phase1 (struct link_socket *sock,
- const char *local_host,
- const char *local_port,
- const char *remote_host,
- const char *remote_port,
- struct cached_dns_entry *dns_cache,
- int proto,
- sa_family_t af,
- bool bind_ipv6_only,
- int mode,
- const struct link_socket *accept_from,
- struct http_proxy_info *http_proxy,
- struct socks_proxy_info *socks_proxy,
+link_socket_init_phase1(struct link_socket *sock,
+ const char *local_host,
+ const char *local_port,
+ const char *remote_host,
+ const char *remote_port,
+ struct cached_dns_entry *dns_cache,
+ int proto,
+ sa_family_t af,
+ bool bind_ipv6_only,
+ int mode,
+ const struct link_socket *accept_from,
+ struct http_proxy_info *http_proxy,
+ struct socks_proxy_info *socks_proxy,
#ifdef ENABLE_DEBUG
- int gremlin,
+ int gremlin,
#endif
- bool bind_local,
- bool remote_float,
- int inetd,
- struct link_socket_addr *lsa,
- const char *ipchange_command,
- const struct plugin_list *plugins,
- int resolve_retry_seconds,
- int mtu_discover_type,
- int rcvbuf,
- int sndbuf,
- int mark,
- struct event_timeout* server_poll_timeout,
- unsigned int sockflags)
-{
- ASSERT (sock);
-
- sock->local_host = local_host;
- sock->local_port = local_port;
- sock->remote_host = remote_host;
- sock->remote_port = remote_port;
- sock->dns_cache = dns_cache;
- sock->http_proxy = http_proxy;
- sock->socks_proxy = socks_proxy;
- sock->bind_local = bind_local;
- sock->inetd = inetd;
- sock->resolve_retry_seconds = resolve_retry_seconds;
- sock->mtu_discover_type = mtu_discover_type;
+ bool bind_local,
+ bool remote_float,
+ int inetd,
+ struct link_socket_addr *lsa,
+ const char *ipchange_command,
+ const struct plugin_list *plugins,
+ int resolve_retry_seconds,
+ int mtu_discover_type,
+ int rcvbuf,
+ int sndbuf,
+ int mark,
+ struct event_timeout *server_poll_timeout,
+ unsigned int sockflags)
+{
+ ASSERT(sock);
+
+ sock->local_host = local_host;
+ sock->local_port = local_port;
+ sock->remote_host = remote_host;
+ sock->remote_port = remote_port;
+ sock->dns_cache = dns_cache;
+ sock->http_proxy = http_proxy;
+ sock->socks_proxy = socks_proxy;
+ sock->bind_local = bind_local;
+ sock->inetd = inetd;
+ sock->resolve_retry_seconds = resolve_retry_seconds;
+ sock->mtu_discover_type = mtu_discover_type;
#ifdef ENABLE_DEBUG
- sock->gremlin = gremlin;
+ sock->gremlin = gremlin;
#endif
- sock->socket_buffer_sizes.rcvbuf = rcvbuf;
- sock->socket_buffer_sizes.sndbuf = sndbuf;
+ sock->socket_buffer_sizes.rcvbuf = rcvbuf;
+ sock->socket_buffer_sizes.sndbuf = sndbuf;
- sock->sockflags = sockflags;
- sock->mark = mark;
+ sock->sockflags = sockflags;
+ sock->mark = mark;
- sock->info.proto = proto;
- sock->info.af = af;
- sock->info.remote_float = remote_float;
- sock->info.lsa = lsa;
- sock->info.bind_ipv6_only = bind_ipv6_only;
- sock->info.ipchange_command = ipchange_command;
- sock->info.plugins = plugins;
- sock->server_poll_timeout = server_poll_timeout;
+ sock->info.proto = proto;
+ sock->info.af = af;
+ sock->info.remote_float = remote_float;
+ sock->info.lsa = lsa;
+ sock->info.bind_ipv6_only = bind_ipv6_only;
+ sock->info.ipchange_command = ipchange_command;
+ sock->info.plugins = plugins;
+ sock->server_poll_timeout = server_poll_timeout;
- sock->mode = mode;
- if (mode == LS_MODE_TCP_ACCEPT_FROM)
+ sock->mode = mode;
+ if (mode == LS_MODE_TCP_ACCEPT_FROM)
{
- ASSERT (accept_from);
- ASSERT (sock->info.proto == PROTO_TCP_SERVER);
- ASSERT (!sock->inetd);
- sock->sd = accept_from->sd;
+ ASSERT(accept_from);
+ ASSERT(sock->info.proto == PROTO_TCP_SERVER);
+ ASSERT(!sock->inetd);
+ sock->sd = accept_from->sd;
}
- /* are we running in HTTP proxy mode? */
- if (sock->http_proxy)
+ /* are we running in HTTP proxy mode? */
+ if (sock->http_proxy)
{
- ASSERT (sock->info.proto == PROTO_TCP_CLIENT);
- ASSERT (!sock->inetd);
+ ASSERT(sock->info.proto == PROTO_TCP_CLIENT);
+ ASSERT(!sock->inetd);
- /* the proxy server */
- sock->remote_host = http_proxy->options.server;
- sock->remote_port = http_proxy->options.port;
+ /* the proxy server */
+ sock->remote_host = http_proxy->options.server;
+ sock->remote_port = http_proxy->options.port;
- /* the OpenVPN server we will use the proxy to connect to */
- sock->proxy_dest_host = remote_host;
- sock->proxy_dest_port = remote_port;
+ /* the OpenVPN server we will use the proxy to connect to */
+ sock->proxy_dest_host = remote_host;
+ sock->proxy_dest_port = remote_port;
}
- /* or in Socks proxy mode? */
- else if (sock->socks_proxy)
+ /* or in Socks proxy mode? */
+ else if (sock->socks_proxy)
{
- ASSERT (!sock->inetd);
+ ASSERT(!sock->inetd);
- /* the proxy server */
- sock->remote_host = socks_proxy->server;
- sock->remote_port = socks_proxy->port;
+ /* the proxy server */
+ sock->remote_host = socks_proxy->server;
+ sock->remote_port = socks_proxy->port;
- /* the OpenVPN server we will use the proxy to connect to */
- sock->proxy_dest_host = remote_host;
- sock->proxy_dest_port = remote_port;
+ /* the OpenVPN server we will use the proxy to connect to */
+ sock->proxy_dest_host = remote_host;
+ sock->proxy_dest_port = remote_port;
}
- else
+ else
{
- sock->remote_host = remote_host;
- sock->remote_port = remote_port;
+ sock->remote_host = remote_host;
+ sock->remote_port = remote_port;
}
- /* bind behavior for TCP server vs. client */
- if (sock->info.proto == PROTO_TCP_SERVER)
+ /* bind behavior for TCP server vs. client */
+ if (sock->info.proto == PROTO_TCP_SERVER)
{
- if (sock->mode == LS_MODE_TCP_ACCEPT_FROM)
- sock->bind_local = false;
- else
- sock->bind_local = true;
+ if (sock->mode == LS_MODE_TCP_ACCEPT_FROM)
+ {
+ sock->bind_local = false;
+ }
+ else
+ {
+ sock->bind_local = true;
+ }
}
- /* were we started by inetd or xinetd? */
- if (sock->inetd)
+ /* were we started by inetd or xinetd? */
+ if (sock->inetd)
{
- ASSERT (sock->info.proto != PROTO_TCP_CLIENT);
- ASSERT (socket_defined (inetd_socket_descriptor));
- sock->sd = inetd_socket_descriptor;
+ ASSERT(sock->info.proto != PROTO_TCP_CLIENT);
+ ASSERT(socket_defined(inetd_socket_descriptor));
+ sock->sd = inetd_socket_descriptor;
+ set_cloexec(sock->sd); /* not created by create_socket*() */
}
- else if (mode != LS_MODE_TCP_ACCEPT_FROM)
+ else if (mode != LS_MODE_TCP_ACCEPT_FROM)
{
- if (sock->bind_local) {
- resolve_bind_local (sock, sock->info.af);
- }
- resolve_remote (sock, 1, NULL, NULL);
+ if (sock->bind_local)
+ {
+ resolve_bind_local(sock, sock->info.af);
+ }
+ resolve_remote(sock, 1, NULL, NULL);
}
}
static
-void phase2_inetd (struct link_socket* sock, const struct frame *frame,
- const char *remote_dynamic, volatile int *signal_received)
+void
+phase2_inetd(struct link_socket *sock, const struct frame *frame,
+ const char *remote_dynamic, volatile int *signal_received)
{
- bool remote_changed = false;
+ bool remote_changed = false;
- 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
+ if (sock->info.proto == PROTO_TCP_SERVER)
{
- /* 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);
+ /* 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, &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 /* ifdef HAVE_GETSOCKNAME */
+ msg(M_WARN, "inetd(%s): this OS does not provide the getsockname() "
+ "function, using AF_INET",
+ proto2ascii(sock->info.proto, false));
+#endif /* ifdef HAVE_GETSOCKNAME */
+ 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);
+ }
+ ASSERT(!remote_changed);
}
static void
-phase2_set_socket_flags (struct link_socket* sock)
+phase2_set_socket_flags(struct link_socket *sock)
{
- /* set misc socket parameters */
- socket_set_flags (sock->sd, sock->sockflags);
+ /* set misc socket parameters */
+ socket_set_flags(sock->sd, sock->sockflags);
- /* set socket to non-blocking mode */
- set_nonblock (sock->sd);
+ /* set socket to non-blocking mode */
+ set_nonblock(sock->sd);
- /* set socket file descriptor to not pass across execs, so that
- scripts don't have access to it */
- set_cloexec (sock->sd);
-
- if (socket_defined (sock->ctrl_sd))
- set_cloexec (sock->ctrl_sd);
-
- /* set Path MTU discovery options on the socket */
- set_mtu_discover_type (sock->sd, sock->mtu_discover_type, sock->info.af);
+ /* set Path MTU discovery options on the socket */
+ set_mtu_discover_type(sock->sd, sock->mtu_discover_type, sock->info.af);
#if EXTENDED_SOCKET_ERROR_CAPABILITY
- /* if the OS supports it, enable extended error passing on the socket */
- set_sock_extended_error_passing (sock->sd);
+ /* 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 ();
- const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO;
-
- /* print local address */
- if (sock->inetd)
- msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true));
- else if (sock->bind_local)
- {
- sa_family_t ai_family = sock->info.lsa->actual.dest.addr.sa.sa_family;
- /* Socket is always bound on the first matching address,
- * For bound sockets with no remote addr this is the element of
- * the list */
- struct addrinfo *cur;
- for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next)
- {
- if(!ai_family || ai_family == cur->ai_family)
- break;
- }
- ASSERT (cur);
- msg (msglevel, "%s link local (bound): %s",
- proto2ascii (sock->info.proto, sock->info.af, true),
- print_sockaddr(cur->ai_addr,&gc));
- }
- else
- msg (msglevel, "%s link local: (not bound)",
- proto2ascii (sock->info.proto, sock->info.af, true));
-
- /* print active remote address */
- msg (msglevel, "%s link remote: %s",
- proto2ascii (sock->info.proto, sock->info.af, true),
- print_link_socket_actual_ex (&sock->info.lsa->actual,
- ":",
- PS_SHOW_PORT_IF_DEFINED,
- &gc));
- gc_free(&gc);
+linksock_print_addr(struct link_socket *sock)
+{
+ struct gc_arena gc = gc_new();
+ const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO;
+
+ /* print local address */
+ if (sock->inetd)
+ {
+ msg(msglevel, "%s link local: [inetd]", proto2ascii(sock->info.proto, sock->info.af, true));
+ }
+ else if (sock->bind_local)
+ {
+ sa_family_t ai_family = sock->info.lsa->actual.dest.addr.sa.sa_family;
+ /* Socket is always bound on the first matching address,
+ * For bound sockets with no remote addr this is the element of
+ * the list */
+ struct addrinfo *cur;
+ for (cur = sock->info.lsa->bind_local; cur; cur = cur->ai_next)
+ {
+ if (!ai_family || ai_family == cur->ai_family)
+ {
+ break;
+ }
+ }
+ ASSERT(cur);
+ msg(msglevel, "%s link local (bound): %s",
+ proto2ascii(sock->info.proto, sock->info.af, true),
+ print_sockaddr(cur->ai_addr,&gc));
+ }
+ else
+ {
+ msg(msglevel, "%s link local: (not bound)",
+ proto2ascii(sock->info.proto, sock->info.af, true));
+ }
+
+ /* print active remote address */
+ msg(msglevel, "%s link remote: %s",
+ proto2ascii(sock->info.proto, sock->info.af, true),
+ print_link_socket_actual_ex(&sock->info.lsa->actual,
+ ":",
+ PS_SHOW_PORT_IF_DEFINED,
+ &gc));
+ 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,
- 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);
+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,
+ 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)
+phase2_tcp_client(struct link_socket *sock, struct signal_info *sig_info)
{
- bool proxy_retry = false;
- do {
- socket_connect (&sock->sd,
- sock->info.lsa->current_remote->ai_addr,
- get_server_poll_remaining_time (sock->server_poll_timeout),
- sig_info);
+ bool proxy_retry = false;
+ do {
+ socket_connect(&sock->sd,
+ sock->info.lsa->current_remote->ai_addr,
+ get_server_poll_remaining_time(sock->server_poll_timeout),
+ sig_info);
- if (sig_info->signal_received)
- return;
+ if (sig_info->signal_received)
+ {
+ return;
+ }
- if (sock->http_proxy)
- {
- proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
- sock->sd,
- sock->proxy_dest_host,
- sock->proxy_dest_port,
- sock->server_poll_timeout,
- &sock->stream_buf.residual,
- &sig_info->signal_received);
- }
- else if (sock->socks_proxy)
- {
- establish_socks_proxy_passthru (sock->socks_proxy,
- sock->sd,
- sock->proxy_dest_host,
- sock->proxy_dest_port,
- &sig_info->signal_received);
- }
- if (proxy_retry)
- {
- openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp (sock->info.lsa->current_remote);
- }
+ if (sock->http_proxy)
+ {
+ proxy_retry = establish_http_proxy_passthru(sock->http_proxy,
+ sock->sd,
+ sock->proxy_dest_host,
+ sock->proxy_dest_port,
+ sock->server_poll_timeout,
+ &sock->stream_buf.residual,
+ &sig_info->signal_received);
+ }
+ else if (sock->socks_proxy)
+ {
+ establish_socks_proxy_passthru(sock->socks_proxy,
+ sock->sd,
+ sock->proxy_dest_host,
+ sock->proxy_dest_port,
+ &sig_info->signal_received);
+ }
+ if (proxy_retry)
+ {
+ openvpn_close_socket(sock->sd);
+ sock->sd = create_socket_tcp(sock->info.lsa->current_remote);
+ }
- } while (proxy_retry);
+ } while (proxy_retry);
}
static void
-phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info)
+phase2_socks_client(struct link_socket *sock, struct signal_info *sig_info)
{
- socket_connect (&sock->ctrl_sd,
- sock->info.lsa->current_remote->ai_addr,
- get_server_poll_remaining_time (sock->server_poll_timeout),
- sig_info);
+ socket_connect(&sock->ctrl_sd,
+ sock->info.lsa->current_remote->ai_addr,
+ get_server_poll_remaining_time(sock->server_poll_timeout),
+ sig_info);
if (sig_info->signal_received)
- return;
+ {
+ return;
+ }
- establish_socks_proxy_udpassoc (sock->socks_proxy,
- sock->ctrl_sd,
- sock->sd,
- &sock->socks_relay.dest,
- &sig_info->signal_received);
+ 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;
+ {
+ return;
+ }
sock->remote_host = sock->proxy_dest_host;
sock->remote_port = sock->proxy_dest_port;
addr_zero_host(&sock->info.lsa->actual.dest);
if (sock->info.lsa->remote_list)
- {
- freeaddrinfo(sock->info.lsa->remote_list);
- sock->info.lsa->current_remote = NULL;
- sock->info.lsa->remote_list = NULL;
- }
+ {
+ freeaddrinfo(sock->info.lsa->remote_list);
+ sock->info.lsa->current_remote = NULL;
+ sock->info.lsa->remote_list = NULL;
+ }
- resolve_remote (sock, 1, NULL, &sig_info->signal_received);
+ resolve_remote(sock, 1, NULL, &sig_info->signal_received);
}
/* 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);
- ASSERT (sig_info);
-
- if (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->signal_received)
- goto done;
-
- }
- else
- {
- /* Second chance to resolv/create socket */
- resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received);
-
- /* If a valid remote has been found, create the socket with its addrinfo */
- if (sock->info.lsa->current_remote)
- create_socket (sock, sock->info.lsa->current_remote);
-
- /* If socket has not already been created create it now */
- if (sock->sd == SOCKET_UNDEFINED)
- {
- /* If we have no --remote and have still not figured out the
- * protocol family to use we will use the first of the bind */
-
- if (sock->bind_local && !sock->remote_host && sock->info.lsa->bind_local)
- {
- /* Warn if this is because neither v4 or v6 was specified
- * and we should not connect a remote */
- if (sock->info.af == AF_UNSPEC)
- {
- msg (M_WARN, "Could not determine IPv4/IPv6 protocol. Using %s",
- addr_family_name(sock->info.lsa->bind_local->ai_family));
- sock->info.af = sock->info.lsa->bind_local->ai_family;
- }
-
- create_socket (sock, sock->info.lsa->bind_local);
- }
- }
-
- /* Socket still undefined, give a warning and abort connection */
- if (sock->sd == SOCKET_UNDEFINED)
- {
- msg (M_WARN, "Could not determine IPv4/IPv6 protocol");
- sig_info->signal_received = SIGUSR1;
- goto done;
- }
-
- if (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);
-
- }
- else if (sock->info.proto == PROTO_UDP && sock->socks_proxy)
- {
- phase2_socks_client (sock, sig_info);
- }
+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);
+ ASSERT(sig_info);
+
+ if (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->signal_received)
+ {
+ goto done;
+ }
+
+ }
+ else
+ {
+ /* Second chance to resolv/create socket */
+ resolve_remote(sock, 2, &remote_dynamic, &sig_info->signal_received);
+
+ /* If a valid remote has been found, create the socket with its addrinfo */
+ if (sock->info.lsa->current_remote)
+ {
+ create_socket(sock, sock->info.lsa->current_remote);
+ }
+
+ /* If socket has not already been created create it now */
+ if (sock->sd == SOCKET_UNDEFINED)
+ {
+ /* If we have no --remote and have still not figured out the
+ * protocol family to use we will use the first of the bind */
+
+ if (sock->bind_local && !sock->remote_host && sock->info.lsa->bind_local)
+ {
+ /* Warn if this is because neither v4 or v6 was specified
+ * and we should not connect a remote */
+ if (sock->info.af == AF_UNSPEC)
+ {
+ msg(M_WARN, "Could not determine IPv4/IPv6 protocol. Using %s",
+ addr_family_name(sock->info.lsa->bind_local->ai_family));
+ sock->info.af = sock->info.lsa->bind_local->ai_family;
+ }
+
+ create_socket(sock, sock->info.lsa->bind_local);
+ }
+ }
+
+ /* Socket still undefined, give a warning and abort connection */
+ if (sock->sd == SOCKET_UNDEFINED)
+ {
+ msg(M_WARN, "Could not determine IPv4/IPv6 protocol");
+ sig_info->signal_received = SIGUSR1;
+ goto done;
+ }
+
+ if (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);
+
+ }
+ else if (sock->info.proto == PROTO_UDP && sock->socks_proxy)
+ {
+ phase2_socks_client(sock, sig_info);
+ }
#ifdef TARGET_ANDROID
- if (sock->sd != -1)
- protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa);
+ if (sock->sd != -1)
+ {
+ protect_fd_nonlocal(sock->sd, &sock->info.lsa->actual.dest.addr.sa);
+ }
#endif
- if (sig_info->signal_received)
- goto done;
+ if (sig_info->signal_received)
+ {
+ goto done;
+ }
}
- phase2_set_socket_flags(sock);
- linksock_print_addr(sock);
+ phase2_set_socket_flags(sock);
+ linksock_print_addr(sock);
- done:
- if (sig_save)
+done:
+ if (sig_save)
{
- if (!sig_info->signal_received)
- sig_info->signal_received = sig_save;
+ if (!sig_info->signal_received)
+ {
+ sig_info->signal_received = sig_save;
+ }
}
}
void
-link_socket_close (struct link_socket *sock)
+link_socket_close(struct link_socket *sock)
{
- if (sock)
+ if (sock)
{
#ifdef ENABLE_DEBUG
- const int gremlin = GREMLIN_CONNECTION_FLOOD_LEVEL (sock->gremlin);
+ const int gremlin = GREMLIN_CONNECTION_FLOOD_LEVEL(sock->gremlin);
#else
- const int gremlin = 0;
+ const int gremlin = 0;
#endif
- if (socket_defined (sock->sd))
- {
+ if (socket_defined(sock->sd))
+ {
#ifdef _WIN32
- close_net_event_win32 (&sock->listen_handle, sock->sd, 0);
+ close_net_event_win32(&sock->listen_handle, sock->sd, 0);
#endif
- if (!gremlin)
- {
- msg (D_LOW, "TCP/UDP: Closing socket");
- if (openvpn_close_socket (sock->sd))
- msg (M_WARN | M_ERRNO, "TCP/UDP: Close Socket failed");
- }
- sock->sd = SOCKET_UNDEFINED;
+ if (!gremlin)
+ {
+ msg(D_LOW, "TCP/UDP: Closing socket");
+ if (openvpn_close_socket(sock->sd))
+ {
+ msg(M_WARN | M_ERRNO, "TCP/UDP: Close Socket failed");
+ }
+ }
+ sock->sd = SOCKET_UNDEFINED;
#ifdef _WIN32
- if (!gremlin)
- {
- overlapped_io_close (&sock->reads);
- overlapped_io_close (&sock->writes);
- }
+ if (!gremlin)
+ {
+ overlapped_io_close(&sock->reads);
+ overlapped_io_close(&sock->writes);
+ }
#endif
- }
+ }
- if (socket_defined (sock->ctrl_sd))
- {
- if (openvpn_close_socket (sock->ctrl_sd))
- msg (M_WARN | M_ERRNO, "TCP/UDP: Close Socket (ctrl_sd) failed");
- sock->ctrl_sd = SOCKET_UNDEFINED;
- }
+ if (socket_defined(sock->ctrl_sd))
+ {
+ if (openvpn_close_socket(sock->ctrl_sd))
+ {
+ msg(M_WARN | M_ERRNO, "TCP/UDP: Close Socket (ctrl_sd) failed");
+ }
+ sock->ctrl_sd = SOCKET_UNDEFINED;
+ }
- stream_buf_close (&sock->stream_buf);
- free_buf (&sock->stream_buf_data);
- if (!gremlin)
- free (sock);
+ stream_buf_close(&sock->stream_buf);
+ free_buf(&sock->stream_buf_data);
+ if (!gremlin)
+ {
+ free(sock);
+ }
}
}
/* for stream protocols, allow for packet length prefix */
void
-socket_adjust_frame_parameters (struct frame *frame, int proto)
+socket_adjust_frame_parameters(struct frame *frame, int proto)
{
- if (link_socket_proto_connection_oriented (proto))
- frame_add_to_extra_frame (frame, sizeof (packet_size_type));
+ if (link_socket_proto_connection_oriented(proto))
+ {
+ frame_add_to_extra_frame(frame, sizeof(packet_size_type));
+ }
}
void
-setenv_trusted (struct env_set *es, const struct link_socket_info *info)
+setenv_trusted(struct env_set *es, const struct link_socket_info *info)
{
- setenv_link_socket_actual (es, "trusted", &info->lsa->actual, SA_IP_PORT);
+ setenv_link_socket_actual(es, "trusted", &info->lsa->actual, SA_IP_PORT);
}
static void
-ipchange_fmt (const bool include_cmd, struct argv *argv, const struct link_socket_info *info, struct gc_arena *gc)
+ipchange_fmt(const bool include_cmd, struct argv *argv, const struct link_socket_info *info, struct gc_arena *gc)
{
- const char *host = print_sockaddr_ex (&info->lsa->actual.dest.addr.sa, " ", PS_SHOW_PORT , gc);
- if (include_cmd)
+ const char *host = print_sockaddr_ex(&info->lsa->actual.dest.addr.sa, " ", PS_SHOW_PORT, gc);
+ if (include_cmd)
{
- argv_parse_cmd (argv, info->ipchange_command);
- argv_printf_cat (argv, "%s", host);
+ argv_parse_cmd(argv, info->ipchange_command);
+ argv_printf_cat(argv, "%s", host);
+ }
+ else
+ {
+ argv_printf(argv, "%s", host);
}
- else
- argv_printf (argv, "%s", host);
}
void
-link_socket_connection_initiated (const struct buffer *buf,
- struct link_socket_info *info,
- const struct link_socket_actual *act,
- const char *common_name,
- struct env_set *es)
+link_socket_connection_initiated(const struct buffer *buf,
+ struct link_socket_info *info,
+ const struct link_socket_actual *act,
+ const char *common_name,
+ struct env_set *es)
{
- struct gc_arena gc = gc_new ();
-
- info->lsa->actual = *act; /* Note: skip this line for --force-dest */
- setenv_trusted (es, info);
- info->connection_established = true;
+ struct gc_arena gc = gc_new();
+
+ info->lsa->actual = *act; /* Note: skip this line for --force-dest */
+ setenv_trusted(es, info);
+ info->connection_established = true;
- /* Print connection initiated message, with common name if available */
- {
- struct buffer out = alloc_buf_gc (256, &gc);
- if (common_name)
- buf_printf (&out, "[%s] ", common_name);
- buf_printf (&out, "Peer Connection Initiated with %s", print_link_socket_actual (&info->lsa->actual, &gc));
- msg (M_INFO, "%s", BSTR (&out));
- }
+ /* Print connection initiated message, with common name if available */
+ {
+ struct buffer out = alloc_buf_gc(256, &gc);
+ if (common_name)
+ {
+ buf_printf(&out, "[%s] ", common_name);
+ }
+ buf_printf(&out, "Peer Connection Initiated with %s", print_link_socket_actual(&info->lsa->actual, &gc));
+ msg(M_INFO, "%s", BSTR(&out));
+ }
- /* set environmental vars */
- setenv_str (es, "common_name", common_name);
+ /* set environmental vars */
+ setenv_str(es, "common_name", common_name);
- /* Process --ipchange plugin */
- if (plugin_defined (info->plugins, OPENVPN_PLUGIN_IPCHANGE))
+ /* Process --ipchange plugin */
+ if (plugin_defined(info->plugins, OPENVPN_PLUGIN_IPCHANGE))
{
- struct argv argv = argv_new ();
- ipchange_fmt (false, &argv, info, &gc);
- if (plugin_call (info->plugins, OPENVPN_PLUGIN_IPCHANGE, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
- msg (M_WARN, "WARNING: ipchange plugin call failed");
- argv_reset (&argv);
+ struct argv argv = argv_new();
+ ipchange_fmt(false, &argv, info, &gc);
+ if (plugin_call(info->plugins, OPENVPN_PLUGIN_IPCHANGE, &argv, NULL, es) != OPENVPN_PLUGIN_FUNC_SUCCESS)
+ {
+ msg(M_WARN, "WARNING: ipchange plugin call failed");
+ }
+ argv_reset(&argv);
}
- /* Process --ipchange option */
- if (info->ipchange_command)
+ /* Process --ipchange option */
+ if (info->ipchange_command)
{
- struct argv argv = argv_new ();
- setenv_str (es, "script_type", "ipchange");
- ipchange_fmt (true, &argv, info, &gc);
- openvpn_run_script (&argv, es, 0, "--ipchange");
- argv_reset (&argv);
+ struct argv argv = argv_new();
+ setenv_str(es, "script_type", "ipchange");
+ ipchange_fmt(true, &argv, info, &gc);
+ openvpn_run_script(&argv, es, 0, "--ipchange");
+ argv_reset(&argv);
}
- gc_free (&gc);
+ gc_free(&gc);
}
void
-link_socket_bad_incoming_addr (struct buffer *buf,
- const struct link_socket_info *info,
- const struct link_socket_actual *from_addr)
-{
- struct gc_arena gc = gc_new ();
- struct addrinfo* ai;
-
- switch(from_addr->dest.addr.sa.sa_family)
- {
- case AF_INET:
- case AF_INET6:
- msg (D_LINK_ERRORS,
- "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_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;
+link_socket_bad_incoming_addr(struct buffer *buf,
+ const struct link_socket_info *info,
+ const struct link_socket_actual *from_addr)
+{
+ struct gc_arena gc = gc_new();
+ struct addrinfo *ai;
+
+ switch (from_addr->dest.addr.sa.sa_family)
+ {
+ case AF_INET:
+ case AF_INET6:
+ msg(D_LINK_ERRORS,
+ "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_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;
- gc_free (&gc);
+ buf->len = 0;
+ gc_free(&gc);
}
void
-link_socket_bad_outgoing_addr (void)
+link_socket_bad_outgoing_addr(void)
{
- dmsg (D_READ_WRITE, "TCP/UDP: No outgoing address to send packet");
+ dmsg(D_READ_WRITE, "TCP/UDP: No outgoing address to send packet");
}
in_addr_t
-link_socket_current_remote (const struct link_socket_info *info)
+link_socket_current_remote(const struct link_socket_info *info)
{
- const struct link_socket_addr *lsa = info->lsa;
+ const struct link_socket_addr *lsa = info->lsa;
-/*
- * This logic supports "redirect-gateway" semantic, which
+/*
+ * This logic supports "redirect-gateway" semantic, which
* makes sense only for PF_INET routes over PF_INET endpoints
*
* Maybe in the future consider PF_INET6 endpoints also ...
@@ -2129,22 +2395,30 @@ link_socket_current_remote (const struct link_socket_info *info)
* 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 (lsa->current_remote)
- return ntohl (((struct sockaddr_in*)lsa->current_remote->ai_addr)
- ->sin_addr.s_addr);
- else
- return 0;
+ 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 (lsa->current_remote)
+ {
+ return ntohl(((struct sockaddr_in *)lsa->current_remote->ai_addr)
+ ->sin_addr.s_addr);
+ }
+ else
+ {
+ return 0;
+ }
}
const struct in6_addr *
-link_socket_current_remote_ipv6 (const struct link_socket_info *info)
+link_socket_current_remote_ipv6(const struct link_socket_info *info)
{
- const struct link_socket_addr *lsa = info->lsa;
+ const struct link_socket_addr *lsa = info->lsa;
/* This logic supports "redirect-gateway" semantic,
* for PF_INET6 routes over PF_INET6 endpoints
@@ -2152,50 +2426,58 @@ link_socket_current_remote_ipv6 (const struct link_socket_info *info)
* 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_INET6)
- return NULL;
+ if (lsa->actual.dest.addr.sa.sa_family != AF_INET6)
+ {
+ return NULL;
+ }
- if (link_socket_actual_defined (&lsa->actual))
- return &(lsa->actual.dest.addr.in6.sin6_addr);
- else if (lsa->current_remote)
- return &(((struct sockaddr_in6*)lsa->current_remote->ai_addr) ->sin6_addr);
- else
- return NULL;
+ if (link_socket_actual_defined(&lsa->actual))
+ {
+ return &(lsa->actual.dest.addr.in6.sin6_addr);
+ }
+ else if (lsa->current_remote)
+ {
+ return &(((struct sockaddr_in6 *)lsa->current_remote->ai_addr)->sin6_addr);
+ }
+ else
+ {
+ return NULL;
+ }
}
/*
* Return a status string describing socket state.
*/
const char *
-socket_stat (const struct link_socket *s, unsigned int rwflags, struct gc_arena *gc)
+socket_stat(const struct link_socket *s, unsigned int rwflags, struct gc_arena *gc)
{
- struct buffer out = alloc_buf_gc (64, gc);
- if (s)
+ struct buffer out = alloc_buf_gc(64, gc);
+ if (s)
{
- if (rwflags & EVENT_READ)
- {
- buf_printf (&out, "S%s",
- (s->rwflags_debug & EVENT_READ) ? "R" : "r");
+ if (rwflags & EVENT_READ)
+ {
+ buf_printf(&out, "S%s",
+ (s->rwflags_debug & EVENT_READ) ? "R" : "r");
#ifdef _WIN32
- buf_printf (&out, "%s",
- overlapped_io_state_ascii (&s->reads));
+ buf_printf(&out, "%s",
+ overlapped_io_state_ascii(&s->reads));
#endif
- }
- if (rwflags & EVENT_WRITE)
- {
- buf_printf (&out, "S%s",
- (s->rwflags_debug & EVENT_WRITE) ? "W" : "w");
+ }
+ if (rwflags & EVENT_WRITE)
+ {
+ buf_printf(&out, "S%s",
+ (s->rwflags_debug & EVENT_WRITE) ? "W" : "w");
#ifdef _WIN32
- buf_printf (&out, "%s",
- overlapped_io_state_ascii (&s->writes));
+ buf_printf(&out, "%s",
+ overlapped_io_state_ascii(&s->writes));
#endif
- }
+ }
}
- else
+ else
{
- buf_printf (&out, "S?");
+ buf_printf(&out, "S?");
}
- return BSTR (&out);
+ return BSTR(&out);
}
/*
@@ -2204,152 +2486,160 @@ socket_stat (const struct link_socket *s, unsigned int rwflags, struct gc_arena
*/
static inline void
-stream_buf_reset (struct stream_buf *sb)
+stream_buf_reset(struct stream_buf *sb)
{
- dmsg (D_STREAM_DEBUG, "STREAM: RESET");
- sb->residual_fully_formed = false;
- sb->buf = sb->buf_init;
- buf_reset (&sb->next);
- sb->len = -1;
+ dmsg(D_STREAM_DEBUG, "STREAM: RESET");
+ sb->residual_fully_formed = false;
+ sb->buf = sb->buf_init;
+ buf_reset(&sb->next);
+ sb->len = -1;
}
void
-stream_buf_init (struct stream_buf *sb,
- struct buffer *buf,
- const unsigned int sockflags,
- const int proto)
-{
- sb->buf_init = *buf;
- sb->maxlen = sb->buf_init.len;
- sb->buf_init.len = 0;
- sb->residual = alloc_buf (sb->maxlen);
- sb->error = false;
+stream_buf_init(struct stream_buf *sb,
+ struct buffer *buf,
+ const unsigned int sockflags,
+ const int proto)
+{
+ sb->buf_init = *buf;
+ sb->maxlen = sb->buf_init.len;
+ sb->buf_init.len = 0;
+ sb->residual = alloc_buf(sb->maxlen);
+ sb->error = false;
#if PORT_SHARE
- sb->port_share_state = ((sockflags & SF_PORT_SHARE) && (proto == PROTO_TCP_SERVER))
- ? PS_ENABLED
- : PS_DISABLED;
+ sb->port_share_state = ((sockflags & SF_PORT_SHARE) && (proto == PROTO_TCP_SERVER))
+ ? PS_ENABLED
+ : PS_DISABLED;
#endif
- stream_buf_reset (sb);
+ stream_buf_reset(sb);
- dmsg (D_STREAM_DEBUG, "STREAM: INIT maxlen=%d", sb->maxlen);
+ dmsg(D_STREAM_DEBUG, "STREAM: INIT maxlen=%d", sb->maxlen);
}
static inline void
-stream_buf_set_next (struct stream_buf *sb)
+stream_buf_set_next(struct stream_buf *sb)
{
- /* set up 'next' for next i/o read */
- sb->next = sb->buf;
- sb->next.offset = sb->buf.offset + sb->buf.len;
- sb->next.len = (sb->len >= 0 ? sb->len : sb->maxlen) - sb->buf.len;
- dmsg (D_STREAM_DEBUG, "STREAM: SET NEXT, buf=[%d,%d] next=[%d,%d] len=%d maxlen=%d",
- sb->buf.offset, sb->buf.len,
- sb->next.offset, sb->next.len,
- sb->len, sb->maxlen);
- ASSERT (sb->next.len > 0);
- ASSERT (buf_safe (&sb->buf, sb->next.len));
+ /* set up 'next' for next i/o read */
+ sb->next = sb->buf;
+ sb->next.offset = sb->buf.offset + sb->buf.len;
+ sb->next.len = (sb->len >= 0 ? sb->len : sb->maxlen) - sb->buf.len;
+ dmsg(D_STREAM_DEBUG, "STREAM: SET NEXT, buf=[%d,%d] next=[%d,%d] len=%d maxlen=%d",
+ sb->buf.offset, sb->buf.len,
+ sb->next.offset, sb->next.len,
+ sb->len, sb->maxlen);
+ ASSERT(sb->next.len > 0);
+ ASSERT(buf_safe(&sb->buf, sb->next.len));
}
static inline void
-stream_buf_get_final (struct stream_buf *sb, struct buffer *buf)
+stream_buf_get_final(struct stream_buf *sb, struct buffer *buf)
{
- dmsg (D_STREAM_DEBUG, "STREAM: GET FINAL len=%d",
- buf_defined (&sb->buf) ? sb->buf.len : -1);
- ASSERT (buf_defined (&sb->buf));
- *buf = sb->buf;
+ dmsg(D_STREAM_DEBUG, "STREAM: GET FINAL len=%d",
+ buf_defined(&sb->buf) ? sb->buf.len : -1);
+ ASSERT(buf_defined(&sb->buf));
+ *buf = sb->buf;
}
static inline void
-stream_buf_get_next (struct stream_buf *sb, struct buffer *buf)
+stream_buf_get_next(struct stream_buf *sb, struct buffer *buf)
{
- dmsg (D_STREAM_DEBUG, "STREAM: GET NEXT len=%d",
- buf_defined (&sb->next) ? sb->next.len : -1);
- ASSERT (buf_defined (&sb->next));
- *buf = sb->next;
+ dmsg(D_STREAM_DEBUG, "STREAM: GET NEXT len=%d",
+ buf_defined(&sb->next) ? sb->next.len : -1);
+ ASSERT(buf_defined(&sb->next));
+ *buf = sb->next;
}
bool
-stream_buf_read_setup_dowork (struct link_socket* sock)
+stream_buf_read_setup_dowork(struct link_socket *sock)
{
- if (sock->stream_buf.residual.len && !sock->stream_buf.residual_fully_formed)
+ if (sock->stream_buf.residual.len && !sock->stream_buf.residual_fully_formed)
{
- ASSERT (buf_copy (&sock->stream_buf.buf, &sock->stream_buf.residual));
- ASSERT (buf_init (&sock->stream_buf.residual, 0));
- sock->stream_buf.residual_fully_formed = stream_buf_added (&sock->stream_buf, 0);
- dmsg (D_STREAM_DEBUG, "STREAM: RESIDUAL FULLY FORMED [%s], len=%d",
- sock->stream_buf.residual_fully_formed ? "YES" : "NO",
- sock->stream_buf.residual.len);
+ ASSERT(buf_copy(&sock->stream_buf.buf, &sock->stream_buf.residual));
+ ASSERT(buf_init(&sock->stream_buf.residual, 0));
+ sock->stream_buf.residual_fully_formed = stream_buf_added(&sock->stream_buf, 0);
+ dmsg(D_STREAM_DEBUG, "STREAM: RESIDUAL FULLY FORMED [%s], len=%d",
+ sock->stream_buf.residual_fully_formed ? "YES" : "NO",
+ sock->stream_buf.residual.len);
}
- if (!sock->stream_buf.residual_fully_formed)
- stream_buf_set_next (&sock->stream_buf);
- return !sock->stream_buf.residual_fully_formed;
+ if (!sock->stream_buf.residual_fully_formed)
+ {
+ stream_buf_set_next(&sock->stream_buf);
+ }
+ return !sock->stream_buf.residual_fully_formed;
}
bool
-stream_buf_added (struct stream_buf *sb,
- int length_added)
+stream_buf_added(struct stream_buf *sb,
+ int length_added)
{
- dmsg (D_STREAM_DEBUG, "STREAM: ADD length_added=%d", length_added);
- if (length_added > 0)
- sb->buf.len += length_added;
+ dmsg(D_STREAM_DEBUG, "STREAM: ADD length_added=%d", length_added);
+ if (length_added > 0)
+ {
+ sb->buf.len += length_added;
+ }
- /* if length unknown, see if we can get the length prefix from
- the head of the buffer */
- if (sb->len < 0 && sb->buf.len >= (int) sizeof (packet_size_type))
+ /* if length unknown, see if we can get the length prefix from
+ * the head of the buffer */
+ if (sb->len < 0 && sb->buf.len >= (int) sizeof(packet_size_type))
{
- packet_size_type net_size;
+ packet_size_type net_size;
#if PORT_SHARE
- if (sb->port_share_state == PS_ENABLED)
- {
- if (!is_openvpn_protocol (&sb->buf))
- {
- msg (D_STREAM_ERRORS, "Non-OpenVPN client protocol detected");
- sb->port_share_state = PS_FOREIGN;
- sb->error = true;
- return false;
- }
- else
- sb->port_share_state = PS_DISABLED;
- }
+ if (sb->port_share_state == PS_ENABLED)
+ {
+ if (!is_openvpn_protocol(&sb->buf))
+ {
+ msg(D_STREAM_ERRORS, "Non-OpenVPN client protocol detected");
+ sb->port_share_state = PS_FOREIGN;
+ sb->error = true;
+ return false;
+ }
+ else
+ {
+ sb->port_share_state = PS_DISABLED;
+ }
+ }
#endif
- ASSERT (buf_read (&sb->buf, &net_size, sizeof (net_size)));
- sb->len = ntohps (net_size);
+ ASSERT(buf_read(&sb->buf, &net_size, sizeof(net_size)));
+ sb->len = ntohps(net_size);
- if (sb->len < 1 || sb->len > sb->maxlen)
- {
- msg (M_WARN, "WARNING: Bad encapsulated packet length from peer (%d), which must be > 0 and <= %d -- please ensure that --tun-mtu or --link-mtu is equal on both peers -- this condition could also indicate a possible active attack on the TCP link -- [Attempting restart...]", sb->len, sb->maxlen);
- stream_buf_reset (sb);
- sb->error = true;
- return false;
- }
+ if (sb->len < 1 || sb->len > sb->maxlen)
+ {
+ msg(M_WARN, "WARNING: Bad encapsulated packet length from peer (%d), which must be > 0 and <= %d -- please ensure that --tun-mtu or --link-mtu is equal on both peers -- this condition could also indicate a possible active attack on the TCP link -- [Attempting restart...]", sb->len, sb->maxlen);
+ stream_buf_reset(sb);
+ sb->error = true;
+ return false;
+ }
}
- /* is our incoming packet fully read? */
- if (sb->len > 0 && sb->buf.len >= sb->len)
+ /* is our incoming packet fully read? */
+ if (sb->len > 0 && sb->buf.len >= sb->len)
{
- /* save any residual data that's part of the next packet */
- ASSERT (buf_init (&sb->residual, 0));
- if (sb->buf.len > sb->len)
- ASSERT (buf_copy_excess (&sb->residual, &sb->buf, sb->len));
- dmsg (D_STREAM_DEBUG, "STREAM: ADD returned TRUE, buf_len=%d, residual_len=%d",
- BLEN (&sb->buf),
- BLEN (&sb->residual));
- return true;
+ /* save any residual data that's part of the next packet */
+ ASSERT(buf_init(&sb->residual, 0));
+ if (sb->buf.len > sb->len)
+ {
+ ASSERT(buf_copy_excess(&sb->residual, &sb->buf, sb->len));
+ }
+ dmsg(D_STREAM_DEBUG, "STREAM: ADD returned TRUE, buf_len=%d, residual_len=%d",
+ BLEN(&sb->buf),
+ BLEN(&sb->residual));
+ return true;
}
- else
+ else
{
- dmsg (D_STREAM_DEBUG, "STREAM: ADD returned FALSE (have=%d need=%d)", sb->buf.len, sb->len);
- stream_buf_set_next (sb);
- return false;
+ dmsg(D_STREAM_DEBUG, "STREAM: ADD returned FALSE (have=%d need=%d)", sb->buf.len, sb->len);
+ stream_buf_set_next(sb);
+ return false;
}
}
void
-stream_buf_close (struct stream_buf* sb)
+stream_buf_close(struct stream_buf *sb)
{
- free_buf (&sb->residual);
+ free_buf(&sb->residual);
}
/*
@@ -2358,14 +2648,16 @@ stream_buf_close (struct stream_buf* sb)
* TCP socket, for use in server mode.
*/
event_t
-socket_listen_event_handle (struct link_socket *s)
+socket_listen_event_handle(struct link_socket *s)
{
#ifdef _WIN32
- if (!defined_net_event_win32 (&s->listen_handle))
- init_net_event_win32 (&s->listen_handle, FD_ACCEPT, s->sd, 0);
- return &s->listen_handle;
-#else
- return s->sd;
+ if (!defined_net_event_win32(&s->listen_handle))
+ {
+ init_net_event_win32(&s->listen_handle, FD_ACCEPT, s->sd, 0);
+ }
+ return &s->listen_handle;
+#else /* ifdef _WIN32 */
+ return s->sd;
#endif
}
@@ -2374,72 +2666,90 @@ socket_listen_event_handle (struct link_socket *s)
*/
const char *
-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 = false;
- char hostaddr[NI_MAXHOST] = "";
- char servname[NI_MAXSERV] = "";
- int status;
+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 = false;
+ char hostaddr[NI_MAXHOST] = "";
+ char servname[NI_MAXSERV] = "";
+ int status;
+
+ socklen_t salen = 0;
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ if (!(flags & PS_DONT_SHOW_FAMILY))
+ {
+ buf_puts(&out, "[AF_INET]");
+ }
+ salen = sizeof(struct sockaddr_in);
+ addr_is_defined = ((struct sockaddr_in *) sa)->sin_addr.s_addr != 0;
+ break;
- socklen_t salen = 0;
- switch(sa->sa_family)
- {
- case AF_INET:
- if (!(flags & PS_DONT_SHOW_FAMILY))
- 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:
- if (!(flags & PS_DONT_SHOW_FAMILY))
- buf_puts (&out, "[AF_INET6]");
- salen = sizeof (struct sockaddr_in6);
- addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6*) sa)->sin6_addr);
- break;
- case AF_UNSPEC:
- if (!(flags & PS_DONT_SHOW_FAMILY))
- return "[AF_UNSPEC]";
- else
- return "";
- default:
- ASSERT(0);
+ case AF_INET6:
+ if (!(flags & PS_DONT_SHOW_FAMILY))
+ {
+ buf_puts(&out, "[AF_INET6]");
+ }
+ salen = sizeof(struct sockaddr_in6);
+ addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) sa)->sin6_addr);
+ break;
+
+ case AF_UNSPEC:
+ if (!(flags & PS_DONT_SHOW_FAMILY))
+ {
+ return "[AF_UNSPEC]";
+ }
+ else
+ {
+ return "";
+ }
+
+ default:
+ ASSERT(0);
}
- status = getnameinfo(sa, salen, hostaddr, sizeof (hostaddr),
- servname, sizeof(servname), NI_NUMERICHOST | NI_NUMERICSERV);
+ 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 (status!=0)
+ {
+ buf_printf(&out,"[nameinfo() err: %s]",gai_strerror(status));
+ return BSTR(&out);
+ }
- if (!(flags & PS_DONT_SHOW_ADDR))
+ if (!(flags & PS_DONT_SHOW_ADDR))
{
- if (addr_is_defined)
- buf_puts (&out, hostaddr);
- else
- buf_puts (&out, "[undef]");
+ 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 ((flags & PS_SHOW_PORT) || (flags & PS_SHOW_PORT_IF_DEFINED))
{
- if (separator)
- buf_puts (&out, separator);
+ if (separator)
+ {
+ buf_puts(&out, separator);
+ }
- buf_puts (&out, servname);
+ buf_puts(&out, servname);
}
- return BSTR (&out);
+ return BSTR(&out);
}
const char *
-print_link_socket_actual (const struct link_socket_actual *act, struct gc_arena *gc)
+print_link_socket_actual(const struct link_socket_actual *act, struct gc_arena *gc)
{
- return print_link_socket_actual_ex (act, ":", PS_SHOW_PORT|PS_SHOW_PKTINFO, gc);
+ return print_link_socket_actual_ex(act, ":", PS_SHOW_PORT|PS_SHOW_PKTINFO, gc);
}
#ifndef IF_NAMESIZE
@@ -2447,62 +2757,69 @@ print_link_socket_actual (const struct link_socket_actual *act, struct gc_arena
#endif
const char *
-print_link_socket_actual_ex (const struct link_socket_actual *act,
- const char *separator,
- const unsigned int flags,
- struct gc_arena *gc)
+print_link_socket_actual_ex(const struct link_socket_actual *act,
+ const char *separator,
+ const unsigned int flags,
+ struct gc_arena *gc)
{
- if (act)
+ if (act)
{
- char ifname[IF_NAMESIZE] = "[undef]";
- struct buffer out = alloc_buf_gc (128, gc);
- buf_printf (&out, "%s", print_sockaddr_ex (&act->dest.addr.sa, separator, flags, gc));
+ char ifname[IF_NAMESIZE] = "[undef]";
+ struct buffer out = alloc_buf_gc(128, 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))
- {
- switch(act->dest.addr.sa.sa_family)
- {
- case AF_INET:
- {
- struct openvpn_sockaddr sa;
- CLEAR (sa);
- sa.addr.in4.sin_family = AF_INET;
+ if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act))
+ {
+ switch (act->dest.addr.sa.sa_family)
+ {
+ case AF_INET:
+ {
+ struct openvpn_sockaddr sa;
+ CLEAR(sa);
+ sa.addr.in4.sin_family = AF_INET;
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
- sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst;
- if_indextoname(act->pi.in4.ipi_ifindex, ifname);
+ sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst;
+ if_indextoname(act->pi.in4.ipi_ifindex, ifname);
#elif defined(IP_RECVDSTADDR)
- sa.addr.in4.sin_addr = act->pi.in4;
- ifname[0]=0;
-#else
+ sa.addr.in4.sin_addr = act->pi.in4;
+ ifname[0] = 0;
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
#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.addr.sa, separator, 0, gc),
- ifname);
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 sin6;
- char buf[INET6_ADDRSTRLEN] = "[undef]";
- CLEAR(sin6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = act->pi.in6.ipi6_addr;
- if_indextoname(act->pi.in6.ipi6_ifindex, ifname);
- if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct sockaddr_in6),
- buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) == 0)
- buf_printf (&out, " (via %s%%%s)", buf, ifname);
- else
- buf_printf (&out, " (via [getnameinfo() err]%%%s)", ifname);
- }
- break;
- }
- }
-#endif
- return BSTR (&out);
+ buf_printf(&out, " (via %s%%%s)",
+ print_sockaddr_ex(&sa.addr.sa, separator, 0, gc),
+ ifname);
+ }
+ break;
+
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6;
+ char buf[INET6_ADDRSTRLEN] = "[undef]";
+ CLEAR(sin6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = act->pi.in6.ipi6_addr;
+ if_indextoname(act->pi.in6.ipi6_ifindex, ifname);
+ if (getnameinfo((struct sockaddr *)&sin6, sizeof(struct sockaddr_in6),
+ buf, sizeof(buf), NULL, 0, NI_NUMERICHOST) == 0)
+ {
+ buf_printf(&out, " (via %s%%%s)", buf, ifname);
+ }
+ else
+ {
+ buf_printf(&out, " (via [getnameinfo() err]%%%s)", ifname);
+ }
+ }
+ break;
+ }
+ }
+#endif /* if ENABLE_IP_PKTINFO */
+ return BSTR(&out);
+ }
+ else
+ {
+ return "[NULL]";
}
- else
- return "[NULL]";
}
/*
@@ -2510,19 +2827,19 @@ print_link_socket_actual_ex (const struct link_socket_actual *act,
* to an ascii dotted quad.
*/
const char *
-print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc)
+print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
{
- struct in_addr ia;
- struct buffer out = alloc_buf_gc (64, gc);
+ struct in_addr ia;
+ struct buffer out = alloc_buf_gc(64, gc);
- if (addr || !(flags & IA_EMPTY_IF_UNDEF))
+ if (addr || !(flags & IA_EMPTY_IF_UNDEF))
{
- CLEAR (ia);
- ia.s_addr = (flags & IA_NET_ORDER) ? addr : htonl (addr);
+ CLEAR(ia);
+ ia.s_addr = (flags & IA_NET_ORDER) ? addr : htonl(addr);
- buf_printf (&out, "%s", inet_ntoa (ia));
+ buf_printf(&out, "%s", inet_ntoa(ia));
}
- return BSTR (&out);
+ return BSTR(&out);
}
/*
@@ -2530,133 +2847,139 @@ print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc)
* to an ascii representation of an IPv6 address
*/
const char *
-print_in6_addr (struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
+print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
{
- struct buffer out = alloc_buf_gc (64, gc);
- char tmp_out_buf[64]; /* inet_ntop wants pointer to buffer */
+ struct buffer out = alloc_buf_gc(64, gc);
+ char tmp_out_buf[64]; /* inet_ntop wants pointer to buffer */
- if ( memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 ||
- !(flags & IA_EMPTY_IF_UNDEF))
+ if (memcmp(&a6, &in6addr_any, sizeof(a6)) != 0
+ || !(flags & IA_EMPTY_IF_UNDEF))
{
- inet_ntop (AF_INET6, &a6, tmp_out_buf, sizeof(tmp_out_buf)-1);
- buf_printf (&out, "%s", tmp_out_buf );
+ inet_ntop(AF_INET6, &a6, tmp_out_buf, sizeof(tmp_out_buf)-1);
+ buf_printf(&out, "%s", tmp_out_buf );
}
- return BSTR (&out);
+ return BSTR(&out);
}
#ifndef UINT8_MAX
-# define UINT8_MAX 0xff
+#define UINT8_MAX 0xff
#endif
/* add some offset to an ipv6 address
* (add in steps of 8 bits, taking overflow into next round)
*/
-struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add )
+struct in6_addr
+add_in6_addr( struct in6_addr base, uint32_t add )
{
int i;
- for( i=15; i>=0 && add > 0 ; i-- )
+ for (i = 15; i>=0 && add > 0; i--)
{
- register int carry;
- register uint32_t h;
+ register int carry;
+ register uint32_t h;
- h = (unsigned char) base.s6_addr[i];
- base.s6_addr[i] = (h+add) & UINT8_MAX;
+ h = (unsigned char) base.s6_addr[i];
+ base.s6_addr[i] = (h+add) & UINT8_MAX;
- /* using explicit carry for the 8-bit additions will catch
+ /* using explicit carry for the 8-bit additions will catch
* 8-bit and(!) 32-bit overruns nicely
*/
- carry = ((h & 0xff) + (add & 0xff)) >> 8;
- add = (add>>8) + carry;
+ carry = ((h & 0xff) + (add & 0xff)) >> 8;
+ add = (add>>8) + carry;
}
return base;
}
/* set environmental variables for ip/port in *addr */
void
-setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const unsigned int flags)
-{
- char name_buf[256];
-
- char buf[128];
- switch(addr->addr.sa.sa_family)
- {
- case AF_INET:
- if (flags & SA_IP_PORT)
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix);
- else
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s", name_prefix);
-
- setenv_str (es, name_buf, inet_ntoa (addr->addr.in4.sin_addr));
-
- if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port)
- {
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_port", name_prefix);
- setenv_int (es, name_buf, ntohs (addr->addr.in4.sin_port));
- }
- break;
- case AF_INET6:
- if ( IN6_IS_ADDR_V4MAPPED( &addr->addr.in6.sin6_addr ))
- {
- struct in_addr ia;
- memcpy (&ia.s_addr, &addr->addr.in6.sin6_addr.s6_addr[12],
- sizeof (ia.s_addr));
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix);
- openvpn_snprintf (buf, sizeof(buf), "%s", inet_ntoa(ia) );
- }
- else
- {
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip6", name_prefix);
- getnameinfo(&addr->addr.sa, sizeof (struct sockaddr_in6),
- buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
- }
- setenv_str (es, name_buf, buf);
-
- if ((flags & SA_IP_PORT) && addr->addr.in6.sin6_port)
- {
- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_port", name_prefix);
- setenv_int (es, name_buf, ntohs (addr->addr.in6.sin6_port));
- }
- break;
+setenv_sockaddr(struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const unsigned int flags)
+{
+ char name_buf[256];
+
+ char buf[128];
+ switch (addr->addr.sa.sa_family)
+ {
+ case AF_INET:
+ if (flags & SA_IP_PORT)
+ {
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix);
+ }
+ else
+ {
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s", name_prefix);
+ }
+
+ setenv_str(es, name_buf, inet_ntoa(addr->addr.in4.sin_addr));
+
+ if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port)
+ {
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix);
+ setenv_int(es, name_buf, ntohs(addr->addr.in4.sin_port));
+ }
+ break;
+
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED( &addr->addr.in6.sin6_addr ))
+ {
+ struct in_addr ia;
+ memcpy(&ia.s_addr, &addr->addr.in6.sin6_addr.s6_addr[12],
+ sizeof(ia.s_addr));
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s_ip", name_prefix);
+ openvpn_snprintf(buf, sizeof(buf), "%s", inet_ntoa(ia) );
+ }
+ else
+ {
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s_ip6", name_prefix);
+ getnameinfo(&addr->addr.sa, sizeof(struct sockaddr_in6),
+ buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
+ }
+ setenv_str(es, name_buf, buf);
+
+ if ((flags & SA_IP_PORT) && addr->addr.in6.sin6_port)
+ {
+ openvpn_snprintf(name_buf, sizeof(name_buf), "%s_port", name_prefix);
+ setenv_int(es, name_buf, ntohs(addr->addr.in6.sin6_port));
+ }
+ break;
}
}
void
-setenv_in_addr_t (struct env_set *es, const char *name_prefix, in_addr_t addr, const unsigned int flags)
+setenv_in_addr_t(struct env_set *es, const char *name_prefix, in_addr_t addr, const unsigned int flags)
{
- if (addr || !(flags & SA_SET_IF_NONZERO))
+ if (addr || !(flags & SA_SET_IF_NONZERO))
{
- struct openvpn_sockaddr si;
- CLEAR (si);
- si.addr.in4.sin_family = AF_INET;
- si.addr.in4.sin_addr.s_addr = htonl (addr);
- setenv_sockaddr (es, name_prefix, &si, flags);
+ struct openvpn_sockaddr si;
+ CLEAR(si);
+ si.addr.in4.sin_family = AF_INET;
+ si.addr.in4.sin_addr.s_addr = htonl(addr);
+ setenv_sockaddr(es, name_prefix, &si, flags);
}
}
void
-setenv_in6_addr (struct env_set *es,
- const char *name_prefix,
- const struct in6_addr *addr,
- const unsigned int flags)
+setenv_in6_addr(struct env_set *es,
+ const char *name_prefix,
+ const struct in6_addr *addr,
+ const unsigned int flags)
{
- if (!IN6_IS_ADDR_UNSPECIFIED (addr) || !(flags & SA_SET_IF_NONZERO))
+ if (!IN6_IS_ADDR_UNSPECIFIED(addr) || !(flags & SA_SET_IF_NONZERO))
{
- struct openvpn_sockaddr si;
- CLEAR (si);
- si.addr.in6.sin6_family = AF_INET6;
- si.addr.in6.sin6_addr = *addr;
- setenv_sockaddr (es, name_prefix, &si, flags);
+ struct openvpn_sockaddr si;
+ CLEAR(si);
+ si.addr.in6.sin6_family = AF_INET6;
+ si.addr.in6.sin6_addr = *addr;
+ setenv_sockaddr(es, name_prefix, &si, flags);
}
}
void
-setenv_link_socket_actual (struct env_set *es,
- const char *name_prefix,
- const struct link_socket_actual *act,
- const unsigned int flags)
+setenv_link_socket_actual(struct env_set *es,
+ const char *name_prefix,
+ const struct link_socket_actual *act,
+ const unsigned int flags)
{
- setenv_sockaddr (es, name_prefix, &act->dest, flags);
+ setenv_sockaddr(es, name_prefix, &act->dest, flags);
}
/*
@@ -2664,37 +2987,39 @@ setenv_link_socket_actual (struct env_set *es,
*/
struct proto_names {
- const char *short_form;
- const char *display_form;
- sa_family_t proto_af;
- int proto;
+ const char *short_form;
+ const char *display_form;
+ sa_family_t proto_af;
+ int proto;
};
/* Indexed by PROTO_x */
static const struct proto_names proto_names[] = {
- {"proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE},
- /* try IPv4 and IPv6 (client), bind dual-stack (server) */
- {"udp", "UDP", AF_UNSPEC, PROTO_UDP},
- {"tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER},
- {"tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT},
- {"tcp", "TCP", AF_UNSPEC, PROTO_TCP},
- /* force IPv4 */
- {"udp4", "UDPv4", AF_INET, PROTO_UDP},
- {"tcp4-server","TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER},
- {"tcp4-client","TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT},
- {"tcp4", "TCPv4", AF_INET, PROTO_TCP},
- /* force IPv6 */
- {"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},
+ {"proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE},
+ /* try IPv4 and IPv6 (client), bind dual-stack (server) */
+ {"udp", "UDP", AF_UNSPEC, PROTO_UDP},
+ {"tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER},
+ {"tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT},
+ {"tcp", "TCP", AF_UNSPEC, PROTO_TCP},
+ /* force IPv4 */
+ {"udp4", "UDPv4", AF_INET, PROTO_UDP},
+ {"tcp4-server","TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER},
+ {"tcp4-client","TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT},
+ {"tcp4", "TCPv4", AF_INET, PROTO_TCP},
+ /* force IPv6 */
+ {"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
proto_is_net(int proto)
{
- if (proto < 0 || proto >= PROTO_N)
- ASSERT(0);
+ if (proto < 0 || proto >= PROTO_N)
+ {
+ ASSERT(0);
+ }
return proto != PROTO_NONE;
}
bool
@@ -2706,81 +3031,96 @@ proto_is_dgram(int proto)
bool
proto_is_udp(int proto)
{
- if (proto < 0 || proto >= PROTO_N)
- ASSERT(0);
- return proto == PROTO_UDP;
+ if (proto < 0 || proto >= PROTO_N)
+ {
+ ASSERT(0);
+ }
+ return proto == PROTO_UDP;
}
bool
proto_is_tcp(int proto)
{
- if (proto < 0 || proto >= PROTO_N)
- ASSERT(0);
- return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER;
+ if (proto < 0 || proto >= PROTO_N)
+ {
+ ASSERT(0);
+ }
+ return proto == PROTO_TCP_CLIENT || proto == PROTO_TCP_SERVER;
}
int
-ascii2proto (const char* proto_name)
+ascii2proto(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;
- return -1;
+ int i;
+ for (i = 0; i < SIZE(proto_names); ++i)
+ if (!strcmp(proto_name, proto_names[i].short_form))
+ {
+ return proto_names[i].proto;
+ }
+ return -1;
}
sa_family_t
-ascii2af (const char* proto_name)
+ascii2af(const char *proto_name)
{
int i;
- for (i = 0; i < SIZE (proto_names); ++i)
- if (!strcmp (proto_name, proto_names[i].short_form))
+ 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, sa_family_t af, bool display_form)
+proto2ascii(int proto, sa_family_t af, bool display_form)
{
- unsigned int i;
- for (i = 0; i < SIZE (proto_names); ++i)
+ unsigned int i;
+ for (i = 0; i < SIZE(proto_names); ++i)
{
- if(proto_names[i].proto_af == af && proto_names[i].proto == proto)
+ 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;
+ if (display_form)
+ {
+ return proto_names[i].display_form;
+ }
+ else
+ {
+ return proto_names[i].short_form;
+ }
}
}
- return "[unknown protocol]";
+ return "[unknown protocol]";
}
const char *
-proto2ascii_all (struct gc_arena *gc)
+proto2ascii_all(struct gc_arena *gc)
{
- struct buffer out = alloc_buf_gc (256, gc);
- int i;
+ struct buffer out = alloc_buf_gc(256, gc);
+ int i;
- for (i = 0; i < SIZE (proto_names); ++i)
+ for (i = 0; i < SIZE(proto_names); ++i)
{
- if (i)
- buf_printf(&out, " ");
- buf_printf(&out, "[%s]", proto_names[i].short_form);
+ if (i)
+ {
+ buf_printf(&out, " ");
+ }
+ buf_printf(&out, "[%s]", proto_names[i].short_form);
}
- return BSTR (&out);
+ return BSTR(&out);
}
const char *
-addr_family_name (int af)
+addr_family_name(int af)
{
- switch (af)
+ switch (af)
{
- case AF_INET: return "AF_INET";
- case AF_INET6: return "AF_INET6";
+ case AF_INET: return "AF_INET";
+
+ case AF_INET6: return "AF_INET6";
}
- return "AF_UNSPEC";
+ return "AF_UNSPEC";
}
/*
@@ -2795,22 +3135,28 @@ addr_family_name (int af)
* has always sent UDPv4, TCPv4 over the wire. Keep these
* strings for backward compatbility
*/
-const char*
-proto_remote (int proto, bool remote)
+const char *
+proto_remote(int proto, bool remote)
{
- ASSERT (proto >= 0 && proto < PROTO_N);
- if (proto == PROTO_UDP)
- return "UDPv4";
+ ASSERT(proto >= 0 && proto < PROTO_N);
+ if (proto == PROTO_UDP)
+ {
+ return "UDPv4";
+ }
- if ( (remote && proto == PROTO_TCP_CLIENT) ||
- (!remote && proto == PROTO_TCP_SERVER))
- return "TCPv4_SERVER";
- if ( (remote && proto == PROTO_TCP_SERVER) ||
- (!remote && proto == PROTO_TCP_CLIENT))
- return "TCPv4_CLIENT";
+ if ( (remote && proto == PROTO_TCP_CLIENT)
+ || (!remote && proto == PROTO_TCP_SERVER))
+ {
+ return "TCPv4_SERVER";
+ }
+ if ( (remote && proto == PROTO_TCP_SERVER)
+ || (!remote && proto == PROTO_TCP_CLIENT))
+ {
+ return "TCPv4_CLIENT";
+ }
- ASSERT (0);
- return ""; /* Make the compiler happy */
+ ASSERT(0);
+ return ""; /* Make the compiler happy */
}
/*
@@ -2818,11 +3164,11 @@ proto_remote (int proto, bool remote)
* we expect are considered to be fatal errors.
*/
void
-bad_address_length (int actual, int expected)
+bad_address_length(int actual, int expected)
{
- msg (M_FATAL, "ERROR: received strange incoming packet with an address length of %d -- we only accept address lengths of %d.",
- actual,
- expected);
+ msg(M_FATAL, "ERROR: received strange incoming packet with an address length of %d -- we only accept address lengths of %d.",
+ actual,
+ expected);
}
/*
@@ -2830,36 +3176,42 @@ bad_address_length (int actual, int expected)
*/
int
-link_socket_read_tcp (struct link_socket *sock,
- struct buffer *buf)
+link_socket_read_tcp(struct link_socket *sock,
+ struct buffer *buf)
{
- int len = 0;
+ int len = 0;
- if (!sock->stream_buf.residual_fully_formed)
+ if (!sock->stream_buf.residual_fully_formed)
{
#ifdef _WIN32
- len = socket_finalize (sock->sd, &sock->reads, buf, NULL);
+ len = socket_finalize(sock->sd, &sock->reads, buf, NULL);
#else
- struct buffer frag;
- stream_buf_get_next (&sock->stream_buf, &frag);
- len = recv (sock->sd, BPTR (&frag), BLEN (&frag), MSG_NOSIGNAL);
+ struct buffer frag;
+ stream_buf_get_next(&sock->stream_buf, &frag);
+ len = recv(sock->sd, BPTR(&frag), BLEN(&frag), MSG_NOSIGNAL);
#endif
- if (!len)
- sock->stream_reset = true;
- if (len <= 0)
- return buf->len = len;
+ if (!len)
+ {
+ sock->stream_reset = true;
+ }
+ if (len <= 0)
+ {
+ return buf->len = len;
+ }
}
- if (sock->stream_buf.residual_fully_formed
- || stream_buf_added (&sock->stream_buf, len)) /* packet complete? */
+ if (sock->stream_buf.residual_fully_formed
+ || stream_buf_added(&sock->stream_buf, len)) /* packet complete? */
+ {
+ stream_buf_get_final(&sock->stream_buf, buf);
+ stream_buf_reset(&sock->stream_buf);
+ return buf->len;
+ }
+ else
{
- stream_buf_get_final (&sock->stream_buf, buf);
- stream_buf_reset (&sock->stream_buf);
- return buf->len;
+ return buf->len = 0; /* no error, but packet is still incomplete */
}
- else
- return buf->len = 0; /* no error, but packet is still incomplete */
}
#ifndef _WIN32
@@ -2870,202 +3222,208 @@ link_socket_read_tcp (struct link_socket *sock,
* both IPv4 and IPv6 destination addresses, plus padding (see RFC 2292)
*/
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
-#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof (struct in6_pktinfo)), \
- CMSG_SPACE(sizeof (struct in_pktinfo)) )
+#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof(struct in6_pktinfo)), \
+ CMSG_SPACE(sizeof(struct in_pktinfo)) )
#else
-#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof (struct in6_pktinfo)), \
- CMSG_SPACE(sizeof (struct in_addr)) )
+#define PKTINFO_BUF_SIZE max_int( CMSG_SPACE(sizeof(struct in6_pktinfo)), \
+ CMSG_SPACE(sizeof(struct in_addr)) )
#endif
static socklen_t
-link_socket_read_udp_posix_recvmsg (struct link_socket *sock,
- struct buffer *buf,
- struct link_socket_actual *from)
-{
- struct iovec iov;
- uint8_t pktinfo_buf[PKTINFO_BUF_SIZE];
- struct msghdr mesg;
- socklen_t fromlen = sizeof (from->dest.addr);
-
- iov.iov_base = BPTR (buf);
- iov.iov_len = buf_forward_capacity_total (buf);
- mesg.msg_iov = &iov;
- mesg.msg_iovlen = 1;
- mesg.msg_name = &from->dest.addr;
- mesg.msg_namelen = fromlen;
- mesg.msg_control = pktinfo_buf;
- mesg.msg_controllen = sizeof pktinfo_buf;
- buf->len = recvmsg (sock->sd, &mesg, 0);
- if (buf->len >= 0)
- {
- struct cmsghdr *cmsg;
- fromlen = mesg.msg_namelen;
- cmsg = CMSG_FIRSTHDR (&mesg);
- if (cmsg != NULL
- && CMSG_NXTHDR (&mesg, cmsg) == NULL
+link_socket_read_udp_posix_recvmsg(struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *from)
+{
+ struct iovec iov;
+ uint8_t pktinfo_buf[PKTINFO_BUF_SIZE];
+ struct msghdr mesg;
+ socklen_t fromlen = sizeof(from->dest.addr);
+
+ iov.iov_base = BPTR(buf);
+ iov.iov_len = buf_forward_capacity_total(buf);
+ mesg.msg_iov = &iov;
+ mesg.msg_iovlen = 1;
+ mesg.msg_name = &from->dest.addr;
+ mesg.msg_namelen = fromlen;
+ mesg.msg_control = pktinfo_buf;
+ mesg.msg_controllen = sizeof pktinfo_buf;
+ buf->len = recvmsg(sock->sd, &mesg, 0);
+ if (buf->len >= 0)
+ {
+ struct cmsghdr *cmsg;
+ fromlen = mesg.msg_namelen;
+ cmsg = CMSG_FIRSTHDR(&mesg);
+ if (cmsg != NULL
+ && CMSG_NXTHDR(&mesg, cmsg) == NULL
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
- && cmsg->cmsg_level == SOL_IP
- && cmsg->cmsg_type == IP_PKTINFO
- && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_pktinfo)) )
+ && cmsg->cmsg_level == SOL_IP
+ && cmsg->cmsg_type == IP_PKTINFO
+ && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_pktinfo)) )
#elif defined(IP_RECVDSTADDR)
- && cmsg->cmsg_level == IPPROTO_IP
- && cmsg->cmsg_type == IP_RECVDSTADDR
- && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_addr)) )
-#else
+ && cmsg->cmsg_level == IPPROTO_IP
+ && cmsg->cmsg_type == IP_RECVDSTADDR
+ && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_addr)) )
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
- {
+ {
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
- struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
- from->pi.in4.ipi_ifindex = pkti->ipi_ifindex;
- from->pi.in4.ipi_spec_dst = pkti->ipi_spec_dst;
+ struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA(cmsg);
+ from->pi.in4.ipi_ifindex = pkti->ipi_ifindex;
+ from->pi.in4.ipi_spec_dst = pkti->ipi_spec_dst;
#elif defined(IP_RECVDSTADDR)
- from->pi.in4 = *(struct in_addr*) CMSG_DATA (cmsg);
-#else
+ from->pi.in4 = *(struct in_addr *) CMSG_DATA(cmsg);
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
- }
- else if (cmsg != NULL
- && CMSG_NXTHDR (&mesg, cmsg) == NULL
- && cmsg->cmsg_level == IPPROTO_IPV6
- && cmsg->cmsg_type == IPV6_PKTINFO
- && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in6_pktinfo)) )
- {
- struct in6_pktinfo *pkti6 = (struct in6_pktinfo *) CMSG_DATA (cmsg);
- from->pi.in6.ipi6_ifindex = pkti6->ipi6_ifindex;
- from->pi.in6.ipi6_addr = pkti6->ipi6_addr;
- }
- else if (cmsg != NULL)
- {
- msg(M_WARN, "CMSG received that cannot be parsed (cmsg_level=%d, cmsg_type=%d, cmsg=len=%d)", (int)cmsg->cmsg_level, (int)cmsg->cmsg_type, (int)cmsg->cmsg_len );
- }
- }
-
- return fromlen;
+ }
+ else if (cmsg != NULL
+ && CMSG_NXTHDR(&mesg, cmsg) == NULL
+ && cmsg->cmsg_level == IPPROTO_IPV6
+ && cmsg->cmsg_type == IPV6_PKTINFO
+ && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in6_pktinfo)) )
+ {
+ struct in6_pktinfo *pkti6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
+ from->pi.in6.ipi6_ifindex = pkti6->ipi6_ifindex;
+ from->pi.in6.ipi6_addr = pkti6->ipi6_addr;
+ }
+ else if (cmsg != NULL)
+ {
+ msg(M_WARN, "CMSG received that cannot be parsed (cmsg_level=%d, cmsg_type=%d, cmsg=len=%d)", (int)cmsg->cmsg_level, (int)cmsg->cmsg_type, (int)cmsg->cmsg_len );
+ }
+ }
+
+ return fromlen;
}
-#endif
+#endif /* if ENABLE_IP_PKTINFO */
int
-link_socket_read_udp_posix (struct link_socket *sock,
- struct buffer *buf,
- struct link_socket_actual *from)
+link_socket_read_udp_posix(struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *from)
{
- socklen_t fromlen = sizeof (from->dest.addr);
- socklen_t expectedlen = af_addr_size(sock->info.af);
- addr_zero_host(&from->dest);
+ socklen_t fromlen = sizeof(from->dest.addr);
+ socklen_t expectedlen = af_addr_size(sock->info.af);
+ addr_zero_host(&from->dest);
#if ENABLE_IP_PKTINFO
- /* Both PROTO_UDPv4 and PROTO_UDPv6 */
- if (sock->info.proto == PROTO_UDP && sock->sockflags & SF_USE_IP_PKTINFO)
- fromlen = link_socket_read_udp_posix_recvmsg (sock, buf, from);
- else
+ /* Both PROTO_UDPv4 and PROTO_UDPv6 */
+ if (sock->info.proto == PROTO_UDP && sock->sockflags & SF_USE_IP_PKTINFO)
+ {
+ fromlen = link_socket_read_udp_posix_recvmsg(sock, buf, from);
+ }
+ else
#endif
- buf->len = recvfrom (sock->sd, BPTR (buf), buf_forward_capacity(buf), 0,
- &from->dest.addr.sa, &fromlen);
- /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
- if (buf->len >= 0 && expectedlen && fromlen != expectedlen)
- bad_address_length (fromlen, expectedlen);
- return buf->len;
+ buf->len = recvfrom(sock->sd, BPTR(buf), buf_forward_capacity(buf), 0,
+ &from->dest.addr.sa, &fromlen);
+ /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
+ if (buf->len >= 0 && expectedlen && fromlen != expectedlen)
+ {
+ bad_address_length(fromlen, expectedlen);
+ }
+ return buf->len;
}
-#endif
+#endif /* ifndef _WIN32 */
/*
* Socket Write Routines
*/
int
-link_socket_write_tcp (struct link_socket *sock,
- struct buffer *buf,
- struct link_socket_actual *to)
-{
- packet_size_type len = BLEN (buf);
- dmsg (D_STREAM_DEBUG, "STREAM: WRITE %d offset=%d", (int)len, buf->offset);
- ASSERT (len <= sock->stream_buf.maxlen);
- len = htonps (len);
- ASSERT (buf_write_prepend (buf, &len, sizeof (len)));
+link_socket_write_tcp(struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *to)
+{
+ packet_size_type len = BLEN(buf);
+ dmsg(D_STREAM_DEBUG, "STREAM: WRITE %d offset=%d", (int)len, buf->offset);
+ ASSERT(len <= sock->stream_buf.maxlen);
+ len = htonps(len);
+ ASSERT(buf_write_prepend(buf, &len, sizeof(len)));
#ifdef _WIN32
- return link_socket_write_win32 (sock, buf, to);
+ return link_socket_write_win32(sock, buf, to);
#else
- return link_socket_write_tcp_posix (sock, buf, to);
+ return link_socket_write_tcp_posix(sock, buf, to);
#endif
}
#if ENABLE_IP_PKTINFO
size_t
-link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
- struct buffer *buf,
- struct link_socket_actual *to)
-{
- struct iovec iov;
- struct msghdr mesg;
- struct cmsghdr *cmsg;
- uint8_t pktinfo_buf[PKTINFO_BUF_SIZE];
-
- iov.iov_base = BPTR (buf);
- iov.iov_len = BLEN (buf);
- mesg.msg_iov = &iov;
- mesg.msg_iovlen = 1;
- switch (to->dest.addr.sa.sa_family)
- {
- case AF_INET:
- {
- mesg.msg_name = &to->dest.addr.sa;
- mesg.msg_namelen = sizeof (struct sockaddr_in);
- mesg.msg_control = pktinfo_buf;
- mesg.msg_flags = 0;
+link_socket_write_udp_posix_sendmsg(struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *to)
+{
+ struct iovec iov;
+ struct msghdr mesg;
+ struct cmsghdr *cmsg;
+ uint8_t pktinfo_buf[PKTINFO_BUF_SIZE];
+
+ iov.iov_base = BPTR(buf);
+ iov.iov_len = BLEN(buf);
+ mesg.msg_iov = &iov;
+ mesg.msg_iovlen = 1;
+ switch (to->dest.addr.sa.sa_family)
+ {
+ case AF_INET:
+ {
+ mesg.msg_name = &to->dest.addr.sa;
+ mesg.msg_namelen = sizeof(struct sockaddr_in);
+ mesg.msg_control = pktinfo_buf;
+ mesg.msg_flags = 0;
#if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST)
- mesg.msg_controllen = CMSG_SPACE(sizeof (struct in_pktinfo));
- cmsg = CMSG_FIRSTHDR (&mesg);
- cmsg->cmsg_len = CMSG_LEN(sizeof (struct in_pktinfo));
- cmsg->cmsg_level = SOL_IP;
- cmsg->cmsg_type = IP_PKTINFO;
- {
- struct in_pktinfo *pkti;
- pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
- pkti->ipi_ifindex = to->pi.in4.ipi_ifindex;
- pkti->ipi_spec_dst = to->pi.in4.ipi_spec_dst;
- pkti->ipi_addr.s_addr = 0;
- }
+ mesg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
+ cmsg = CMSG_FIRSTHDR(&mesg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ cmsg->cmsg_level = SOL_IP;
+ cmsg->cmsg_type = IP_PKTINFO;
+ {
+ struct in_pktinfo *pkti;
+ pkti = (struct in_pktinfo *) CMSG_DATA(cmsg);
+ pkti->ipi_ifindex = to->pi.in4.ipi_ifindex;
+ pkti->ipi_spec_dst = to->pi.in4.ipi_spec_dst;
+ pkti->ipi_addr.s_addr = 0;
+ }
#elif defined(IP_RECVDSTADDR)
- ASSERT( CMSG_SPACE(sizeof (struct in_addr)) <= sizeof(pktinfo_buf) );
- mesg.msg_controllen = CMSG_SPACE(sizeof (struct in_addr));
- cmsg = CMSG_FIRSTHDR (&mesg);
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
- cmsg->cmsg_level = IPPROTO_IP;
- cmsg->cmsg_type = IP_RECVDSTADDR;
- *(struct in_addr *) CMSG_DATA (cmsg) = to->pi.in4;
-#else
+ ASSERT( CMSG_SPACE(sizeof(struct in_addr)) <= sizeof(pktinfo_buf) );
+ mesg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
+ cmsg = CMSG_FIRSTHDR(&mesg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_RECVDSTADDR;
+ *(struct in_addr *) CMSG_DATA(cmsg) = to->pi.in4;
+#else /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
-#endif
- break;
- }
- case AF_INET6:
- {
- struct in6_pktinfo *pkti6;
- mesg.msg_name = &to->dest.addr.sa;
- mesg.msg_namelen = sizeof (struct sockaddr_in6);
-
- ASSERT( CMSG_SPACE(sizeof (struct in6_pktinfo)) <= sizeof(pktinfo_buf) );
- mesg.msg_control = pktinfo_buf;
- mesg.msg_controllen = CMSG_SPACE(sizeof (struct in6_pktinfo));
- mesg.msg_flags = 0;
- cmsg = CMSG_FIRSTHDR (&mesg);
- cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
- cmsg->cmsg_level = IPPROTO_IPV6;
- cmsg->cmsg_type = IPV6_PKTINFO;
-
- pkti6 = (struct in6_pktinfo *) CMSG_DATA (cmsg);
- pkti6->ipi6_ifindex = to->pi.in6.ipi6_ifindex;
- pkti6->ipi6_addr = to->pi.in6.ipi6_addr;
- break;
- }
- default: ASSERT(0);
- }
- return sendmsg (sock->sd, &mesg, 0);
+#endif /* if defined(HAVE_IN_PKTINFO) && defined(HAVE_IPI_SPEC_DST) */
+ break;
+ }
+
+ case AF_INET6:
+ {
+ struct in6_pktinfo *pkti6;
+ mesg.msg_name = &to->dest.addr.sa;
+ mesg.msg_namelen = sizeof(struct sockaddr_in6);
+
+ ASSERT( CMSG_SPACE(sizeof(struct in6_pktinfo)) <= sizeof(pktinfo_buf) );
+ mesg.msg_control = pktinfo_buf;
+ mesg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+ mesg.msg_flags = 0;
+ cmsg = CMSG_FIRSTHDR(&mesg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ cmsg->cmsg_level = IPPROTO_IPV6;
+ cmsg->cmsg_type = IPV6_PKTINFO;
+
+ pkti6 = (struct in6_pktinfo *) CMSG_DATA(cmsg);
+ pkti6->ipi6_ifindex = to->pi.in6.ipi6_ifindex;
+ pkti6->ipi6_addr = to->pi.in6.ipi6_addr;
+ break;
+ }
+
+ default: ASSERT(0);
+ }
+ return sendmsg(sock->sd, &mesg, 0);
}
-#endif
+#endif /* if ENABLE_IP_PKTINFO */
/*
* Win32 overlapped socket I/O functions.
@@ -3074,335 +3432,347 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
#ifdef _WIN32
int
-socket_recv_queue (struct link_socket *sock, int maxsize)
-{
- if (sock->reads.iostate == IOSTATE_INITIAL)
- {
- WSABUF wsabuf[1];
- int status;
-
- /* reset buf to its initial state */
- if (proto_is_udp(sock->info.proto))
- {
- sock->reads.buf = sock->reads.buf_init;
- }
- else if (proto_is_tcp(sock->info.proto))
- {
- stream_buf_get_next (&sock->stream_buf, &sock->reads.buf);
- }
- else
- {
- ASSERT (0);
- }
-
- /* Win32 docs say it's okay to allocate the wsabuf on the stack */
- wsabuf[0].buf = BPTR (&sock->reads.buf);
- wsabuf[0].len = maxsize ? maxsize : BLEN (&sock->reads.buf);
-
- /* check for buffer overflow */
- ASSERT (wsabuf[0].len <= BLEN (&sock->reads.buf));
-
- /* the overlapped read will signal this event on I/O completion */
- ASSERT (ResetEvent (sock->reads.overlapped.hEvent));
- sock->reads.flags = 0;
-
- if (proto_is_udp(sock->info.proto))
- {
- sock->reads.addr_defined = true;
- sock->reads.addrlen = sizeof (sock->reads.addr6);
- status = WSARecvFrom(
- sock->sd,
- wsabuf,
- 1,
- &sock->reads.size,
- &sock->reads.flags,
- (struct sockaddr *) &sock->reads.addr,
- &sock->reads.addrlen,
- &sock->reads.overlapped,
- NULL);
- }
- else if (proto_is_tcp(sock->info.proto))
- {
- sock->reads.addr_defined = false;
- status = WSARecv(
- sock->sd,
- wsabuf,
- 1,
- &sock->reads.size,
- &sock->reads.flags,
- &sock->reads.overlapped,
- NULL);
- }
- else
- {
- status = 0;
- ASSERT (0);
- }
-
- if (!status) /* operation completed immediately? */
- {
- /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
- int af_len = af_addr_size (sock->info.af);
- if (sock->reads.addr_defined && af_len && sock->reads.addrlen != af_len)
- bad_address_length (sock->reads.addrlen, af_len);
- sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
-
- /* since we got an immediate return, we must signal the event object ourselves */
- ASSERT (SetEvent (sock->reads.overlapped.hEvent));
- sock->reads.status = 0;
-
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Receive immediate return [%d,%d]",
- (int) wsabuf[0].len,
- (int) sock->reads.size);
- }
- else
- {
- status = WSAGetLastError ();
- if (status == WSA_IO_PENDING) /* operation queued? */
- {
- sock->reads.iostate = IOSTATE_QUEUED;
- sock->reads.status = status;
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Receive queued [%d]",
- (int) wsabuf[0].len);
- }
- else /* error occurred */
- {
- struct gc_arena gc = gc_new ();
- ASSERT (SetEvent (sock->reads.overlapped.hEvent));
- sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
- sock->reads.status = status;
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Receive error [%d]: %s",
- (int) wsabuf[0].len,
- strerror_win32 (status, &gc));
- gc_free (&gc);
- }
- }
- }
- return sock->reads.iostate;
+socket_recv_queue(struct link_socket *sock, int maxsize)
+{
+ if (sock->reads.iostate == IOSTATE_INITIAL)
+ {
+ WSABUF wsabuf[1];
+ int status;
+
+ /* reset buf to its initial state */
+ if (proto_is_udp(sock->info.proto))
+ {
+ sock->reads.buf = sock->reads.buf_init;
+ }
+ else if (proto_is_tcp(sock->info.proto))
+ {
+ stream_buf_get_next(&sock->stream_buf, &sock->reads.buf);
+ }
+ else
+ {
+ ASSERT(0);
+ }
+
+ /* Win32 docs say it's okay to allocate the wsabuf on the stack */
+ wsabuf[0].buf = BPTR(&sock->reads.buf);
+ wsabuf[0].len = maxsize ? maxsize : BLEN(&sock->reads.buf);
+
+ /* check for buffer overflow */
+ ASSERT(wsabuf[0].len <= BLEN(&sock->reads.buf));
+
+ /* the overlapped read will signal this event on I/O completion */
+ ASSERT(ResetEvent(sock->reads.overlapped.hEvent));
+ sock->reads.flags = 0;
+
+ if (proto_is_udp(sock->info.proto))
+ {
+ sock->reads.addr_defined = true;
+ sock->reads.addrlen = sizeof(sock->reads.addr6);
+ status = WSARecvFrom(
+ sock->sd,
+ wsabuf,
+ 1,
+ &sock->reads.size,
+ &sock->reads.flags,
+ (struct sockaddr *) &sock->reads.addr,
+ &sock->reads.addrlen,
+ &sock->reads.overlapped,
+ NULL);
+ }
+ else if (proto_is_tcp(sock->info.proto))
+ {
+ sock->reads.addr_defined = false;
+ status = WSARecv(
+ sock->sd,
+ wsabuf,
+ 1,
+ &sock->reads.size,
+ &sock->reads.flags,
+ &sock->reads.overlapped,
+ NULL);
+ }
+ else
+ {
+ status = 0;
+ ASSERT(0);
+ }
+
+ if (!status) /* operation completed immediately? */
+ {
+ /* FIXME: won't do anything when sock->info.af == AF_UNSPEC */
+ int af_len = af_addr_size(sock->info.af);
+ if (sock->reads.addr_defined && af_len && sock->reads.addrlen != af_len)
+ {
+ bad_address_length(sock->reads.addrlen, af_len);
+ }
+ sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
+
+ /* since we got an immediate return, we must signal the event object ourselves */
+ ASSERT(SetEvent(sock->reads.overlapped.hEvent));
+ sock->reads.status = 0;
+
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Receive immediate return [%d,%d]",
+ (int) wsabuf[0].len,
+ (int) sock->reads.size);
+ }
+ else
+ {
+ status = WSAGetLastError();
+ if (status == WSA_IO_PENDING) /* operation queued? */
+ {
+ sock->reads.iostate = IOSTATE_QUEUED;
+ sock->reads.status = status;
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Receive queued [%d]",
+ (int) wsabuf[0].len);
+ }
+ else /* error occurred */
+ {
+ struct gc_arena gc = gc_new();
+ ASSERT(SetEvent(sock->reads.overlapped.hEvent));
+ sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
+ sock->reads.status = status;
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Receive error [%d]: %s",
+ (int) wsabuf[0].len,
+ strerror_win32(status, &gc));
+ gc_free(&gc);
+ }
+ }
+ }
+ return sock->reads.iostate;
}
int
-socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct link_socket_actual *to)
-{
- if (sock->writes.iostate == IOSTATE_INITIAL)
- {
- WSABUF wsabuf[1];
- int status;
-
- /* make a private copy of buf */
- sock->writes.buf = sock->writes.buf_init;
- sock->writes.buf.len = 0;
- ASSERT (buf_copy (&sock->writes.buf, buf));
-
- /* Win32 docs say it's okay to allocate the wsabuf on the stack */
- wsabuf[0].buf = BPTR (&sock->writes.buf);
- wsabuf[0].len = BLEN (&sock->writes.buf);
-
- /* the overlapped write will signal this event on I/O completion */
- ASSERT (ResetEvent (sock->writes.overlapped.hEvent));
- sock->writes.flags = 0;
-
- if (proto_is_udp(sock->info.proto))
- {
- /* set destination address for UDP writes */
- sock->writes.addr_defined = true;
- if (to->dest.addr.sa.sa_family == AF_INET6)
- {
- sock->writes.addr6 = to->dest.addr.in6;
- sock->writes.addrlen = sizeof (sock->writes.addr6);
- }
- else
- {
- sock->writes.addr = to->dest.addr.in4;
- sock->writes.addrlen = sizeof (sock->writes.addr);
- }
-
- status = WSASendTo(
- sock->sd,
- wsabuf,
- 1,
- &sock->writes.size,
- sock->writes.flags,
- (struct sockaddr *) &sock->writes.addr,
- sock->writes.addrlen,
- &sock->writes.overlapped,
- NULL);
- }
- else if (proto_is_tcp(sock->info.proto))
- {
- /* destination address for TCP writes was established on connection initiation */
- sock->writes.addr_defined = false;
-
- status = WSASend(
- sock->sd,
- wsabuf,
- 1,
- &sock->writes.size,
- sock->writes.flags,
- &sock->writes.overlapped,
- NULL);
- }
- else
- {
- status = 0;
- ASSERT (0);
- }
-
- if (!status) /* operation completed immediately? */
- {
- sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
-
- /* since we got an immediate return, we must signal the event object ourselves */
- ASSERT (SetEvent (sock->writes.overlapped.hEvent));
-
- sock->writes.status = 0;
-
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Send immediate return [%d,%d]",
- (int) wsabuf[0].len,
- (int) sock->writes.size);
- }
- else
- {
- status = WSAGetLastError ();
- if (status == WSA_IO_PENDING) /* operation queued? */
- {
- sock->writes.iostate = IOSTATE_QUEUED;
- sock->writes.status = status;
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Send queued [%d]",
- (int) wsabuf[0].len);
- }
- else /* error occurred */
- {
- struct gc_arena gc = gc_new ();
- ASSERT (SetEvent (sock->writes.overlapped.hEvent));
- sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
- sock->writes.status = status;
-
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Send error [%d]: %s",
- (int) wsabuf[0].len,
- strerror_win32 (status, &gc));
-
- gc_free (&gc);
- }
- }
- }
- return sock->writes.iostate;
+socket_send_queue(struct link_socket *sock, struct buffer *buf, const struct link_socket_actual *to)
+{
+ if (sock->writes.iostate == IOSTATE_INITIAL)
+ {
+ WSABUF wsabuf[1];
+ int status;
+
+ /* make a private copy of buf */
+ sock->writes.buf = sock->writes.buf_init;
+ sock->writes.buf.len = 0;
+ ASSERT(buf_copy(&sock->writes.buf, buf));
+
+ /* Win32 docs say it's okay to allocate the wsabuf on the stack */
+ wsabuf[0].buf = BPTR(&sock->writes.buf);
+ wsabuf[0].len = BLEN(&sock->writes.buf);
+
+ /* the overlapped write will signal this event on I/O completion */
+ ASSERT(ResetEvent(sock->writes.overlapped.hEvent));
+ sock->writes.flags = 0;
+
+ if (proto_is_udp(sock->info.proto))
+ {
+ /* set destination address for UDP writes */
+ sock->writes.addr_defined = true;
+ if (to->dest.addr.sa.sa_family == AF_INET6)
+ {
+ sock->writes.addr6 = to->dest.addr.in6;
+ sock->writes.addrlen = sizeof(sock->writes.addr6);
+ }
+ else
+ {
+ sock->writes.addr = to->dest.addr.in4;
+ sock->writes.addrlen = sizeof(sock->writes.addr);
+ }
+
+ status = WSASendTo(
+ sock->sd,
+ wsabuf,
+ 1,
+ &sock->writes.size,
+ sock->writes.flags,
+ (struct sockaddr *) &sock->writes.addr,
+ sock->writes.addrlen,
+ &sock->writes.overlapped,
+ NULL);
+ }
+ else if (proto_is_tcp(sock->info.proto))
+ {
+ /* destination address for TCP writes was established on connection initiation */
+ sock->writes.addr_defined = false;
+
+ status = WSASend(
+ sock->sd,
+ wsabuf,
+ 1,
+ &sock->writes.size,
+ sock->writes.flags,
+ &sock->writes.overlapped,
+ NULL);
+ }
+ else
+ {
+ status = 0;
+ ASSERT(0);
+ }
+
+ if (!status) /* operation completed immediately? */
+ {
+ sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
+
+ /* since we got an immediate return, we must signal the event object ourselves */
+ ASSERT(SetEvent(sock->writes.overlapped.hEvent));
+
+ sock->writes.status = 0;
+
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Send immediate return [%d,%d]",
+ (int) wsabuf[0].len,
+ (int) sock->writes.size);
+ }
+ else
+ {
+ status = WSAGetLastError();
+ if (status == WSA_IO_PENDING) /* operation queued? */
+ {
+ sock->writes.iostate = IOSTATE_QUEUED;
+ sock->writes.status = status;
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Send queued [%d]",
+ (int) wsabuf[0].len);
+ }
+ else /* error occurred */
+ {
+ struct gc_arena gc = gc_new();
+ ASSERT(SetEvent(sock->writes.overlapped.hEvent));
+ sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
+ sock->writes.status = status;
+
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Send error [%d]: %s",
+ (int) wsabuf[0].len,
+ strerror_win32(status, &gc));
+
+ gc_free(&gc);
+ }
+ }
+ }
+ return sock->writes.iostate;
}
int
-socket_finalize (SOCKET s,
- struct overlapped_io *io,
- struct buffer *buf,
- struct link_socket_actual *from)
-{
- int ret = -1;
- BOOL status;
-
- switch (io->iostate)
- {
- case IOSTATE_QUEUED:
- status = WSAGetOverlappedResult(
- s,
- &io->overlapped,
- &io->size,
- FALSE,
- &io->flags
- );
- if (status)
- {
- /* successful return for a queued operation */
- if (buf)
- *buf = io->buf;
- ret = io->size;
- io->iostate = IOSTATE_INITIAL;
- ASSERT (ResetEvent (io->overlapped.hEvent));
-
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Completion success [%d]", ret);
- }
- else
- {
- /* error during a queued operation */
- ret = -1;
- if (WSAGetLastError() != WSA_IO_INCOMPLETE)
- {
- /* if no error (i.e. just not finished yet), then DON'T execute this code */
- io->iostate = IOSTATE_INITIAL;
- ASSERT (ResetEvent (io->overlapped.hEvent));
- msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion error");
- }
- }
- break;
-
- case IOSTATE_IMMEDIATE_RETURN:
- io->iostate = IOSTATE_INITIAL;
- ASSERT (ResetEvent (io->overlapped.hEvent));
- if (io->status)
- {
- /* error return for a non-queued operation */
- WSASetLastError (io->status);
- ret = -1;
- msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion non-queued error");
- }
- else
- {
- /* successful return for a non-queued operation */
- if (buf)
- *buf = io->buf;
- ret = io->size;
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Completion non-queued success [%d]", ret);
- }
- break;
-
- case IOSTATE_INITIAL: /* were we called without proper queueing? */
- WSASetLastError (WSAEINVAL);
- ret = -1;
- dmsg (D_WIN32_IO, "WIN32 I/O: Socket Completion BAD STATE");
- break;
-
- default:
- ASSERT (0);
- }
-
- /* return from address if requested */
- if (from)
- {
- if (ret >= 0 && io->addr_defined)
- {
- /* TODO(jjo): streamline this mess */
- /* in this func we dont have relevant info about the PF_ of this
- * endpoint, as link_socket_actual will be zero for the 1st received packet
- *
- * Test for inets PF_ possible sizes
- */
- switch (io->addrlen)
- {
- case sizeof(struct sockaddr_in):
- case sizeof(struct sockaddr_in6):
- /* TODO(jjo): for some reason (?) I'm getting 24,28 for AF_INET6
- * under _WIN32*/
- case sizeof(struct sockaddr_in6)-4:
- break;
- default:
- bad_address_length (io->addrlen, af_addr_size(io->addr.sin_family));
- }
-
- switch (io->addr.sin_family)
- {
- case AF_INET:
- from->dest.addr.in4 = io->addr;
- break;
- case AF_INET6:
- from->dest.addr.in6 = io->addr6;
- break;
- }
- }
- else
- CLEAR (from->dest.addr);
- }
-
- if (buf)
- buf->len = ret;
- return ret;
+socket_finalize(SOCKET s,
+ struct overlapped_io *io,
+ struct buffer *buf,
+ struct link_socket_actual *from)
+{
+ int ret = -1;
+ BOOL status;
+
+ switch (io->iostate)
+ {
+ case IOSTATE_QUEUED:
+ status = WSAGetOverlappedResult(
+ s,
+ &io->overlapped,
+ &io->size,
+ FALSE,
+ &io->flags
+ );
+ if (status)
+ {
+ /* successful return for a queued operation */
+ if (buf)
+ {
+ *buf = io->buf;
+ }
+ ret = io->size;
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT(ResetEvent(io->overlapped.hEvent));
+
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion success [%d]", ret);
+ }
+ else
+ {
+ /* error during a queued operation */
+ ret = -1;
+ if (WSAGetLastError() != WSA_IO_INCOMPLETE)
+ {
+ /* if no error (i.e. just not finished yet), then DON'T execute this code */
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT(ResetEvent(io->overlapped.hEvent));
+ msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion error");
+ }
+ }
+ break;
+
+ case IOSTATE_IMMEDIATE_RETURN:
+ io->iostate = IOSTATE_INITIAL;
+ ASSERT(ResetEvent(io->overlapped.hEvent));
+ if (io->status)
+ {
+ /* error return for a non-queued operation */
+ WSASetLastError(io->status);
+ ret = -1;
+ msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion non-queued error");
+ }
+ else
+ {
+ /* successful return for a non-queued operation */
+ if (buf)
+ {
+ *buf = io->buf;
+ }
+ ret = io->size;
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion non-queued success [%d]", ret);
+ }
+ break;
+
+ case IOSTATE_INITIAL: /* were we called without proper queueing? */
+ WSASetLastError(WSAEINVAL);
+ ret = -1;
+ dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion BAD STATE");
+ break;
+
+ default:
+ ASSERT(0);
+ }
+
+ /* return from address if requested */
+ if (from)
+ {
+ if (ret >= 0 && io->addr_defined)
+ {
+ /* TODO(jjo): streamline this mess */
+ /* in this func we dont have relevant info about the PF_ of this
+ * endpoint, as link_socket_actual will be zero for the 1st received packet
+ *
+ * Test for inets PF_ possible sizes
+ */
+ switch (io->addrlen)
+ {
+ case sizeof(struct sockaddr_in):
+ case sizeof(struct sockaddr_in6):
+ /* TODO(jjo): for some reason (?) I'm getting 24,28 for AF_INET6
+ * under _WIN32*/
+ case sizeof(struct sockaddr_in6)-4:
+ break;
+
+ default:
+ bad_address_length(io->addrlen, af_addr_size(io->addr.sin_family));
+ }
+
+ switch (io->addr.sin_family)
+ {
+ case AF_INET:
+ from->dest.addr.in4 = io->addr;
+ break;
+
+ case AF_INET6:
+ from->dest.addr.in6 = io->addr6;
+ break;
+ }
+ }
+ else
+ {
+ CLEAR(from->dest.addr);
+ }
+ }
+
+ if (buf)
+ {
+ buf->len = ret;
+ }
+ return ret;
}
#endif /* _WIN32 */
@@ -3412,45 +3782,49 @@ socket_finalize (SOCKET s,
*/
unsigned int
-socket_set (struct link_socket *s,
- struct event_set *es,
- unsigned int rwflags,
- void *arg,
- unsigned int *persistent)
-{
- if (s)
- {
- if ((rwflags & EVENT_READ) && !stream_buf_read_setup (s))
- {
- ASSERT (!persistent);
- rwflags &= ~EVENT_READ;
- }
-
+socket_set(struct link_socket *s,
+ struct event_set *es,
+ unsigned int rwflags,
+ void *arg,
+ unsigned int *persistent)
+{
+ if (s)
+ {
+ if ((rwflags & EVENT_READ) && !stream_buf_read_setup(s))
+ {
+ ASSERT(!persistent);
+ rwflags &= ~EVENT_READ;
+ }
+
#ifdef _WIN32
- if (rwflags & EVENT_READ)
- socket_recv_queue (s, 0);
+ if (rwflags & EVENT_READ)
+ {
+ socket_recv_queue(s, 0);
+ }
#endif
- /* if persistent is defined, call event_ctl only if rwflags has changed since last call */
- if (!persistent || *persistent != rwflags)
- {
- event_ctl (es, socket_event_handle (s), rwflags, arg);
- if (persistent)
- *persistent = rwflags;
- }
+ /* if persistent is defined, call event_ctl only if rwflags has changed since last call */
+ if (!persistent || *persistent != rwflags)
+ {
+ event_ctl(es, socket_event_handle(s), rwflags, arg);
+ if (persistent)
+ {
+ *persistent = rwflags;
+ }
+ }
- s->rwflags_debug = rwflags;
+ s->rwflags_debug = rwflags;
}
- return rwflags;
+ return rwflags;
}
void
-sd_close (socket_descriptor_t *sd)
+sd_close(socket_descriptor_t *sd)
{
- if (sd && socket_defined (*sd))
+ if (sd && socket_defined(*sd))
{
- openvpn_close_socket (*sd);
- *sd = SOCKET_UNDEFINED;
+ openvpn_close_socket(*sd);
+ *sd = SOCKET_UNDEFINED;
}
}
@@ -3461,117 +3835,150 @@ sd_close (socket_descriptor_t *sd)
*/
const char *
-sockaddr_unix_name (const struct sockaddr_un *local, const char *null)
+sockaddr_unix_name(const struct sockaddr_un *local, const char *null)
{
- if (local && local->sun_family == PF_UNIX)
- return local->sun_path;
- else
- return null;
+ if (local && local->sun_family == PF_UNIX)
+ {
+ return local->sun_path;
+ }
+ else
+ {
+ return null;
+ }
}
socket_descriptor_t
-create_socket_unix (void)
+create_socket_unix(void)
{
- socket_descriptor_t sd;
+ socket_descriptor_t sd;
- if ((sd = socket (PF_UNIX, SOCK_STREAM, 0)) < 0)
- msg (M_ERR, "Cannot create unix domain socket");
- return sd;
+ if ((sd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ msg(M_ERR, "Cannot create unix domain socket");
+ }
+
+ /* set socket file descriptor to not pass across execs, so that
+ * scripts don't have access to it */
+ set_cloexec(sd);
+
+ return sd;
}
void
-socket_bind_unix (socket_descriptor_t sd,
- struct sockaddr_un *local,
- const char *prefix)
+socket_bind_unix(socket_descriptor_t sd,
+ struct sockaddr_un *local,
+ const char *prefix)
{
- struct gc_arena gc = gc_new ();
+ struct gc_arena gc = gc_new();
#ifdef HAVE_UMASK
- const mode_t orig_umask = umask (0);
+ const mode_t orig_umask = umask(0);
#endif
- if (bind (sd, (struct sockaddr *) local, sizeof (struct sockaddr_un)))
+ if (bind(sd, (struct sockaddr *) local, sizeof(struct sockaddr_un)))
{
- const int errnum = openvpn_errno ();
- msg (M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s",
- prefix,
- (int)sd,
- sockaddr_unix_name (local, "NULL"),
- strerror_ts (errnum, &gc));
+ const int errnum = openvpn_errno();
+ msg(M_FATAL, "%s: Socket bind[%d] failed on unix domain socket %s: %s",
+ prefix,
+ (int)sd,
+ sockaddr_unix_name(local, "NULL"),
+ strerror_ts(errnum, &gc));
}
#ifdef HAVE_UMASK
- umask (orig_umask);
+ umask(orig_umask);
#endif
- gc_free (&gc);
+ gc_free(&gc);
}
socket_descriptor_t
-socket_accept_unix (socket_descriptor_t sd,
- struct sockaddr_un *remote)
+socket_accept_unix(socket_descriptor_t sd,
+ struct sockaddr_un *remote)
{
- socklen_t remote_len = sizeof (struct sockaddr_un);
- socket_descriptor_t ret;
+ socklen_t remote_len = sizeof(struct sockaddr_un);
+ socket_descriptor_t ret;
- CLEAR (*remote);
- ret = accept (sd, (struct sockaddr *) remote, &remote_len);
- return ret;
+ CLEAR(*remote);
+ ret = accept(sd, (struct sockaddr *) remote, &remote_len);
+ if (ret >= 0)
+ {
+ /* set socket file descriptor to not pass across execs, so that
+ * scripts don't have access to it */
+ set_cloexec(ret);
+ }
+ return ret;
}
int
-socket_connect_unix (socket_descriptor_t sd,
- struct sockaddr_un *remote)
+socket_connect_unix(socket_descriptor_t sd,
+ struct sockaddr_un *remote)
{
- int status = connect (sd, (struct sockaddr *) remote, sizeof (struct sockaddr_un));
- if (status)
- status = openvpn_errno ();
- return status;
+ int status = connect(sd, (struct sockaddr *) remote, sizeof(struct sockaddr_un));
+ if (status)
+ {
+ status = openvpn_errno();
+ }
+ return status;
}
void
-sockaddr_unix_init (struct sockaddr_un *local, const char *path)
+sockaddr_unix_init(struct sockaddr_un *local, const char *path)
{
- local->sun_family = PF_UNIX;
- strncpynt (local->sun_path, path, sizeof (local->sun_path));
+ local->sun_family = PF_UNIX;
+ strncpynt(local->sun_path, path, sizeof(local->sun_path));
}
void
-socket_delete_unix (const struct sockaddr_un *local)
+socket_delete_unix(const struct sockaddr_un *local)
{
- const char *name = sockaddr_unix_name (local, NULL);
+ const char *name = sockaddr_unix_name(local, NULL);
#ifdef HAVE_UNLINK
- if (name && strlen (name))
- unlink (name);
+ if (name && strlen(name))
+ {
+ unlink(name);
+ }
#endif
}
bool
-unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *gid)
+unix_socket_get_peer_uid_gid(const socket_descriptor_t sd, int *uid, int *gid)
{
#ifdef HAVE_GETPEEREID
- uid_t u;
- gid_t g;
- if (getpeereid (sd, &u, &g) == -1)
- return false;
- if (uid)
- *uid = u;
- if (gid)
- *gid = g;
- return true;
+ uid_t u;
+ gid_t g;
+ if (getpeereid(sd, &u, &g) == -1)
+ {
+ return false;
+ }
+ if (uid)
+ {
+ *uid = u;
+ }
+ if (gid)
+ {
+ *gid = g;
+ }
+ return true;
#elif defined(SO_PEERCRED)
- struct ucred peercred;
- socklen_t so_len = sizeof(peercred);
- if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1)
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+ if (getsockopt(sd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1)
+ {
+ return false;
+ }
+ if (uid)
+ {
+ *uid = peercred.uid;
+ }
+ if (gid)
+ {
+ *gid = peercred.gid;
+ }
+ return true;
+#else /* ifdef HAVE_GETPEEREID */
return false;
- if (uid)
- *uid = peercred.uid;
- if (gid)
- *gid = peercred.gid;
- return true;
-#else
- return false;
-#endif
+#endif /* ifdef HAVE_GETPEEREID */
}
-#endif
+#endif /* if UNIX_SOCK_SUPPORT */