summaryrefslogtreecommitdiffstats
path: root/src/openvpn/socket.c
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2014-03-21 14:18:43 +0100
committerGert Doering <gert@greenie.muc.de>2014-03-26 14:18:02 +0100
commit7dbe04de74ea01bd77461ec82253dd769381c711 (patch)
tree3161c577d11fef64a88f3a7ffb101a4a26eaee4c /src/openvpn/socket.c
parente9b088b20847905ed2c2b85a12be58f457c10d06 (diff)
downloadopenvpn-7dbe04de74ea01bd77461ec82253dd769381c711.tar.gz
openvpn-7dbe04de74ea01bd77461ec82253dd769381c711.tar.xz
openvpn-7dbe04de74ea01bd77461ec82253dd769381c711.zip
Clean up of socket code.
Let socket_create take struct addrinfo as argument and use the entries of addrinfo to create the socket. Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <1395407925-25518-11-git-send-email-arne@rfc2549.org> URL: http://article.gmane.org/gmane.network.openvpn.devel/8370 Signed-off-by: Gert Doering <gert@greenie.muc.de>
Diffstat (limited to 'src/openvpn/socket.c')
-rw-r--r--src/openvpn/socket.c188
1 files changed, 92 insertions, 96 deletions
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 21aeac2..b769171 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -769,11 +769,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! */
@@ -790,17 +794,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,
@@ -814,7 +822,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,
@@ -830,28 +838,49 @@ 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;
+ addrinfo_tmp.ai_socktype = SOCK_STREAM;
+ addrinfo_tmp.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
{
@@ -862,6 +891,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
@@ -1207,21 +1238,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
@@ -1349,23 +1374,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,
@@ -1494,30 +1502,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,
@@ -1658,7 +1642,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);
}
}
@@ -1742,11 +1729,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);
@@ -1815,8 +1805,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,10 +1839,8 @@ phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info)
#endif
if (proxy_retry)
{
- /* TODO (schwabe): This code assumes AF_INET for the proxy socket
- * when retrying a connection */
openvpn_close_socket (sock->sd);
- sock->sd = create_socket_tcp (AF_INET);
+ sock->sd = create_socket_tcp (sock->info.lsa->current_remote);
}
} while (proxy_retry);
@@ -1863,7 +1852,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);
@@ -1935,33 +1924,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)
@@ -2801,6 +2791,7 @@ proto_remote (int proto, bool remote)
return "TCPv4_CLIENT";
ASSERT (0);
+ return ""; /* Make the compiler happy */
}
/*
@@ -2936,7 +2927,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 (cmsg_level=%d, cmsg_type=%d, cmsg=len=%d)", (int)cmsg->cmsg_level, (int)cmsg->cmsg_type, (int)cmsg->cmsg_len );
+ }
}
+
return fromlen;
}
#endif
@@ -3003,7 +2999,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:
{