Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index e99faa4096b..26ad716dbe3 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3899,6 +3899,7 @@ static void test_fionbio(void) u_long one = 1, zero = 0; HANDLE port, event; ULONG_PTR key; + void *output; DWORD size; SOCKET s; int ret; @@ -3931,6 +3932,11 @@ static void test_fionbio(void) ret = WSAIoctl(s, FIONBIO, &one, sizeof(one) + 1, NULL, 0, &size, NULL, NULL); ok(!ret, "got error %u\n", WSAGetLastError());
+ output = VirtualAlloc(NULL, 4, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); + ret = WSAIoctl(s, FIONBIO, &one, sizeof(one) + 1, output, 4, &size, NULL, NULL); + todo_wine ok(!ret, "got error %u\n", WSAGetLastError()); + VirtualFree(output, 0, MEM_FREE); + overlapped.Internal = 0xdeadbeef; overlapped.InternalHigh = 0xdeadbeef; size = 0xdeadbeef;
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51231 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 4 +++- dlls/ws2_32/tests/sock.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index a425905e5af..12698a37fd0 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3368,8 +3368,10 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return -1; }
+ /* Explicitly ignore the output buffer; WeChat tries to pass an address + * without write access. */ ret = server_ioctl_sock( s, IOCTL_AFD_WINE_FIONBIO, in_buff, in_size, - out_buff, out_size, ret_size, overlapped, completion ); + NULL, 0, ret_size, overlapped, completion ); SetLastError( ret ); return ret ? -1 : 0; } diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 26ad716dbe3..ddcc4313c8f 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3934,7 +3934,7 @@ static void test_fionbio(void)
output = VirtualAlloc(NULL, 4, MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS); ret = WSAIoctl(s, FIONBIO, &one, sizeof(one) + 1, output, 4, &size, NULL, NULL); - todo_wine ok(!ret, "got error %u\n", WSAGetLastError()); + ok(!ret, "got error %u\n", WSAGetLastError()); VirtualFree(output, 0, MEM_FREE);
overlapped.Internal = 0xdeadbeef;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/socket.c | 93 ++++++++++++++++++++++++++++++++++++++++ include/wine/afd.h | 1 + 2 files changed, 94 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index e5f4862bf3c..bc77514669d 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -24,7 +24,14 @@
#include "config.h" #include <errno.h> +#include <sys/types.h> #include <unistd.h> +#ifdef HAVE_IFADDRS_H +# include <ifaddrs.h> +#endif +#ifdef HAVE_NET_IF_H +# include <net/if.h> +#endif #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> #endif @@ -1355,6 +1362,92 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc break; }
+ case IOCTL_AFD_WINE_GET_INTERFACE_LIST: + { +#ifdef HAVE_GETIFADDRS + INTERFACE_INFO *info = out_buffer; + struct ifaddrs *ifaddrs, *ifaddr; + unsigned int count = 0; + ULONG ret_size; + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return status; + + if (getifaddrs( &ifaddrs ) < 0) + { + status = sock_errno_to_status( errno ); + break; + } + + for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) + { + if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET) ++count; + } + + ret_size = count * sizeof(*info); + if (out_size < ret_size) + { + status = STATUS_PENDING; + complete_async( handle, event, apc, apc_user, io, STATUS_BUFFER_TOO_SMALL, 0 ); + freeifaddrs( ifaddrs ); + break; + } + + memset( out_buffer, 0, ret_size ); + + count = 0; + for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) + { + in_addr_t addr, mask; + + if (!ifaddr->ifa_addr || ifaddr->ifa_addr->sa_family != AF_INET) + continue; + + addr = ((const struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr; + mask = ((const struct sockaddr_in *)ifaddr->ifa_netmask)->sin_addr.s_addr; + + info[count].iiFlags = 0; + if (ifaddr->ifa_flags & IFF_BROADCAST) + info[count].iiFlags |= WS_IFF_BROADCAST; + if (ifaddr->ifa_flags & IFF_LOOPBACK) + info[count].iiFlags |= WS_IFF_LOOPBACK; + if (ifaddr->ifa_flags & IFF_MULTICAST) + info[count].iiFlags |= WS_IFF_MULTICAST; +#ifdef IFF_POINTTOPOINT + if (ifaddr->ifa_flags & IFF_POINTTOPOINT) + info[count].iiFlags |= WS_IFF_POINTTOPOINT; +#endif + if (ifaddr->ifa_flags & IFF_UP) + info[count].iiFlags |= WS_IFF_UP; + + info[count].iiAddress.AddressIn.sin_family = WS_AF_INET; + info[count].iiAddress.AddressIn.sin_port = 0; + info[count].iiAddress.AddressIn.sin_addr.WS_s_addr = addr; + + info[count].iiNetmask.AddressIn.sin_family = WS_AF_INET; + info[count].iiNetmask.AddressIn.sin_port = 0; + info[count].iiNetmask.AddressIn.sin_addr.WS_s_addr = mask; + + if (ifaddr->ifa_flags & IFF_BROADCAST) + { + info[count].iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET; + info[count].iiBroadcastAddress.AddressIn.sin_port = 0; + info[count].iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask; + } + + ++count; + } + + freeifaddrs( ifaddrs ); + status = STATUS_PENDING; + complete_async( handle, event, apc, apc_user, io, STATUS_SUCCESS, ret_size ); +#else + FIXME( "Interface list queries are currently not supported on this platform.\n" ); + status = STATUS_NOT_SUPPORTED; +#endif + break; + } + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/include/wine/afd.h b/include/wine/afd.h index 2b4c39e7a86..cc328f9bcae 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -100,6 +100,7 @@ struct afd_poll_params #define IOCTL_AFD_WINE_COMPLETE_ASYNC CTL_CODE(FILE_DEVICE_NETWORK, 210, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_FIONREAD CTL_CODE(FILE_DEVICE_NETWORK, 211, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SIOCATMARK CTL_CODE(FILE_DEVICE_NETWORK, 212, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_GET_INTERFACE_LIST CTL_CODE(FILE_DEVICE_NETWORK, 213, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 131 +++------------------------------------ dlls/ws2_32/tests/sock.c | 33 +++++----- 2 files changed, 24 insertions(+), 140 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 12698a37fd0..ee1984ca79a 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3219,122 +3219,6 @@ static DWORD server_ioctl_sock( SOCKET s, DWORD code, LPVOID in_buff, DWORD in_s return NtStatusToWSAError( status ); }
-static DWORD get_interface_list(SOCKET s, void *out_buff, DWORD out_size, DWORD *ret_size, DWORD *total_bytes) -{ - DWORD size, interface_count = 0, ret; - INTERFACE_INFO *info = out_buff; - PMIB_IPADDRTABLE table = NULL; - struct if_nameindex *if_ni; - DWORD status = 0; - int fd; - - if (!out_buff) - return WSAEFAULT; - - if ((fd = get_sock_fd(s, 0, NULL)) == -1) - return SOCKET_ERROR; - - if ((ret = GetIpAddrTable(NULL, &size, TRUE)) != ERROR_INSUFFICIENT_BUFFER) - { - if (ret != ERROR_NO_DATA) - { - ERR("Unable to get ip address table.\n"); - status = WSAEINVAL; - } - goto done; - } - if (!(table = heap_alloc(size))) - { - ERR("No memory.\n"); - status = WSAEINVAL; - goto done; - } - if (GetIpAddrTable(table, &size, TRUE) != NO_ERROR) - { - ERR("Unable to get interface table.\n"); - status = WSAEINVAL; - goto done; - } - if (table->dwNumEntries * sizeof(INTERFACE_INFO) > out_size) - { - WARN("Buffer too small, dwNumEntries %u, out_size = %u.\n", table->dwNumEntries, out_size); - *ret_size = 0; - status = WSAEFAULT; - goto done; - } - - if (!(if_ni = if_nameindex())) - { - ERR("Unable to get interface name index.\n"); - status = WSAEINVAL; - goto done; - } - - for (; interface_count < table->dwNumEntries; ++interface_count, ++info) - { - unsigned int addr, mask; - struct ifreq if_info; - unsigned int i; - - memset(info, 0, sizeof(*info)); - - for (i = 0; if_ni[i].if_index || if_ni[i].if_name; ++i) - if (if_ni[i].if_index == table->table[interface_count].dwIndex) - break; - - if (!if_ni[i].if_name) - { - ERR("Error obtaining interface name for ifindex %u.\n", table->table[interface_count].dwIndex); - status = WSAEINVAL; - break; - } - - lstrcpynA(if_info.ifr_name, if_ni[i].if_name, IFNAMSIZ); - if (ioctl(fd, SIOCGIFFLAGS, &if_info) < 0) - { - ERR("Error obtaining status flags for socket.\n"); - status = WSAEINVAL; - break; - } - - if (if_info.ifr_flags & IFF_BROADCAST) - info->iiFlags |= WS_IFF_BROADCAST; -#ifdef IFF_POINTOPOINT - if (if_info.ifr_flags & IFF_POINTOPOINT) - info->iiFlags |= WS_IFF_POINTTOPOINT; -#endif - if (if_info.ifr_flags & IFF_LOOPBACK) - info->iiFlags |= WS_IFF_LOOPBACK; - if (if_info.ifr_flags & IFF_UP) - info->iiFlags |= WS_IFF_UP; - if (if_info.ifr_flags & IFF_MULTICAST) - info->iiFlags |= WS_IFF_MULTICAST; - - addr = table->table[interface_count].dwAddr; - mask = table->table[interface_count].dwMask; - - info->iiAddress.AddressIn.sin_family = WS_AF_INET; - info->iiAddress.AddressIn.sin_port = 0; - info->iiAddress.AddressIn.sin_addr.WS_s_addr = addr; - - info->iiNetmask.AddressIn.sin_family = WS_AF_INET; - info->iiNetmask.AddressIn.sin_port = 0; - info->iiNetmask.AddressIn.sin_addr.WS_s_addr = mask; - - if (if_info.ifr_flags & IFF_BROADCAST) - { - info->iiBroadcastAddress.AddressIn.sin_family = WS_AF_INET; - info->iiBroadcastAddress.AddressIn.sin_port = 0; - info->iiBroadcastAddress.AddressIn.sin_addr.WS_s_addr = addr | ~mask; - } - } - if_freenameindex(if_ni); -done: - heap_free(table); - *total_bytes = sizeof(INTERFACE_INFO) * interface_count; - release_sock_fd(s, fd); - return status; -}
/********************************************************************** * WSAIoctl (WS2_32.50) @@ -3403,13 +3287,16 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID SetLastError(WSAEINVAL); return SOCKET_ERROR;
- case WS_SIO_GET_INTERFACE_LIST: - { - TRACE("-> SIO_GET_INTERFACE_LIST request\n"); + case WS_SIO_GET_INTERFACE_LIST: + { + DWORD ret;
- status = get_interface_list(s, out_buff, out_size, ret_size, &total); - break; - } + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_GET_INTERFACE_LIST, in_buff, in_size, + out_buff, out_size, ret_size, overlapped, completion ); + SetLastError( ret ); + if (ret && ret != ERROR_IO_PENDING) *ret_size = 0; + return ret ? -1 : 0; + }
case WS_SIO_ADDRESS_LIST_QUERY: { diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ddcc4313c8f..3dc11c9bf3d 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -10076,7 +10076,7 @@ static void test_get_interface_list(void) WSASetLastError(0xdeadbeef); ret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, sizeof(buffer), &size, NULL, NULL); ok(!ret, "Got unexpected ret %d.\n", ret); - todo_wine ok(!WSAGetLastError(), "Got error %u.\n", WSAGetLastError()); + ok(!WSAGetLastError(), "Got error %u.\n", WSAGetLastError()); ok(size && size != 0xdeadbeef && !(size % sizeof(INTERFACE_INFO)), "Got unexpected size %u.\n", size); expect_size = size;
@@ -10084,9 +10084,9 @@ static void test_get_interface_list(void) overlapped.Internal = 0xdeadbeef; overlapped.InternalHigh = 0xdeadbeef; ret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, sizeof(buffer), &size, &overlapped, NULL); - todo_wine ok(ret == -1, "Got unexpected ret %d.\n", ret); - todo_wine ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); - todo_wine ok(size == 0xdeadbeef, "Got size %u.\n", size); + ok(ret == -1, "Got unexpected ret %d.\n", ret); + ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); + ok(size == 0xdeadbeef, "Got size %u.\n", size);
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 100); ok(ret, "Got error %u.\n", GetLastError()); @@ -10131,16 +10131,16 @@ static void test_get_interface_list(void) overlapped.InternalHigh = 0xdeadbeef; ret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, sizeof(INTERFACE_INFO) - 1, &size, &overlapped, NULL); ok(ret == -1, "Got unexpected ret %d.\n", ret); - todo_wine ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); - todo_wine ok(size == 0xdeadbeef, "Got size %u.\n", size); + ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); + ok(size == 0xdeadbeef, "Got size %u.\n", size);
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 100); ok(!ret, "Expected failure.\n"); - todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got error %u.\n", GetLastError()); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Got error %u.\n", GetLastError()); ok(!size, "Got size %u.\n", size); ok(key == 123, "Got key %Iu.\n", key); ok(overlapped_ptr == &overlapped, "Got overlapped %p.\n", overlapped_ptr); - todo_wine ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_TOO_SMALL, "Got status %#x.\n", (NTSTATUS)overlapped.Internal); + ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_TOO_SMALL, "Got status %#x.\n", (NTSTATUS)overlapped.Internal); ok(!overlapped.InternalHigh, "Got size %Iu.\n", overlapped.InternalHigh);
ret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, sizeof(buffer), NULL, NULL, NULL); @@ -10160,18 +10160,15 @@ static void test_get_interface_list(void) ret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, buffer, sizeof(INTERFACE_INFO) - 1, &size, &overlapped, socket_apc); ok(ret == -1, "Got unexpected ret %d.\n", ret); - todo_wine ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); - todo_wine ok(size == 0xdeadbeef, "Got size %u.\n", size); + ok(WSAGetLastError() == ERROR_IO_PENDING, "Got error %u.\n", WSAGetLastError()); + ok(size == 0xdeadbeef, "Got size %u.\n", size);
ret = SleepEx(100, TRUE); - todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); - if (ret == WAIT_IO_COMPLETION) - { - ok(apc_count == 1, "APC was called %u times\n", apc_count); - ok(apc_error == WSAEFAULT, "got APC error %u\n", apc_error); - ok(!apc_size, "got APC size %u\n", apc_size); - ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped); - } + ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); + ok(apc_count == 1, "APC was called %u times\n", apc_count); + ok(apc_error == WSAEFAULT, "got APC error %u\n", apc_error); + ok(!apc_size, "got APC size %u\n", apc_size); + ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
closesocket(s); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/socket.c | 59 ++++++++++++++++++++++++++++++++++++++++ include/wine/afd.h | 1 + 2 files changed, 60 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index bc77514669d..c1cd319ccf9 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -41,6 +41,9 @@ #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif +#ifdef HAVE_NETINET_TCP_H +# include <netinet/tcp.h> +#endif
#ifdef HAVE_NETIPX_IPX_H # include <netipx/ipx.h> @@ -72,6 +75,7 @@ #define USE_WS_PREFIX #include "winsock2.h" #include "mswsock.h" +#include "mstcpip.h" #include "ws2tcpip.h" #include "wsipx.h" #include "af_irda.h" @@ -79,6 +83,11 @@
#include "unix_private.h"
+#if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) +/* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */ +#define TCP_KEEPIDLE TCP_KEEPALIVE +#endif + WINE_DEFAULT_DEBUG_CHANNEL(winsock);
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2) @@ -1448,6 +1457,56 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc break; }
+ case IOCTL_AFD_WINE_KEEPALIVE_VALS: + { + struct tcp_keepalive *k = in_buffer; + int keepalive; + + if (!in_buffer || in_size < sizeof(struct tcp_keepalive)) + return STATUS_BUFFER_TOO_SMALL; + keepalive = !!k->onoff; + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return status; + + if (setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(int) ) < 0) + { + status = STATUS_INVALID_PARAMETER; + break; + } + + if (keepalive) + { +#ifdef TCP_KEEPIDLE + int idle = max( 1, (k->keepalivetime + 500) / 1000 ); + + if (setsockopt( fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(int) ) < 0) + { + status = STATUS_INVALID_PARAMETER; + break; + } +#else + FIXME("ignoring keepalive timeout\n"); +#endif + } + + if (keepalive) + { +#ifdef TCP_KEEPINTVL + int interval = max( 1, (k->keepaliveinterval + 500) / 1000 ); + + if (setsockopt( fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(int) ) < 0) + status = STATUS_INVALID_PARAMETER; +#else + FIXME("ignoring keepalive interval\n"); +#endif + } + + status = STATUS_SUCCESS; + complete_async( handle, event, apc, apc_user, io, status, 0 ); + break; + } + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/include/wine/afd.h b/include/wine/afd.h index cc328f9bcae..595fc572a1c 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -101,6 +101,7 @@ struct afd_poll_params #define IOCTL_AFD_WINE_FIONREAD CTL_CODE(FILE_DEVICE_NETWORK, 211, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SIOCATMARK CTL_CODE(FILE_DEVICE_NETWORK, 212, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_GET_INTERFACE_LIST CTL_CODE(FILE_DEVICE_NETWORK, 213, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_AFD_WINE_KEEPALIVE_VALS CTL_CODE(FILE_DEVICE_NETWORK, 214, METHOD_BUFFERED, FILE_ANY_ACCESS)
struct afd_create_params {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 56 ++++++---------------------------------- dlls/ws2_32/tests/sock.c | 21 +++++++-------- 2 files changed, 17 insertions(+), 60 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index ee1984ca79a..1b3ad2fa6d0 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -40,11 +40,6 @@ # define sipx_node sipx_addr.x_host.c_host #endif /* __FreeBSD__ */
-#if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) -/* TCP_KEEPALIVE is the Mac OS name for TCP_KEEPIDLE */ -#define TCP_KEEPIDLE TCP_KEEPALIVE -#endif - #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
WINE_DEFAULT_DEBUG_CHANNEL(winsock); @@ -3228,7 +3223,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID DWORD out_size, LPDWORD ret_size, LPWSAOVERLAPPED overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion ) { - int fd; DWORD status = 0, total = 0;
TRACE("%04lx, %s, %p, %d, %p, %d, %p, %p, %p\n", @@ -3422,52 +3416,18 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID SetLastError( WSAEINVAL ); return -1; } + case WS_SIO_KEEPALIVE_VALS: { - struct tcp_keepalive *k; - int keepalive, keepidle, keepintvl; - - if (!in_buff || in_size < sizeof(struct tcp_keepalive)) - { - SetLastError(WSAEFAULT); - return SOCKET_ERROR; - } - - k = in_buff; - keepalive = k->onoff ? 1 : 0; - keepidle = max( 1, (k->keepalivetime + 500) / 1000 ); - keepintvl = max( 1, (k->keepaliveinterval + 500) / 1000 ); + DWORD ret;
- TRACE("onoff: %d, keepalivetime: %d, keepaliveinterval: %d\n", keepalive, keepidle, keepintvl); + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_KEEPALIVE_VALS, in_buff, in_size, + out_buff, out_size, ret_size, overlapped, completion ); + if (!overlapped || completion) *ret_size = 0; + SetLastError( ret ); + return ret ? -1 : 0; + }
- fd = get_sock_fd(s, 0, NULL); - if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(int)) == -1) - status = WSAEINVAL; -#if defined(TCP_KEEPIDLE) || defined(TCP_KEEPINTVL) - /* these values need to be set only if SO_KEEPALIVE is enabled */ - else if(keepalive) - { -#ifndef TCP_KEEPIDLE - FIXME("ignoring keepalive timeout\n"); -#else - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&keepidle, sizeof(int)) == -1) - status = WSAEINVAL; - else -#endif -#ifdef TCP_KEEPINTVL - if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(int)) == -1) - status = WSAEINVAL; -#else - FIXME("ignoring keepalive interval\n"); -#endif - } -#else - else - FIXME("ignoring keepalive interval and timeout\n"); -#endif - release_sock_fd(s, fd); - break; - } case WS_SIO_ROUTING_INTERFACE_QUERY: { struct WS_sockaddr *daddr = (struct WS_sockaddr *)in_buff; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 3dc11c9bf3d..3648fa2a329 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4012,21 +4012,21 @@ static void test_keepalive_vals(void) ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, 0, NULL, 0, &size, NULL, NULL); ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n"); ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); - todo_wine ok(!size, "got size %u\n", size); + ok(!size, "got size %u\n", size);
WSASetLastError(0xdeadbeef); size = 0xdeadbeef; ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, NULL, sizeof(kalive), NULL, 0, &size, NULL, NULL); ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n"); ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); - todo_wine ok(!size, "got size %u\n", size); + ok(!size, "got size %u\n", size);
WSASetLastError(0xdeadbeef); size = 0xdeadbeef; make_keepalive(kalive, 0, 0, 0); ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(kalive), NULL, 0, &size, NULL, NULL); ok(ret == 0, "WSAIoctl failed unexpectedly\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); ok(!size, "got size %u\n", size);
ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(kalive), NULL, 0, NULL, NULL, NULL); @@ -4054,7 +4054,7 @@ static void test_keepalive_vals(void) overlapped.InternalHigh = 0xdeadbeef; ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &kalive, sizeof(kalive), NULL, 0, &size, &overlapped, NULL); ok(ret == 0, "WSAIoctl failed unexpectedly\n"); - todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); todo_wine ok(size == 0xdeadbeef, "got size %u\n", size);
ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); @@ -4100,14 +4100,11 @@ static void test_keepalive_vals(void) ok(!size, "got size %u\n", size);
ret = SleepEx(0, TRUE); - todo_wine ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); - if (ret == WAIT_IO_COMPLETION) - { - ok(apc_count == 1, "APC was called %u times\n", apc_count); - ok(!apc_error, "got APC error %u\n", apc_error); - ok(!apc_size, "got APC size %u\n", apc_size); - ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped); - } + ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); + ok(apc_count == 1, "APC was called %u times\n", apc_count); + ok(!apc_error, "got APC error %u\n", apc_error); + ok(!apc_size, "got APC size %u\n", apc_size); + ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped);
closesocket(sock); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92051
Your paranoid android.
=== debiant2 (32 bit WoW report) ===
ws2_32: sock.c:4684: Test failed: got events 0x10 sock.c:4685: Test failed: expected timeout sock.c:4685: Test failed: got events 0x2