Let socket_create take struct addrinfo as argument and use the entries of 
addrinfo to create the socket.
---
 src/openvpn/manage.c |   6 +-
 src/openvpn/socket.c | 187 +++++++++++++++++++++++++--------------------------
 src/openvpn/socket.h |   6 +-
 3 files changed, 95 insertions(+), 104 deletions(-)

diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 0cc185b..f5b3ad5 100644
--- a/src/openvpn/manage.c
+++ b/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/src/openvpn/socket.c b/src/openvpn/socket.c
index 97f6756..f024c0a 100644
--- a/src/openvpn/socket.c
+++ b/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);

@@ -1845,10 +1835,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);
@@ -1860,7 +1848,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 +1920,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 +2787,7 @@ proto_remote (int proto, bool remote)
        return "TCPv4_CLIENT";

   ASSERT (0);
+  return ""; /* Make the compiler happy */
 }

 /*
@@ -2933,7 +2923,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 +2995,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/src/openvpn/socket.h b/src/openvpn/socket.h
index 8d4316b..5132953 100644
--- a/src/openvpn/socket.h
+++ b/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,
-- 
1.8.5.2 (Apple Git-48)


Reply via email to