Attention is currently required from: plaisthos.

Hello plaisthos,

I'd like you to do a code review.
Please visit

    http://gerrit.openvpn.net/c/openvpn/+/1769?usp=email

to review the following change.


Change subject: socket: adopt a pre-created UDP socket for a client connection
......................................................................

socket: adopt a pre-created UDP socket for a client connection

Add LS_MODE_UDP_ADOPT: a client link_socket can take ownership of an
already-bound UDP socket handed off via c2.oob_probe_adopt/oob_probe_sd
instead of creating its own, and pins c2.oob_probe_remote as the outgoing
address. This lets the OOB server-probe socket become the connection socket,
so the source IP+port and destination match what the server's handshake
cookie is bound to.

  - link_socket_init_phase1: adopt the fd, inherit the address family, skip the
    local bind, and pre-set lsa->actual (resolve_remote preserves an already-
    defined actual)
  - link_socket_init_phase2: skip create_socket() so the adopted fd is not
    clobbered (overlapped-I/O init is fd-independent, so Windows is fine)
  - do_init_socket_phase1: select the mode for the single client socket

Dormant until the client sets oob_probe_adopt (next commit).

Change-Id: Iec384ee6844ab278b280d6eafec8aaecf9dde755
Signed-off-by: Lev Stipakov <[email protected]>
---
M src/openvpn/init.c
M src/openvpn/openvpn.h
M src/openvpn/socket.c
M src/openvpn/socket.h
4 files changed, 65 insertions(+), 2 deletions(-)



  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/69/1769/1

diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index e0d6a14..8eca6f7 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -3820,6 +3820,12 @@
                 mode = LS_MODE_TCP_ACCEPT_FROM;
             }
         }
+        /* adopt the OOB server-probe socket as this client's connection socket
+         * (handshake shortcut); only the single client socket is ever adopted 
*/
+        else if (c->c2.oob_probe_adopt && i == 0)
+        {
+            mode = LS_MODE_UDP_ADOPT;
+        }

         /* init each socket with its specific args */
         link_socket_init_phase1(c, i, mode);
@@ -3985,6 +3991,16 @@
 static void
 do_close_link_socket(struct context *c)
 {
+    /* An OOB probe socket handed off for the handshake shortcut is adopted by 
the
+     * link socket in link_socket_init_phase1() (which clears oob_probe_sd). 
If the
+     * connection attempt aborted before that, the fd is still owned here; 
close it
+     * so it is not leaked when context_clear_2() zeroes c2. */
+    if (c->c2.oob_probe_sd != SOCKET_UNDEFINED)
+    {
+        openvpn_close_socket(c->c2.oob_probe_sd);
+        c->c2.oob_probe_sd = SOCKET_UNDEFINED;
+    }
+
     if (c->c2.link_sockets && c->c2.link_socket_owned)
     {
         for (int i = 0; i < c->c1.link_sockets_num; i++)
diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h
index fa00822..e5a1d76 100644
--- a/src/openvpn/openvpn.h
+++ b/src/openvpn/openvpn.h
@@ -239,7 +239,16 @@

     bool link_socket_owned;

-    const struct link_socket *accept_from;   /* possibly do accept() on a 
parent link_socket */
+    const struct link_socket *accept_from; /* possibly do accept() on a parent 
link_socket */
+
+    /* OOB server-probe handshake shortcut: when oob_probe_adopt is true, the
+     * connection adopts oob_probe_sd (the winning remote's already-bound probe
+     * socket) instead of creating one, and pins oob_probe_remote (the exact
+     * address probed) as the outgoing address, so the source IP+port and the
+     * destination match what the server's handshake cookie is bound to. */
+    bool oob_probe_adopt;
+    socket_descriptor_t oob_probe_sd;
+    struct openvpn_sockaddr oob_probe_remote;

     struct link_socket_actual *to_link_addr; /* IP address of remote */
     struct link_socket_actual from;          /* address of incoming datagram */
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index df2cc9e..a9dca0a 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -1428,6 +1428,41 @@
         /* inherit (possibly guessed) info AF from parent context */
         sock->info.af = c->c2.accept_from->info.af;
     }
+    else if (mode == LS_MODE_UDP_ADOPT)
+    {
+        /* Adopt the OOB probe socket: same source IP+port the server's cookie 
is
+         * bound to. It is already bound, so do not bind again. */
+        ASSERT(c->c2.oob_probe_sd != SOCKET_UNDEFINED);
+        sock->sd = c->c2.oob_probe_sd;
+        c->c2.oob_probe_sd = SOCKET_UNDEFINED; /* ownership moves to the link 
socket */
+        sock->info.af = c->c2.oob_probe_remote.addr.sa.sa_family;
+        sock->bind_local = false;
+
+        /* The probe socket was created plainly, so apply the same options
+         * create_socket() would (it is already bound, so no bind here).
+         * --multihome's IP_PKTINFO never applies to a probing client, so it is
+         * intentionally not set. */
+        sock->sockflags |= SF_GETADDRINFO_DGRAM;
+        socket_set_buffers(sock->sd, &sock->socket_buffer_sizes, true);
+        socket_set_mark(sock->sd, sock->mark);
+#if defined(TARGET_LINUX)
+        if (sock->bind_dev)
+        {
+            msg(M_INFO, "Using bind-dev %s", sock->bind_dev);
+            if (setsockopt(sock->sd, SOL_SOCKET, SO_BINDTODEVICE, 
sock->bind_dev,
+                           strlen(sock->bind_dev) + 1)
+                != 0)
+            {
+                msg(M_WARN | M_ERRNO, "WARN: setsockopt SO_BINDTODEVICE=%s 
failed", sock->bind_dev);
+            }
+        }
+#endif
+
+        /* Pin the exact address we probed so the connection targets the 
address
+         * the cookie was minted for; resolve_remote() preserves a defined 
actual. */
+        CLEAR(sock->info.lsa->actual);
+        sock->info.lsa->actual.dest = c->c2.oob_probe_remote;
+    }

     /* are we running in HTTP proxy mode? */
     if (sock->http_proxy)
@@ -1720,7 +1755,7 @@
         goto done;
     }
 #endif
-    if (sock->info.lsa->current_remote)
+    if (sock->mode != LS_MODE_UDP_ADOPT && sock->info.lsa->current_remote)
     {
         create_socket(sock, sock->info.lsa->current_remote);
     }
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index cd4e8ed..d807f36 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -197,6 +197,9 @@
 #define LS_MODE_DEFAULT         0
 #define LS_MODE_TCP_LISTEN      1
 #define LS_MODE_TCP_ACCEPT_FROM 2
+/* Adopt a pre-created, already-bound UDP socket (from the OOB server probe) as
+ * the connection socket, instead of creating one. */
+#define LS_MODE_UDP_ADOPT       3
     int mode;

     int resolve_retry_seconds;

--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1769?usp=email
To unsubscribe, or for help writing mail filters, visit 
http://gerrit.openvpn.net/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: Iec384ee6844ab278b280d6eafec8aaecf9dde755
Gerrit-Change-Number: 1769
Gerrit-PatchSet: 1
Gerrit-Owner: stipa <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to