Windows 10 [received support](https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) for AF_UNIX sockets in Insider Build 17063. This merge request adds basic support for AF_UNIX sockets to ws2_32 and wineserver.
Of particular note is the difficulty in handling `sun_path`. Most of the functions that allow for translating Windows paths to Unix paths are not accessible from ws2_32. I considered the following options: * Pass the Windows path to wineserver and do the conversion there. * This is, as far as I can tell, not possible without major rearchitecting. wineserver does not have functions to translate Windows paths to Unix paths, for obvious reasons. * Obtain the current working directory of the requesting process and temporarily change directories to there. * This only handles relative paths and fails for absolute paths, UNC paths, etc. * Conditionally change directories based on whether the path is relative or not. * This is error-prone and wineserver does not have the requisite functions to do this cleanly.
I ultimately decided to pass the translated Unix path to wineserver, which changes directories to `dirname(path)`. It then provides `bind` and `connect` with `basename(path)`. This is not threadsafe, but wineserver is not (currently) multithreaded.
Abstract sockets are supported by this patch.
-- v4: ws2_32/tests: Add test for AF_UNIX sockets. server: Introduce error when attempting to connect() to abstract AF_UNIX sockets. ws2_32: Fix pointer arithmetic error in bind(). server: Fix pointer arithmetic error in sock_ioctl(). server: Allow for deletion of socket files. ws2_32: Add support for AF_UNIX sockets. ntdll/unix: Add support for AF_UNIX sockets to multiple functions. ws2_32: Add afunix.h header.
From: Ally Sommers dropbear.sh@gmail.com
This header is needed for support of AF_UNIX sockets. --- include/Makefile.in | 1 + include/afunix.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 include/afunix.h
diff --git a/include/Makefile.in b/include/Makefile.in index 0dae4cab2bf..03493e7dd5c 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -11,6 +11,7 @@ SOURCES = \ adshlp.h \ advpub.h \ af_irda.h \ + afunix.h \ amaudio.h \ amsi.idl \ amstream.idl \ diff --git a/include/afunix.h b/include/afunix.h new file mode 100644 index 00000000000..8118dda271b --- /dev/null +++ b/include/afunix.h @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Ally Sommers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _WS2AFUNIX_ +#define _WS2AFUNIX_ + +#include "windef.h" +#include "ws2def.h" + +#ifdef USE_WS_PREFIX +# define WS(x) WS_##x +#else +# define WS(x) x +#endif + +#define UNIX_PATH_MAX 108 + +typedef struct WS(sockaddr_un) { + USHORT sun_family; + char sun_path[UNIX_PATH_MAX]; +} SOCKADDR_UN, *PSOCKADDR_UN; + +#endif /* _WS2AFUNIX_ */ \ No newline at end of file
From: Ally Sommers dropbear.sh@gmail.com
--- dlls/ntdll/unix/socket.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 4e706323a0a..2f8733c7592 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -66,6 +66,8 @@ # define HAS_IRDA #endif
+#include <sys/un.h> + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -77,6 +79,7 @@ #include "ws2tcpip.h" #include "wsipx.h" #include "af_irda.h" +#include "afunix.h" #include "wine/afd.h"
#include "unix_private.h" @@ -105,6 +108,7 @@ union unix_sockaddr #ifdef HAS_IRDA struct sockaddr_irda irda; #endif + struct sockaddr_un un; };
struct async_recv_ioctl @@ -289,6 +293,17 @@ static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrl return sizeof(uaddr->in6); }
+ case WS_AF_UNIX: + { + struct WS_sockaddr_un win = {0}; + + if (wsaddrlen < sizeof(win)) return 0; + memcpy( &win, wsaddr, sizeof(win) ); + uaddr->un.sun_family = AF_UNIX; + memcpy( uaddr->un.sun_path, win.sun_path, sizeof(win.sun_path) ); + return sizeof(uaddr->un); + } + default: FIXME( "unknown address family %u\n", wsaddr->sa_family ); return 0; @@ -361,6 +376,17 @@ static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_socka } #endif
+ case AF_UNIX: + { + struct WS_sockaddr_un win = {0}; + + if (wsaddrlen < sizeof(win)) return -1; + win.sun_family = WS_AF_UNIX; + memcpy( win.sun_path, uaddr->un.sun_path, sizeof(win.sun_path) ); + memcpy( wsaddr, &win, sizeof(win) ); + return sizeof(win); + } + case AF_UNSPEC: return 0;
From: Ally Sommers dropbear.sh@gmail.com
This commit additionally modifies wineserver's sock_ioctl to handle the provided pathname by changing directories and then returning after the native call. This is NOT threadsafe, but wineserver is not multithreaded. --- dlls/ws2_32/socket.c | 49 +++++++++++++++++++++++--- dlls/ws2_32/ws2_32_private.h | 14 ++++++++ server/sock.c | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 5 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 5eb926a408b..026bb029328 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -226,6 +226,11 @@ const char *debugstr_sockaddr( const struct sockaddr *a ) addr, ((const SOCKADDR_IRDA *)a)->irdaServiceName); } + case AF_UNIX: + { + return wine_dbg_sprintf("{ family AF_UNIX, path %s }", + ((const SOCKADDR_UN *)a)->sun_path); + } default: return wine_dbg_sprintf("{ family %d }", a->sa_family); } @@ -1106,6 +1111,9 @@ int WINAPI bind( SOCKET s, const struct sockaddr *addr, int len ) HANDLE sync_event; NTSTATUS status;
+ char *unix_path = NULL; + int unix_path_len = 0; + TRACE( "socket %#Ix, addr %s\n", s, debugstr_sockaddr(addr) );
if (!addr) @@ -1148,6 +1156,14 @@ int WINAPI bind( SOCKET s, const struct sockaddr *addr, int len ) } break;
+ case AF_UNIX: + if (len < sizeof(struct sockaddr_un)) + { + SetLastError( WSAEFAULT ); + return -1; + } + break; + default: FIXME( "unknown protocol %u\n", addr->sa_family ); SetLastError( WSAEAFNOSUPPORT ); @@ -1156,8 +1172,16 @@ int WINAPI bind( SOCKET s, const struct sockaddr *addr, int len )
if (!(sync_event = get_sync_event())) return -1;
- params = malloc( sizeof(int) + len ); - ret_addr = malloc( len ); + if (addr->sa_family == AF_UNIX && *addr->sa_data) + { + WCHAR *sun_pathW = strdupAtoW(addr->sa_data); + unix_path = wine_get_unix_file_name(sun_pathW); + unix_path_len = strlen(unix_path) + 1; + free(sun_pathW); + } + + params = malloc( sizeof(int) + len + unix_path_len ); + ret_addr = malloc( len + unix_path_len ); if (!params || !ret_addr) { free( params ); @@ -1167,9 +1191,11 @@ int WINAPI bind( SOCKET s, const struct sockaddr *addr, int len ) } params->unknown = 0; memcpy( ¶ms->addr, addr, len ); + if (unix_path) + memcpy( params + 1, unix_path, unix_path_len );
status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_BIND, - params, sizeof(int) + len, ret_addr, len ); + params, sizeof(int) + len + unix_path_len, ret_addr, len + unix_path_len ); if (status == STATUS_PENDING) { if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) @@ -1222,11 +1248,22 @@ int WINAPI connect( SOCKET s, const struct sockaddr *addr, int len ) HANDLE sync_event; NTSTATUS status;
+ char *unix_path = NULL; + int unix_path_len = 0; + TRACE( "socket %#Ix, addr %s, len %d\n", s, debugstr_sockaddr(addr), len );
if (!(sync_event = get_sync_event())) return -1;
- if (!(params = malloc( sizeof(*params) + len ))) + if (addr->sa_family == AF_UNIX && *addr->sa_data) + { + WCHAR *sun_pathW = strdupAtoW(addr->sa_data); + unix_path = wine_get_unix_file_name(sun_pathW); + unix_path_len = strlen(unix_path) + 1; + free(sun_pathW); + } + + if (!(params = malloc( sizeof(*params) + len + unix_path_len ))) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return -1; @@ -1234,9 +1271,11 @@ int WINAPI connect( SOCKET s, const struct sockaddr *addr, int len ) params->addr_len = len; params->synchronous = TRUE; memcpy( params + 1, addr, len ); + if (unix_path_len) + memcpy( (char *)(params + 1) + len, unix_path, unix_path_len );
status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_WINE_CONNECT, - params, sizeof(*params) + len, NULL, 0 ); + params, sizeof(*params) + len + unix_path_len, NULL, 0 ); free( params ); if (status == STATUS_PENDING) { diff --git a/dlls/ws2_32/ws2_32_private.h b/dlls/ws2_32/ws2_32_private.h index 41d9e512488..0ded6a87efb 100644 --- a/dlls/ws2_32/ws2_32_private.h +++ b/dlls/ws2_32/ws2_32_private.h @@ -46,6 +46,7 @@ #include "mstcpip.h" #include "af_irda.h" #include "winnt.h" +#include "afunix.h" #define USE_WC_PREFIX /* For CMSG_DATA */ #include "iphlpapi.h" #include "ip2string.h" @@ -73,6 +74,19 @@ static inline char *strdupWtoA( const WCHAR *str ) return ret; }
+static inline WCHAR *strdupAtoW( const char *str ) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, NULL, 0); + if ((ret = malloc( len ))) + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, ret, len); + } + return ret; +} + + static const char magic_loopback_addr[] = {127, 12, 34, 56};
const char *debugstr_sockaddr( const struct sockaddr *addr ) DECLSPEC_HIDDEN; diff --git a/server/sock.c b/server/sock.c index 088e6d63079..25e72b003c1 100644 --- a/server/sock.c +++ b/server/sock.c @@ -53,6 +53,7 @@ #include <time.h> #include <unistd.h> #include <limits.h> +#include <libgen.h> #ifdef HAVE_LINUX_FILTER_H # include <linux/filter.h> #endif @@ -83,6 +84,8 @@ # define HAS_IRDA #endif
+#include <sys/un.h> + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -93,6 +96,7 @@ #include "ws2tcpip.h" #include "wsipx.h" #include "af_irda.h" +#include "afunix.h" #include "wine/afd.h" #include "wine/rbtree.h"
@@ -116,6 +120,7 @@ union win_sockaddr struct WS_sockaddr_in6 in6; struct WS_sockaddr_ipx ipx; SOCKADDR_IRDA irda; + struct WS_sockaddr_un un; };
union unix_sockaddr @@ -129,6 +134,7 @@ union unix_sockaddr #ifdef HAS_IRDA struct sockaddr_irda irda; #endif + struct sockaddr_un un; };
static struct list poll_list = LIST_INIT( poll_list ); @@ -546,6 +552,17 @@ static int sockaddr_from_unix( const union unix_sockaddr *uaddr, struct WS_socka } #endif
+ case AF_UNIX: + { + struct WS_sockaddr_un win = {0}; + + if (wsaddrlen < sizeof(win)) return -1; + win.sun_family = WS_AF_UNIX; + memcpy( win.sun_path, uaddr->un.sun_path, sizeof(win.sun_path) ); + memcpy( wsaddr, &win, sizeof(win) ); + return sizeof(win); + } + case AF_UNSPEC: return 0;
@@ -646,6 +663,17 @@ static socklen_t sockaddr_to_unix( const struct WS_sockaddr *wsaddr, int wsaddrl return sizeof(uaddr->in6); }
+ case WS_AF_UNIX: + { + struct WS_sockaddr_un win = {0}; + + if (wsaddrlen < sizeof(win)) return 0; + memcpy( &win, wsaddr, sizeof(win) ); + uaddr->un.sun_family = AF_UNIX; + memcpy( uaddr->un.sun_path, win.sun_path, sizeof(win.sun_path) ); + return sizeof(uaddr->un); + } + default: return 0; } @@ -672,6 +700,9 @@ static socklen_t get_unix_sockaddr_any( union unix_sockaddr *uaddr, int ws_famil uaddr->irda.sir_family = AF_IRDA; return sizeof(uaddr->irda); #endif + case WS_AF_UNIX: + uaddr->un.sun_family = AF_UNIX; + return sizeof(uaddr->un); default: return 0; } @@ -1757,6 +1788,7 @@ static int get_unix_family( int family ) #ifdef AF_IRDA case WS_AF_IRDA: return AF_IRDA; #endif + case WS_AF_UNIX: return AF_UNIX; case WS_AF_UNSPEC: return AF_UNSPEC; default: return -1; } @@ -2607,6 +2639,19 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) if (unix_addr.addr.sa_family == AF_INET && !memcmp( &unix_addr.in.sin_addr, magic_loopback_addr, 4 )) unix_addr.in.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
+ if (sock->family == WS_AF_UNIX && *((char *)(params + 1) + params->addr_len)) + { + char *unix_path = (char *)(params + 1) + params->addr_len; + char unix_path_copy[PATH_MAX]; + strcpy(unix_path_copy, unix_path); + if (chdir( dirname( unix_path_copy ) ) == -1) + { + set_error( sock_get_ntstatus( errno ) ); + return; + } + memcpy( unix_addr.un.sun_path, basename( unix_path ), sizeof(unix_addr.un.sun_path) ); + } + ret = connect( unix_fd, &unix_addr.addr, unix_len ); if (ret < 0 && errno == ECONNABORTED) { @@ -2619,6 +2664,9 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) ret = connect( unix_fd, &unix_addr.addr, unix_len ); }
+ if (sock->family == WS_AF_UNIX && *((char *)(params + 1) + params->addr_len)) + fchdir(server_dir_fd); + if (ret < 0 && errno != EINPROGRESS) { set_error( sock_get_ntstatus( errno ) ); @@ -2943,12 +2991,27 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) if (check_addr_usage( sock, &bind_addr, v6only )) return;
+ if (sock->family == WS_AF_UNIX && *(char *)(params + 1)) + { + char *unix_path = (char *)(params + 1); + char unix_path_copy[PATH_MAX]; + strcpy(unix_path_copy, unix_path); + if (chdir( dirname( unix_path_copy ) ) == -1) + { + set_error( sock_get_ntstatus( errno ) ); + return; + } + memcpy( unix_addr.un.sun_path, basename( unix_path ), sizeof(unix_addr.un.sun_path) ); + } + if (bind( unix_fd, &bind_addr.addr, unix_len ) < 0) { if (errno == EADDRINUSE && sock->reuseaddr) errno = EACCES;
set_error( sock_get_ntstatus( errno ) ); + if (sock->family == WS_AF_UNIX && *(char *)(params + 1)) + fchdir(server_dir_fd); return; }
@@ -2968,6 +3031,9 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
if (get_reply_max_size() >= sock->addr_len) set_reply_data( &sock->addr, sock->addr_len ); + + if (sock->family == WS_AF_UNIX && *(char *)(params + 1)) + fchdir(server_dir_fd); return; }
From: Ally Sommers dropbear.sh@gmail.com
Deleting the socket file is a common pattern with AF_UNIX sockets, and is analogous to unbinding. --- server/fd.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
diff --git a/server/fd.c b/server/fd.c index eaebe044f37..e45c0183dfe 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1957,6 +1957,26 @@ struct fd *open_fd( struct fd *root, const char *name, struct unicode_str nt_nam fd->unix_fd = open( name, O_RDONLY | (flags & ~(O_TRUNC | O_CREAT | O_EXCL)), *mode ); }
+ /* open(3) throws ENXIO when `path` is one of: + * 1. a FIFO, and open(3) is called with O_WRONLY | O_NONBLOCK, + * and no other process is currently attempting to read from `path`. + * 2. a special device file, and the device it corresponds to does not exist. + * 3. a UNIX socket. + * We can confirm the third case to allow for unlinking a socket. + */ + if (errno == ENXIO && !stat( name, &st ) && S_ISSOCK(st.st_mode)) + { + if ((access & DELETE)) + unlink( name ); + else + { + set_error( ENXIO ); + goto error; + } + file_set_error(); + goto error; + } + if (fd->unix_fd == -1) { /* check for trailing slash on file path */
From: Ally Sommers dropbear.sh@gmail.com
--- server/sock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 25e72b003c1..37181bd668e 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2664,7 +2664,7 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) ret = connect( unix_fd, &unix_addr.addr, unix_len ); }
- if (sock->family == WS_AF_UNIX && *((char *)(params + 1) + params->addr_len)) + if (sock->family == WS_AF_UNIX && *(char *)(params + 1)) fchdir(server_dir_fd);
if (ret < 0 && errno != EINPROGRESS) @@ -2991,9 +2991,9 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) if (check_addr_usage( sock, &bind_addr, v6only )) return;
- if (sock->family == WS_AF_UNIX && *(char *)(params + 1)) + if (sock->family == WS_AF_UNIX && *params->addr.sa_data) { - char *unix_path = (char *)(params + 1); + char *unix_path = (char *)¶ms->addr + sizeof(unix_addr.un); char unix_path_copy[PATH_MAX]; strcpy(unix_path_copy, unix_path); if (chdir( dirname( unix_path_copy ) ) == -1)
From: Ally Sommers dropbear.sh@gmail.com
--- dlls/ws2_32/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 026bb029328..a77dbdfcf33 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1192,7 +1192,7 @@ int WINAPI bind( SOCKET s, const struct sockaddr *addr, int len ) params->unknown = 0; memcpy( ¶ms->addr, addr, len ); if (unix_path) - memcpy( params + 1, unix_path, unix_path_len ); + memcpy( (char *)¶ms->addr + len, unix_path, unix_path_len );
status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_BIND, params, sizeof(int) + len + unix_path_len, ret_addr, len + unix_path_len );
From: Ally Sommers dropbear.sh@gmail.com
--- server/sock.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 37181bd668e..aa88e041216 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2639,17 +2639,28 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) if (unix_addr.addr.sa_family == AF_INET && !memcmp( &unix_addr.in.sin_addr, magic_loopback_addr, 4 )) unix_addr.in.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
- if (sock->family == WS_AF_UNIX && *((char *)(params + 1) + params->addr_len)) + if (sock->family == WS_AF_UNIX) { - char *unix_path = (char *)(params + 1) + params->addr_len; - char unix_path_copy[PATH_MAX]; - strcpy(unix_path_copy, unix_path); - if (chdir( dirname( unix_path_copy ) ) == -1) + if (*(char *)(params + 1)) { - set_error( sock_get_ntstatus( errno ) ); + char *unix_path = (char *)(params + 1) + params->addr_len; + char unix_path_copy[PATH_MAX]; + strcpy(unix_path_copy, unix_path); + if (chdir( dirname( unix_path_copy ) ) == -1) + { + set_error( sock_get_ntstatus( errno ) ); + return; + } + memcpy( unix_addr.un.sun_path, basename( unix_path ), sizeof(unix_addr.un.sun_path) ); + } + else + { + /* Contrary to documentation, Windows does not currently support abstract Unix + * sockets. connect() throws WSAEINVAL if sun_family is AF_UNIX and sun_path + * begins with '\0', even though bind() will succeed. */ + set_win32_error( WSAEINVAL ); return; } - memcpy( unix_addr.un.sun_path, basename( unix_path ), sizeof(unix_addr.un.sun_path) ); }
ret = connect( unix_fd, &unix_addr.addr, unix_len );
From: Ally Sommers dropbear.sh@gmail.com
--- dlls/ws2_32/tests/sock.c | 68 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index cddc4c125ff..092bce75d74 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -29,6 +29,7 @@ #include <iphlpapi.h> #include <ws2tcpip.h> #include <wsipx.h> +#include <afunix.h> #include <wsnwlink.h> #include <mswsock.h> #include <mstcpip.h> @@ -13706,6 +13707,72 @@ static void test_connect_udp(void) closesocket(client); }
+struct afunix_thread_param +{ + int sockfd; + SOCKADDR_UN addr; +}; + +static DWORD WINAPI test_afunix_client_connect_thread(void *param) +{ + struct afunix_thread_param *in = param; + ok(!connect(in->sockfd, (SOCKADDR *)&in->addr, sizeof(in->addr)), "Could not connect to Unix socket: %lu\n", + GetLastError()); + return 0; +} + +static void test_afunix(void) +{ + SOCKET server, client, conn; + const SOCKADDR_UN addr = { AF_UNIX, "test_afunix.sock" }; + HANDLE clientThread; + const char serverMsg[] = "ws2_32/AF_UNIX socket test"; + char clientBuf[sizeof(serverMsg)] = { 0 }; + int ret; + + server = socket(AF_UNIX, SOCK_STREAM, 0); + ok(server != INVALID_SOCKET, "Could not create Unix socket: %lu\n", + GetLastError()); + + ok(!bind(server, (SOCKADDR *)&addr, sizeof(SOCKADDR_UN)), "Could not bind Unix socket: %lu\n", + GetLastError()); + ok(!listen(server, 1), "Could not listen on Unix socket: %lu\n", + GetLastError()); + + client = socket(AF_UNIX, SOCK_STREAM, 0); + ok(client != INVALID_SOCKET, "Failed to create second Unix socket: %lu\n", + GetLastError()); + + clientThread = CreateThread(NULL, 0, test_afunix_client_connect_thread, + &(struct afunix_thread_param){ client, addr }, 0, NULL); + ok(clientThread != NULL, "CreateThread failed unexpectedly: %ld\n", GetLastError()); + conn = accept(server, NULL, NULL); + ok(conn != INVALID_SOCKET, "Could not accept Unix socket connection: %lu\n", + GetLastError()); + + ret = send(conn, serverMsg, sizeof(serverMsg), 0); + ok(ret == sizeof(serverMsg), + ret >= 0 + ? "Incorrect amount of bytes written to Unix socket: %lu\n" + : "Could not send data over Unix socket: %lu\n", + ret >= 0 ? ret : GetLastError()); + + ret = recv(client, clientBuf, sizeof(serverMsg), 0); + ok(ret == sizeof(serverMsg), + ret >= 0 + ? "Incorrect amount of bytes read from Unix socket: %lu\n" + : "Could not receive data over Unix socket: %lu\n", + ret >= 0 ? ret : GetLastError()); + + ok(!memcmp(serverMsg, clientBuf, sizeof(serverMsg)), "Data mismatch over Unix socket\n"); + + DeleteFileA("test_afunix.sock"); + ok(GetFileAttributesA("test_afunix.sock") == INVALID_FILE_ATTRIBUTES && + GetLastError() == ERROR_FILE_NOT_FOUND, + "Failed to delete socket file at path '%s'\n", + addr.sun_path); +} + START_TEST( sock ) { int i; @@ -13787,6 +13854,7 @@ START_TEST( sock ) test_tcp_reset(); test_icmp(); test_connect_udp(); + test_afunix();
/* this is an io heavy test, do it at the end so the kernel doesn't start dropping packets */ test_send();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=132718
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 0 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w7u_adm (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 0 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w7u_el (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 0 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w8 (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w8adm (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w864 (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w1064v1507 (32 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w7pro64 (64 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w864 (64 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== w1064v1507 (64 bit report) ===
ws2_32: sock.c:13734: Test failed: Could not create Unix socket: 10047 sock.c:13737: Test failed: Could not bind Unix socket: 10047 sock.c:13739: Test failed: Could not listen on Unix socket: 10038 sock.c:13743: Test failed: Failed to create second Unix socket: 10047 sock.c:13750: Test failed: Could not accept Unix socket connection: 10038 sock.c:13719: Test failed: Could not connect to Unix socket: 87 sock.c:13754: Test failed: Could not send data over Unix socket: 10038 sock.c:13761: Test failed: Could not receive data over Unix socket: 10038 sock.c:13767: Test failed: Data mismatch over Unix socket
=== debian11 (32 bit report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a0ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (35853 bytes)
=== debian11 (32 bit ar:MA report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a0ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34050 bytes)
=== debian11 (32 bit de report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a0ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34084 bytes)
=== debian11 (32 bit fr report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a0ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34050 bytes)
=== debian11 (32 bit he:IL report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a0ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34050 bytes)
=== debian11 (32 bit hi:IN report) ===
ws2_32: Unhandled exception: page fault on read access to 0x003effff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34050 bytes)
=== debian11 (32 bit ja:JP report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00a2ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34084 bytes)
=== debian11 (32 bit zh:CN report) ===
ws2_32: Unhandled exception: page fault on read access to 0x003effff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34050 bytes)
=== debian11b (32 bit WoW report) ===
ws2_32: Unhandled exception: page fault on read access to 0x00b3ffff in 32-bit code (0x7bc27542).
Report validation errors: ws2_32:sock prints too much data (34058 bytes)
I have added a basic test and introduced an error when attempting to call `connect()` on an abstract AF_UNIX socket. Despite the announcement blog post explicitly stating otherwise, abstract AF_UNIX sockets are **not** supported by Windows (discussion here: https://github.com/microsoft/WSL/issues/4240). However, passing an abstract path to `bind()` or calling `listen()` or `accept()` on an abstract AF_UNIX socket does not yield an error.