summaryrefslogtreecommitdiff
path: root/openvpn/src
diff options
context:
space:
mode:
Diffstat (limited to 'openvpn/src')
-rw-r--r--openvpn/src/openvpn/error.h2
-rw-r--r--openvpn/src/openvpn/manage.c6
-rw-r--r--openvpn/src/openvpn/options.c4
-rw-r--r--openvpn/src/openvpn/ps.c2
-rw-r--r--openvpn/src/openvpn/route.c48
-rw-r--r--openvpn/src/openvpn/route.h1
-rw-r--r--openvpn/src/openvpn/socket.c185
-rw-r--r--openvpn/src/openvpn/socket.h6
8 files changed, 150 insertions, 104 deletions
diff --git a/openvpn/src/openvpn/error.h b/openvpn/src/openvpn/error.h
index 5571bfdb..1e1f2acf 100644
--- a/openvpn/src/openvpn/error.h
+++ b/openvpn/src/openvpn/error.h
@@ -194,7 +194,7 @@ void error_reset (void);
void errors_to_stderr (void);
void set_suppress_timestamps (bool suppressed);
-void set_parsable_output (bool parsable);
+void set_machine_readable_output (bool parsable);
#define SDL_CONSTRAIN (1<<0)
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 06965ad2..561c252b 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -1568,9 +1568,9 @@ man_listen (struct management *man)
else
#endif
{
- man->connection.sd_top = create_socket_tcp (man->settings.local->ai_family);
+ man->connection.sd_top = create_socket_tcp (man->settings.local);
socket_bind (man->connection.sd_top, man->settings.local,
- man->settings.local->ai_family, "MANAGEMENT", false);
+ man->settings.local->ai_family, "MANAGEMENT", false);
}
/*
@@ -1635,7 +1635,7 @@ man_connect (struct management *man)
else
#endif
{
- man->connection.sd_cli = create_socket_tcp (AF_INET);
+ man->connection.sd_cli = create_socket_tcp (man->settings.local);
status = openvpn_connect (man->connection.sd_cli,
man->settings.local->ai_addr,
5,
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 52c6c239..9393c0aa 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -2076,6 +2076,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#endif
if (options->routes && (options->routes->flags & RG_ENABLE))
msg (M_USAGE, "--redirect-gateway cannot be used with --mode server (however --push \"redirect-gateway\" is fine)");
+ if (options->routes && ((options->routes->flags & RG_BLOCK_LOCAL) && (options->routes->flags & RG_BLOCK_LOCAL)))
+ msg (M_USAGE, "unblock-local and block-local options of redirect-gateway/redirect-private are mutatlly exclusive");
if (options->route_delay_defined)
msg (M_USAGE, "--route-delay cannot be used with --mode server");
if (options->up_delay)
@@ -5363,6 +5365,8 @@ add_option (struct options *options,
options->routes->flags |= RG_BYPASS_DNS;
else if (streq (p[j], "block-local"))
options->routes->flags |= RG_BLOCK_LOCAL;
+ else if (streq (p[j], "unblock-local"))
+ options->routes->flags |= RG_UNBLOCK_LOCAL;
else
{
msg (msglevel, "unknown --%s flag: %s", p[0], p[j]);
diff --git a/openvpn/src/openvpn/ps.c b/openvpn/src/openvpn/ps.c
index 901a094f..6807aac0 100644
--- a/openvpn/src/openvpn/ps.c
+++ b/openvpn/src/openvpn/ps.c
@@ -803,7 +803,7 @@ port_share_open (const char *host,
* Get host's IP address
*/
- status = openvpn_getaddrinfo (GETADDR_RESOLVE|GETADDR_HOST_ORDER|GETADDR_FATAL,
+ status = openvpn_getaddrinfo (GETADDR_RESOLVE|GETADDR_FATAL,
host, port, 0, NULL, AF_INET, &ai);
ASSERT (status==0);
hostaddr = *((struct sockaddr_in*) ai->ai_addr);
diff --git a/openvpn/src/openvpn/route.c b/openvpn/src/openvpn/route.c
index fa8221d4..25eeb77c 100644
--- a/openvpn/src/openvpn/route.c
+++ b/openvpn/src/openvpn/route.c
@@ -536,6 +536,46 @@ add_block_local_item (struct route_list *rl,
}
static void
+add_unblock_local (struct route_list *rl)
+{
+ const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
+
+ if (rl->flags & RG_UNBLOCK_LOCAL && rl->n+1 < rl->capacity
+ && (rl->rgi.flags & rgi_needed) == rgi_needed)
+ {
+ /* unblock access to local subnet */
+ struct route_ipv4 r;
+ int i;
+
+ CLEAR(r);
+ r.flags = RT_DEFINED;
+ r.network = rl->rgi.gateway.addr & rl->rgi.gateway.netmask;
+ r.netmask = rl->rgi.gateway.netmask;
+ r.gateway = rl->rgi.gateway.addr;
+ rl->routes[rl->n++] = r;
+
+ /* Additional local networks */
+ for (i = 0; i < rl->rgi.n_addrs; ++i)
+ {
+ const struct route_gateway_address *gwa = &rl->rgi.addrs[i];
+
+ /* omit the add/subnet in &rl->rgi which we processed above */
+ if ((!((rl->rgi.gateway.addr & rl->rgi.gateway.netmask) == (gwa->addr & gwa->netmask)
+ && rl->rgi.gateway.netmask == gwa->netmask)) && rl->n+1 < rl->capacity)
+ {
+ CLEAR(r);
+ r.flags = RT_DEFINED;
+ r.network = gwa->addr & gwa->netmask;
+ r.netmask = gwa->netmask;
+ r.gateway = gwa->addr;
+ rl->routes[rl->n++] = r;
+ }
+ }
+ }
+}
+
+
+static void
add_block_local (struct route_list *rl)
{
const int rgi_needed = (RGI_ADDR_DEFINED|RGI_NETMASK_DEFINED);
@@ -546,8 +586,10 @@ add_block_local (struct route_list *rl)
{
size_t i;
+#ifndef TARGET_ANDROID
/* add bypass for gateway addr */
add_bypass_address (&rl->spec.bypass, rl->rgi.gateway.addr);
+#endif
/* block access to local subnet */
add_block_local_item (rl, &rl->rgi.gateway, rl->spec.remote_endpoint);
@@ -564,6 +606,8 @@ add_block_local (struct route_list *rl)
}
}
+
+
bool
init_route_list (struct route_list *rl,
const struct route_option_list *opt,
@@ -632,6 +676,8 @@ init_route_list (struct route_list *rl,
}
}
+
+ add_unblock_local (rl);
if (rl->flags & RG_ENABLE)
{
add_block_local (rl);
@@ -852,6 +898,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
}
else
{
+#ifndef TARGET_ANDROID
bool local = BOOL_CAST(rl->flags & RG_LOCAL);
if (rl->flags & RG_AUTO_LOCAL) {
const int tla = rl->spec.remote_host_local;
@@ -884,6 +931,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u
dmsg (D_ROUTE, "ROUTE remote_host protocol differs from tunneled");
}
}
+#endif
/* route DHCP/DNS server traffic through original default gateway */
add_bypass_routes (&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags, &rl->rgi, es);
diff --git a/openvpn/src/openvpn/route.h b/openvpn/src/openvpn/route.h
index fe9b4616..c5e2c1e4 100644
--- a/openvpn/src/openvpn/route.h
+++ b/openvpn/src/openvpn/route.h
@@ -89,6 +89,7 @@ struct route_option {
#define RG_REROUTE_GW (1<<5)
#define RG_AUTO_LOCAL (1<<6)
#define RG_BLOCK_LOCAL (1<<7)
+#define RG_UNBLOCK_LOCAL (1<<8)
struct route_option_list {
unsigned int flags; /* RG_x flags */
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index 97f67563..4b86d439 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -766,11 +766,15 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
*/
socket_descriptor_t
-create_socket_tcp (int af)
+create_socket_tcp (struct addrinfo* addrinfo)
{
socket_descriptor_t sd;
- if ((sd = socket (af, SOCK_STREAM, IPPROTO_TCP)) < 0)
+ ASSERT (addrinfo);
+ ASSERT (addrinfo->ai_socktype == SOCK_STREAM);
+ ASSERT (addrinfo->ai_protocol == IPPROTO_TCP);
+
+ 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! */
@@ -787,17 +791,21 @@ create_socket_tcp (int af)
}
static socket_descriptor_t
-create_socket_udp (const int af, const unsigned int flags)
+create_socket_udp (struct addrinfo* addrinfo, const unsigned int flags)
{
socket_descriptor_t sd;
- if ((sd = socket (af, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ ASSERT (addrinfo);
+ ASSERT (addrinfo->ai_socktype == SOCK_DGRAM);
+ ASSERT (addrinfo->ai_protocol == IPPROTO_UDP);
+
+ 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)
{
int pad = 1;
- if(af == AF_INET)
+ if(addrinfo->ai_family == AF_INET)
{
#ifdef IP_PKTINFO
if (setsockopt (sd, SOL_IP, IP_PKTINFO,
@@ -811,7 +819,7 @@ create_socket_udp (const int af, const unsigned int flags)
#error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h)
#endif
}
- else if (af == 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,
@@ -827,28 +835,48 @@ create_socket_udp (const int af, const unsigned int flags)
return sd;
}
-static void
-create_socket (struct link_socket *sock)
+static void bind_local (struct link_socket *sock, const sa_family_t ai_family)
{
- /* create socket, use information carried over from getaddrinfo */
- const int ai_proto = sock->info.lsa->actual.ai_protocol;
- int ai_family = sock->info.lsa->actual.ai_family;
-
- ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family);
+ /* bind to local address/port */
+ if (sock->bind_local)
+ {
+#ifdef ENABLE_SOCKS
+ if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
+ socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
+ ai_family, "SOCKS", false);
+ else
+#endif
+ socket_bind (sock->sd, sock->info.lsa->bind_local,
+ ai_family,
+ "TCP/UDP", sock->info.bind_ipv6_only);
+ }
+}
- if (ai_proto == IPPROTO_UDP)
+static void
+create_socket (struct link_socket* sock, struct addrinfo* addr)
+{
+ if (addr->ai_protocol == IPPROTO_UDP)
{
- sock->sd = create_socket_udp (ai_family, sock->sockflags);
+ sock->sd = create_socket_udp (addr, sock->sockflags);
sock->sockflags |= SF_GETADDRINFO_DGRAM;
#ifdef ENABLE_SOCKS
+ /* Assume that control socket and data socket to the socks proxy
+ * are using the same IP family */
if (sock->socks_proxy)
- sock->ctrl_sd = create_socket_tcp (ai_family);
+ {
+ /* 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;
+ addr->ai_protocol = IPPROTO_TCP;
+ sock->ctrl_sd = create_socket_tcp (&addrinfo_tmp);
+ }
#endif
}
- else if (ai_proto == IPPROTO_TCP)
+ else if (addr->ai_protocol == IPPROTO_TCP)
{
- sock->sd = create_socket_tcp (ai_family);
+ sock->sd = create_socket_tcp (addr);
}
else
{
@@ -859,6 +887,8 @@ create_socket (struct link_socket *sock)
/* set socket to --mark packets with given value */
socket_set_mark (sock->sd, sock->mark);
+
+ bind_local (sock, addr->ai_family);
}
#ifdef TARGET_ANDROID
@@ -1204,21 +1234,15 @@ void set_actual_address (struct link_socket_actual* actual, struct addrinfo* ai)
else
ASSERT(0);
- /* Copy addrinfo sock parameters for socket creating */
- actual->ai_family = ai->ai_family;
- actual->ai_protocol = ai->ai_protocol;
- actual->ai_socktype = ai->ai_socktype;
}
void
-socket_connect (socket_descriptor_t *sd,
- struct link_socket_addr *lsa,
+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 ();
- const struct sockaddr *dest = &lsa->actual.dest.addr.sa;
-
int status;
#ifdef CONNECT_NONBLOCK
@@ -1346,23 +1370,6 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af)
gc_free (&gc);
}
-static void bind_local (struct link_socket *sock)
-{
- /* bind to local address/port */
- if (sock->bind_local)
- {
-#ifdef ENABLE_SOCKS
- if (sock->socks_proxy && sock->info.proto == PROTO_UDP)
- socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family, "SOCKS", false);
- else
-#endif
- socket_bind (sock->sd, sock->info.lsa->bind_local,
- sock->info.lsa->actual.ai_family,
- "TCP/UDP", sock->info.bind_ipv6_only);
- }
-}
-
static void
resolve_remote (struct link_socket *sock,
int phase,
@@ -1491,30 +1498,6 @@ link_socket_new (void)
}
void
-create_new_socket (struct link_socket* sock)
-{
- if (sock->bind_local) {
- resolve_bind_local (sock, sock->info.af);
- }
- resolve_remote (sock, 1, NULL, NULL);
-
- /*
- * In P2P or server mode we must create the socket even when resolving
- * the remote site fails/is not specified. */
-
- if (sock->info.lsa->actual.ai_family==0 && sock->bind_local)
- {
- /* Copy sock parameters from bind addr */
- set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local);
- /* clear destination set by set_actual_address */
- CLEAR(sock->info.lsa->actual.dest);
- }
-}
-
-
-
-/* bind socket if necessary */
-void
link_socket_init_phase1 (struct link_socket *sock,
const char *local_host,
const char *local_port,
@@ -1655,7 +1638,10 @@ link_socket_init_phase1 (struct link_socket *sock,
}
else if (mode != LS_MODE_TCP_ACCEPT_FROM)
{
- create_new_socket (sock);
+ if (sock->bind_local) {
+ resolve_bind_local (sock, sock->info.af);
+ }
+ resolve_remote (sock, 1, NULL, NULL);
}
}
@@ -1739,11 +1725,14 @@ linksock_print_addr (struct link_socket *sock)
msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true));
else if (sock->bind_local)
{
- /* Socket is always bound on the first matching address */
+ 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(cur->ai_family == sock->info.lsa->actual.ai_family)
+ if(!ai_family || ai_family == cur->ai_family)
break;
}
ASSERT (cur);
@@ -1812,8 +1801,9 @@ phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)
const bool proxy_retry = false;
#endif
do {
+ ASSERT (sock->info.lsa->current_remote->ai_protocol == IPPROTO_TCP);
socket_connect (&sock->sd,
- sock->info.lsa,
+ sock->info.lsa->current_remote->ai_addr,
sock->connect_timeout,
sig_info);
@@ -1848,7 +1838,7 @@ phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)
/* TODO (schwabe): This code assumes AF_INET for the proxy socket
* when retrying a connection */
openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp (AF_INET);
+ sock->sd = create_socket_tcp (sock->info.lsa->current_remote);
}
} while (proxy_retry);
@@ -1860,7 +1850,7 @@ static void
phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info)
{
socket_connect (&sock->ctrl_sd,
- sock->info.lsa,
+ sock->info.lsa->current_remote->ai_addr,
sock->connect_timeout,
sig_info);
@@ -1932,33 +1922,34 @@ link_socket_init_phase2 (struct link_socket *sock,
/* 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->info.lsa->bind_local
- && !sock->info.lsa->actual.ai_family && !sock->remote_host)
- {
- msg (M_WARN, "Could not determine IPv4/IPv6 protocol. Using %s",
- addr_family_name(sock->info.lsa->bind_local->ai_family));
- set_actual_address(&sock->info.lsa->actual, sock->info.lsa->bind_local);
-
- }
+ /* 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->info.lsa->actual.ai_family)
- {
- create_socket (sock);
- }
- else
+ if (sock->bind_local && !sock->remote_host && sock->info.lsa->bind_local)
{
- msg (M_WARN, "Could not determine IPv4/IPv6 protocol");
- sig_info->signal_received = SIGUSR1;
- goto done;
+ /* 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));
+
+ create_socket (sock, sock->info.lsa->bind_local);
}
+ }
- if (sock->bind_local)
- bind_local(sock);
+ /* 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 && sig_info->signal_received)
@@ -2798,6 +2789,7 @@ proto_remote (int proto, bool remote)
return "TCPv4_CLIENT";
ASSERT (0);
+ return ""; /* Make the compiler happy */
}
/*
@@ -2933,7 +2925,12 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock,
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");
+ }
}
+
return fromlen;
}
#endif
@@ -3000,7 +2997,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
iov.iov_len = BLEN (buf);
mesg.msg_iov = &iov;
mesg.msg_iovlen = 1;
- switch (to->ai_family)
+ switch (to->dest.addr.sa.sa_family)
{
case AF_INET:
{
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index 8d4316ba..51329534 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -91,10 +91,6 @@ struct cached_dns_entry {
struct link_socket_actual
{
/*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */
- int ai_family; /* PF_xxx */
- int ai_socktype; /* SOCK_xxx */
- int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-
struct openvpn_sockaddr dest;
#if ENABLE_IP_PKTINFO
@@ -473,7 +469,7 @@ bool ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn);
bool mac_addr_safe (const char *mac_addr);
bool ipv6_addr_safe (const char *ipv6_text_addr);
-socket_descriptor_t create_socket_tcp (int af);
+socket_descriptor_t create_socket_tcp (struct addrinfo*);
socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
struct link_socket_actual *act,