[PATCH v6 08/10] server: Ensure datagram sockets are bound in send_socket.

Jinoh Kang jinoh.kang.kr at gmail.com
Sat Mar 12 01:40:47 CST 2022


If the type of the socket is SOCK_DGRAM, it shall always be bound to an
address if we ever attempt to send datagrams through the socket, whether
the attempt succeeds or not.

Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---

Notes:
    v4 -> v5: new patch
    v5 -> v6: no changes

 server/sock.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/server/sock.c b/server/sock.c
index 9170f8fe352..2091384e4a4 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -471,6 +471,32 @@ static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrl
     }
 }
 
+static socklen_t get_unix_sockaddr_any( union unix_sockaddr *uaddr, int ws_family )
+{
+    memset( uaddr, 0, sizeof(*uaddr) );
+    switch (ws_family)
+    {
+        case WS_AF_INET:
+            uaddr->in.sin_family = AF_INET;
+            return sizeof(uaddr->in);
+        case WS_AF_INET6:
+            uaddr->in6.sin6_family = AF_INET6;
+            return sizeof(uaddr->in6);
+#ifdef HAS_IPX
+        case WS_AF_IPX:
+            uaddr->ipx.sipx_family = AF_IPX;
+            return sizeof(uaddr->ipx);
+#endif
+#ifdef HAS_IRDA
+        case WS_AF_IRDA:
+            uaddr->irda.sir_family = AF_IRDA;
+            return sizeof(uaddr->irda);
+#endif
+        default:
+            return 0;
+    }
+}
+
 /* some events are generated at the same time but must be sent in a particular
  * order (e.g. CONNECT must be sent before READ) */
 static const enum afd_poll_bit event_bitorder[] =
@@ -3491,15 +3517,24 @@ DECL_HANDLER(send_socket)
     if (!sock) return;
     fd = sock->fd;
 
-    if (sock->type == WS_SOCK_DGRAM)
+    if (sock->type == WS_SOCK_DGRAM && !sock->bound)
     {
-        /* sendto() and sendmsg() implicitly binds a socket */
         union unix_sockaddr unix_addr;
-        socklen_t unix_len = sizeof(unix_addr);
+        socklen_t unix_len;
+        int bind_errno = 0;
+        int unix_fd = get_unix_fd( fd );
 
-        if (!sock->bound && !getsockname( get_unix_fd( fd ), &unix_addr.addr, &unix_len ))
+        unix_len = get_unix_sockaddr_any( &unix_addr, sock->family );
+        if (bind( unix_fd, &unix_addr.addr, unix_len ) < 0)
+            bind_errno = errno;
+
+        if (getsockname( unix_fd, &unix_addr.addr, &unix_len ) >= 0)
+        {
             sock->addr_len = sockaddr_from_unix( &unix_addr, &sock->addr.addr, sizeof(sock->addr) );
-        sock->bound = 1;
+            sock->bound = 1;
+        }
+        else if (status == STATUS_PENDING || status == STATUS_DEVICE_NOT_READY)
+            status = sock_get_ntstatus( bind_errno ? bind_errno : errno );
     }
 
     /* If we had a short write and the socket is nonblocking (and the client is
-- 
2.34.1




More information about the wine-devel mailing list