Signed-off-by: Arne Schwabe <a...@rfc2549.org>
---
 src/openvpn/socket.c |  509 ++++++++++++++++++++++++++++----------------------
 1 file changed, 282 insertions(+), 227 deletions(-)

diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 31d05eb..3a9af65 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -1316,6 +1316,23 @@ link_socket_new (void)
   return sock;
 }

+void
+create_new_socket (struct link_socket* sock, int mark)
+{
+  create_socket (sock);
+    
+  /* set socket buffers based on --sndbuf and --rcvbuf options */
+  socket_set_buffers (sock->sd, &sock->socket_buffer_sizes);
+    
+  /* set socket to --mark packets with given value */
+  socket_set_mark (sock->sd, mark);
+    
+  if(sock->bind_local)
+      resolve_bind_local (sock);
+  resolve_remote (sock, 1, NULL, NULL);
+}
+
+
 /* bind socket if necessary */
 void
 link_socket_init_phase1 (struct link_socket *sock,
@@ -1461,27 +1478,253 @@ link_socket_init_phase1 (struct link_socket *sock,
     }
   else if (mode != LS_MODE_TCP_ACCEPT_FROM)
     {
-      create_socket (sock);
+      create_new_socket (sock, mark);
+    }
+}
+
+static
+void phase2_inetd (struct link_socket* sock, const struct frame *frame,
+                   const char *remote_dynamic, volatile int *signal_received)
+{
+  bool remote_changed = false;

-      /* set socket buffers based on --sndbuf and --rcvbuf options */
-      socket_set_buffers (sock->sd, &sock->socket_buffer_sizes);
+  if (sock->info.proto == PROTO_TCP_SERVER) {
+    /* AF_INET as default (and fallback) for inetd */
+    sock->info.lsa->actual.dest.addr.sa.sa_family = AF_INET;
+#ifdef HAVE_GETSOCKNAME
+    {
+      /* inetd: hint family type for dest = local's */
+      struct openvpn_sockaddr local_addr;
+      socklen_t addrlen = sizeof(local_addr);
+      if (getsockname (sock->sd, (struct sockaddr *)&local_addr, &addrlen) == 
0) {
+        sock->info.lsa->actual.dest.addr.sa.sa_family = 
local_addr.addr.sa.sa_family;
+        dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from 
getsockname(%d)",
+              proto2ascii(sock->info.proto, 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,
+                            &remote_changed,
+                            &sock->info.lsa->local,
+                            false,
+                            sock->inetd == INETD_NOWAIT,
+                            signal_received);
+  }
+  ASSERT (!remote_changed);
+}

-      /* set socket to --mark packets with given value */
-      socket_set_mark (sock->sd, mark);
-      
-      if(sock->bind_local)
-          resolve_bind_local (sock);
-      resolve_remote (sock, 1, NULL, NULL);
+static void
+phase2_set_socket_flags (struct link_socket* sock)
+{
+  /* set misc socket parameters */
+  socket_set_flags (sock->sd, sock->sockflags);
+
+  /* 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);
+
+#ifdef ENABLE_SOCKS
+  if (socket_defined (sock->ctrl_sd))
+    set_cloexec (sock->ctrl_sd);
+#endif
+
+  /* set Path MTU discovery options on the socket */
+  set_mtu_discover_type (sock->sd, sock->mtu_discover_type);
+
+#if EXTENDED_SOCKET_ERROR_CAPABILITY
+  /* if the OS supports it, enable extended error passing on the socket */
+  set_sock_extended_error_passing (sock->sd);
+#endif
+}
+
+
+static void
+linksock_print_addr (struct link_socket *sock)
+{
+  struct gc_arena gc = gc_new ();
+
+  /* print local address */
+  {
+    const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? 
D_INIT_MEDIUM : M_INFO;
+    
+    if (sock->inetd)
+      msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, 
sock->info.af, true));
+    else
+      msg (msglevel, "%s link local%s: %s",
+           proto2ascii (sock->info.proto, sock->info.af, true),
+           (sock->bind_local ? " (bound)" : ""),
+           print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? 
PS_SHOW_PORT : 0, &gc));
+    
+    /* 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, bool *remote_changed,
+                   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,
+                                       remote_changed,
+                                       &sock->info.lsa->local,
+                                       true,
+                                       false,
+                                       signal_received);
+      break;
+    case LS_MODE_TCP_LISTEN:
+      socket_do_listen (sock->sd,
+                        &sock->info.lsa->local,
+                        true,
+                        false);
+      break;
+    case LS_MODE_TCP_ACCEPT_FROM:
+      sock->sd = socket_do_accept (sock->sd,
+                                   &sock->info.lsa->actual,
+                                   false);
+      if (!socket_defined (sock->sd))
+        {
+          *signal_received = SIGTERM;
+          return;
+        }
+      tcp_connection_established (&sock->info.lsa->actual);
+      break;
+    default:
+      ASSERT (0);
     }
+
 }

+
+static void
+phase2_tcp_client (struct link_socket *sock, bool *remote_changed,
+                   const char *remote_dynamic, volatile int *signal_received)
+{
+#ifdef GENERAL_PROXY_SUPPORT
+    bool proxy_retry = false;
+#else
+    const bool proxy_retry = false;
+#endif
+    do {
+        socket_connect (&sock->sd,
+                        &sock->info.lsa->local,
+                        sock->bind_local,
+                        &sock->info.lsa->actual.dest,
+                        sock->connection_profiles_defined,
+                        remote_dynamic,
+                        remote_changed,
+                        sock->connect_retry_seconds,
+                        sock->connect_timeout,
+                        sock->connect_retry_max,
+                        sock->sockflags,
+                        signal_received);
+        
+        if (*signal_received)
+            return;
+        
+        if (false)
+            ;
+#ifdef ENABLE_HTTP_PROXY
+        else if (sock->http_proxy)
+            {
+                proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
+                                                             sock->sd,
+                                                             
sock->proxy_dest_host,
+                                                             
sock->proxy_dest_port,
+                                                             
&sock->stream_buf.residual,
+                                                             signal_received);
+            }
+#endif
+#ifdef ENABLE_SOCKS
+        else if (sock->socks_proxy)
+            {
+                establish_socks_proxy_passthru (sock->socks_proxy,
+                                                sock->sd,
+                                                sock->proxy_dest_host,
+                                                sock->proxy_dest_port,
+                                                signal_received);
+            }
+#endif
+        if (proxy_retry)
+            {
+                openvpn_close_socket (sock->sd);
+                sock->sd = create_socket_tcp (AF_INET);
+            }
+    } while (proxy_retry);
+
+}
+
+#ifdef ENABLE_SOCKS
+static void
+phase2_socks_client (struct link_socket *sock, bool *remote_changed,
+                      const char *remote_dynamic, volatile int 
*signal_received)
+{
+    socket_connect (&sock->ctrl_sd,
+                    &sock->info.lsa->local,
+                    sock->bind_local,
+                    &sock->info.lsa->actual.dest,
+                    sock->connection_profiles_defined,
+                    remote_dynamic,
+                    remote_changed,
+                    sock->connect_retry_seconds,
+                    sock->connect_timeout,
+                    sock->connect_retry_max,
+                    sock->sockflags,
+                    signal_received);
+    
+    if (*signal_received)
+        return;
+    
+    establish_socks_proxy_udpassoc (sock->socks_proxy,
+                                    sock->ctrl_sd,
+                                    sock->sd,
+                                    &sock->socks_relay.dest,
+                                    signal_received);
+    
+    if (*signal_received)
+        return;
+    
+    sock->remote_host = sock->proxy_dest_host;
+    sock->remote_port = sock->proxy_dest_port;
+    sock->did_resolve_remote = false;
+    
+    addr_zero_host(&sock->info.lsa->actual.dest);
+    addr_zero_host(&sock->info.lsa->remote);
+    
+    resolve_remote (sock, 1, NULL, signal_received);
+    
+}
+#endif
+
 /* finalize socket initialization */
 void
 link_socket_init_phase2 (struct link_socket *sock,
-                        const struct frame *frame,
-                        volatile int *signal_received)
+                         const struct frame *frame,
+                         volatile int *signal_received)
 {
-  struct gc_arena gc = gc_new ();
   const char *remote_dynamic = NULL;
   bool remote_changed = false;
   int sig_save = 0;
@@ -1508,243 +1751,55 @@ link_socket_init_phase2 (struct link_socket *sock,
   /* were we started by inetd or xinetd? */
   if (sock->inetd)
     {
-      if (sock->info.proto == PROTO_TCP_SERVER) {
-       /* AF_INET as default (and fallback) for inetd */
-       sock->info.lsa->actual.dest.addr.sa.sa_family = AF_INET;
-#ifdef HAVE_GETSOCKNAME
-         {
-           /* inetd: hint family type for dest = local's */
-           struct openvpn_sockaddr local_addr;
-           socklen_t addrlen = sizeof(local_addr);
-           if (getsockname (sock->sd, (struct sockaddr *)&local_addr, 
&addrlen) == 0) {
-             sock->info.lsa->actual.dest.addr.sa.sa_family = 
local_addr.addr.sa.sa_family;
-             dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from 
getsockname(%d)",
-                   proto2ascii(sock->info.proto, 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,
-                               &remote_changed,
-                               &sock->info.lsa->local,
-                               false,
-                               sock->inetd == INETD_NOWAIT,
-                               signal_received);
-      }
-      ASSERT (!remote_changed);
+      phase2_inetd (sock, frame, remote_dynamic, signal_received);
       if (*signal_received)
-       goto done;
+        goto done;
+
     }
   else
     {
       resolve_remote (sock, 2, &remote_dynamic, signal_received);

       if (*signal_received)
-       goto done;
+        goto done;

-      /* TCP client/server */
       if (sock->info.proto == PROTO_TCP_SERVER)
-       {
-         switch (sock->mode)
-           {
-           case LS_MODE_DEFAULT:
-             sock->sd = socket_listen_accept (sock->sd,
-                                              &sock->info.lsa->actual,
-                                              remote_dynamic,
-                                              &remote_changed,
-                                              &sock->info.lsa->local,
-                                              true,
-                                              false,
-                                              signal_received);
-             break;
-           case LS_MODE_TCP_LISTEN:
-             socket_do_listen (sock->sd,
-                               &sock->info.lsa->local,
-                               true,
-                               false);
-             break;
-           case LS_MODE_TCP_ACCEPT_FROM:
-             sock->sd = socket_do_accept (sock->sd,
-                                          &sock->info.lsa->actual,
-                                          false);
-             if (!socket_defined (sock->sd))
-               {
-                 *signal_received = SIGTERM;
-                 goto done;
-               }
-             tcp_connection_established (&sock->info.lsa->actual);
-             break;
-           default:
-             ASSERT (0);
-           }
-       }
+        {
+          phase2_tcp_server(sock, &remote_changed, remote_dynamic,
+                            signal_received);
+        }
       else if (sock->info.proto == PROTO_TCP_CLIENT)
-       {
-
-#ifdef GENERAL_PROXY_SUPPORT
-         bool proxy_retry = false;
-#else
-         const bool proxy_retry = false;
-#endif
-         do {
-           socket_connect (&sock->sd,
-                           &sock->info.lsa->local,
-                           sock->bind_local,
-                           &sock->info.lsa->actual.dest,
-                           sock->connection_profiles_defined,
-                           remote_dynamic,
-                           &remote_changed,
-                           sock->connect_retry_seconds,
-                           sock->connect_timeout,
-                           sock->connect_retry_max,
-                           sock->sockflags,
-                           signal_received);
-
-           if (*signal_received)
-             goto done;
-
-           if (false)
-             ;
-#ifdef ENABLE_HTTP_PROXY
-           else if (sock->http_proxy)
-             {
-               proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
-                                                            sock->sd,
-                                                            
sock->proxy_dest_host,
-                                                            
sock->proxy_dest_port,
-                                                            
&sock->stream_buf.residual,
-                                                            signal_received);
-             }
-#endif
-#ifdef ENABLE_SOCKS
-           else if (sock->socks_proxy)
-             {
-               establish_socks_proxy_passthru (sock->socks_proxy,
-                                               sock->sd,
-                                               sock->proxy_dest_host,
-                                               sock->proxy_dest_port,
-                                               signal_received);
-             }
-#endif
-           if (proxy_retry)
-             {
-               openvpn_close_socket (sock->sd);
-               sock->sd = create_socket_tcp (AF_INET);
-             }
-         } while (proxy_retry);
-       }
+        {
+          phase2_tcp_client(sock, &remote_changed, remote_dynamic,
+                            signal_received);
+    
+        }
 #ifdef ENABLE_SOCKS
       else if (sock->info.proto == PROTO_UDP && sock->socks_proxy && 
sock->info.af == AF_INET)
-       {
-         socket_connect (&sock->ctrl_sd,
-                          &sock->info.lsa->local,
-                          sock->bind_local,
-                         &sock->info.lsa->actual.dest,
-                         sock->connection_profiles_defined,
-                         remote_dynamic,
-                         &remote_changed,
-                         sock->connect_retry_seconds,
-                         sock->connect_timeout,
-                         sock->connect_retry_max,
-                         sock->sockflags,
-                         signal_received);
-
-         if (*signal_received)
-           goto done;
-
-         establish_socks_proxy_udpassoc (sock->socks_proxy,
-                                         sock->ctrl_sd,
-                                         sock->sd,
-                                         &sock->socks_relay.dest,
-                                         signal_received);
-
-         if (*signal_received)
-           goto done;
-
-         sock->remote_host = sock->proxy_dest_host;
-         sock->remote_port = sock->proxy_dest_port;
-         sock->did_resolve_remote = false;
-
-         addr_zero_host(&sock->info.lsa->actual.dest);
-         addr_zero_host(&sock->info.lsa->remote);
-
-         resolve_remote (sock, 1, NULL, signal_received);
-
-         if (*signal_received)
-           goto done;
-       }
+        {
+          phase2_socks_client(sock, &remote_changed, remote_dynamic,
+                              signal_received);
 #endif
-
+        }
       if (*signal_received)
-       goto done;
-
+        goto done;
+    
       if (remote_changed)
-       {
-         msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP 
connection establishment");
-         addr_copy_host(&sock->info.lsa->remote, &sock->info.lsa->actual.dest);
-       }
+        {
+          msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP 
connection establishment");
+          addr_copy_host(&sock->info.lsa->remote, 
&sock->info.lsa->actual.dest);
+        }
     }

-  /* set misc socket parameters */
-  socket_set_flags (sock->sd, sock->sockflags);
-
-  /* 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);
-
-#ifdef ENABLE_SOCKS
-  if (socket_defined (sock->ctrl_sd))
-    set_cloexec (sock->ctrl_sd);
-#endif
-
-  /* set Path MTU discovery options on the socket */
-  set_mtu_discover_type (sock->sd, sock->mtu_discover_type);
-
-#if EXTENDED_SOCKET_ERROR_CAPABILITY
-  /* if the OS supports it, enable extended error passing on the socket */
-  set_sock_extended_error_passing (sock->sd);
-#endif
-
-  /* print local address */
-  {
-    const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? 
D_INIT_MEDIUM : M_INFO;
-
-    if (sock->inetd)
-      msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, 
sock->info.af, true));
-    else
-      msg (msglevel, "%s link local%s: %s",
-          proto2ascii (sock->info.proto, sock->info.af, true),
-          (sock->bind_local ? " (bound)" : ""),
-          print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? 
PS_SHOW_PORT : 0, &gc));
-
-    /* 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));
-  }
-
+  phase2_set_socket_flags(sock);
+  linksock_print_addr(sock);
+ 
  done:
   if (sig_save && signal_received)
     {
       if (!*signal_received)
-       *signal_received = sig_save;
+        *signal_received = sig_save;
     }
-  gc_free (&gc);
 }

 void
-- 
1.7.9.5


Reply via email to