From: Florian Will florian.will@gmail.com
--- dlls/ntdll/unix/socket.c | 20 +++++++++++++++ dlls/ws2_32/socket.c | 54 ++++++++++++++++++++++++++++++++++++++++ dlls/ws2_32/tests/sock.c | 18 +++++++------- include/wine/afd.h | 6 +++++ 4 files changed, 89 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 4e6781df607..232336da221 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -2507,6 +2507,26 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_SET_TCP_NODELAY: return do_setsockopt( handle, io, IPPROTO_TCP, TCP_NODELAY, in_buffer, in_size );
+ case IOCTL_AFD_WINE_GET_TCP_KEEPALIVE: + /* TCP_KEEPALIVE on Windows is called TCP_KEEPIDLE on Linux */ + return do_getsockopt( handle, io, IPPROTO_TCP, TCP_KEEPIDLE, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_TCP_KEEPALIVE: + /* TCP_KEEPALIVE on Windows is called TCP_KEEPIDLE on Linux */ + return do_setsockopt( handle, io, IPPROTO_TCP, TCP_KEEPIDLE, in_buffer, in_size ); + + case IOCTL_AFD_WINE_GET_TCP_KEEPINTVL: + return do_getsockopt( handle, io, IPPROTO_TCP, TCP_KEEPINTVL, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_TCP_KEEPINTVL: + return do_setsockopt( handle, io, IPPROTO_TCP, TCP_KEEPINTVL, in_buffer, in_size ); + + case IOCTL_AFD_WINE_GET_TCP_KEEPCNT: + return do_getsockopt( handle, io, IPPROTO_TCP, TCP_KEEPCNT, out_buffer, out_size ); + + case IOCTL_AFD_WINE_SET_TCP_KEEPCNT: + return do_setsockopt( handle, io, IPPROTO_TCP, TCP_KEEPCNT, in_buffer, in_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 6aab249a1b8..49b380a6329 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1931,6 +1931,33 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl *optlen = 1; return server_getsockopt( s, IOCTL_AFD_WINE_GET_TCP_NODELAY, optval, optlen );
+ case TCP_KEEPALIVE: + if (*optlen < sizeof(DWORD) || !optval) + { + SetLastError( WSAEFAULT ); + return SOCKET_ERROR; + } + *optlen = sizeof(DWORD); + return server_getsockopt( s, IOCTL_AFD_WINE_GET_TCP_KEEPALIVE, optval, optlen ); + + case TCP_KEEPCNT: + if (*optlen < sizeof(DWORD) || !optval) + { + SetLastError( WSAEFAULT ); + return SOCKET_ERROR; + } + *optlen = sizeof(DWORD); + return server_getsockopt( s, IOCTL_AFD_WINE_GET_TCP_KEEPCNT, optval, optlen ); + + case TCP_KEEPINTVL: + if (*optlen < sizeof(DWORD) || !optval) + { + SetLastError( WSAEFAULT ); + return SOCKET_ERROR; + } + *optlen = sizeof(DWORD); + return server_getsockopt( s, IOCTL_AFD_WINE_GET_TCP_KEEPINTVL, optval, optlen ); + default: FIXME( "unrecognized TCP option %#x\n", optname ); SetLastError( WSAENOPROTOOPT ); @@ -3336,6 +3363,33 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int value = *optval; return server_setsockopt( s, IOCTL_AFD_WINE_SET_TCP_NODELAY, (char*)&value, sizeof(value) );
+ case TCP_KEEPALIVE: + if (optlen < sizeof(DWORD) || !optval) + { + SetLastError( optlen && optval ? WSAENOBUFS : WSAEFAULT ); + return SOCKET_ERROR; + } + value = *(DWORD*)optval; + return server_setsockopt( s, IOCTL_AFD_WINE_SET_TCP_KEEPALIVE, (char*)&value, sizeof(value) ); + + case TCP_KEEPCNT: + if (optlen < sizeof(DWORD) || !optval) + { + SetLastError( optlen && optval ? WSAENOBUFS : WSAEFAULT ); + return SOCKET_ERROR; + } + value = *(DWORD*)optval; + return server_setsockopt( s, IOCTL_AFD_WINE_SET_TCP_KEEPCNT, (char*)&value, sizeof(value) ); + + case TCP_KEEPINTVL: + if (optlen < sizeof(DWORD) || !optval) + { + SetLastError( optlen && optval ? WSAENOBUFS : WSAEFAULT ); + return SOCKET_ERROR; + } + value = *(DWORD*)optval; + return server_setsockopt( s, IOCTL_AFD_WINE_SET_TCP_KEEPINTVL, (char*)&value, sizeof(value) ); + default: FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname); SetLastError(WSAENOPROTOOPT); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 2563e8769f5..131499436cd 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1456,29 +1456,29 @@ static void test_set_getsockopt(void) size = sizeof(DWORD); value = 3600; err = setsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE, (char*)&value, 4); - todo_wine ok(!err, "setsockopt TCP_KEEPALIVE failed\n"); + ok(!err, "setsockopt TCP_KEEPALIVE failed\n"); value = 0; err = getsockopt(s, IPPROTO_TCP, TCP_KEEPALIVE, (char*)&value, &size); - todo_wine ok(!err, "getsockopt TCP_KEEPALIVE failed\n"); - todo_wine ok(value == 3600, "TCP_KEEPALIVE should be 3600, is %ld\n", value); + ok(!err, "getsockopt TCP_KEEPALIVE failed\n"); + ok(value == 3600, "TCP_KEEPALIVE should be 3600, is %ld\n", value);
/* TCP_KEEPCNT and TCP_KEEPINTVL are supported on win10 and later */ value = 5; err = setsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, (char*)&value, 4); if (!err || WSAGetLastError() != WSAENOPROTOOPT || winetest_platform_is_wine) { - todo_wine ok(!err, "setsockopt TCP_KEEPCNT failed: %d\n", WSAGetLastError()); + ok(!err, "setsockopt TCP_KEEPCNT failed: %d\n", WSAGetLastError()); value = 0; err = getsockopt(s, IPPROTO_TCP, TCP_KEEPCNT, (char*)&value, &size); - todo_wine ok(!err, "getsockopt TCP_KEEPCNT failed\n"); - todo_wine ok(value == 5, "TCP_KEEPCNT should be 5, is %ld\n", value); + ok(!err, "getsockopt TCP_KEEPCNT failed\n"); + ok(value == 5, "TCP_KEEPCNT should be 5, is %ld\n", value);
err = setsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&value, 4); - todo_wine ok(!err, "setsockopt TCP_KEEPINTVL failed\n"); + ok(!err, "setsockopt TCP_KEEPINTVL failed\n"); value = 0; err = getsockopt(s, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&value, &size); - todo_wine ok(!err, "getsockopt TCP_KEEPINTVL failed\n"); - todo_wine ok(value == 5, "TCP_KEEPINTVL should be 5, is %ld\n", value); + ok(!err, "getsockopt TCP_KEEPINTVL failed\n"); + ok(value == 5, "TCP_KEEPINTVL should be 5, is %ld\n", value); }
/* Test for erroneously passing a value instead of a pointer as optval */ diff --git a/include/wine/afd.h b/include/wine/afd.h index 788adb4a495..aba559ebd8a 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -285,6 +285,12 @@ C_ASSERT( sizeof(struct afd_get_events_params) == 56 ); #define IOCTL_AFD_WINE_SET_IP_RECVTOS WINE_AFD_IOC(296) #define IOCTL_AFD_WINE_GET_SO_EXCLUSIVEADDRUSE WINE_AFD_IOC(297) #define IOCTL_AFD_WINE_SET_SO_EXCLUSIVEADDRUSE WINE_AFD_IOC(298) +#define IOCTL_AFD_WINE_GET_TCP_KEEPALIVE WINE_AFD_IOC(299) +#define IOCTL_AFD_WINE_SET_TCP_KEEPALIVE WINE_AFD_IOC(300) +#define IOCTL_AFD_WINE_GET_TCP_KEEPCNT WINE_AFD_IOC(301) +#define IOCTL_AFD_WINE_SET_TCP_KEEPCNT WINE_AFD_IOC(302) +#define IOCTL_AFD_WINE_GET_TCP_KEEPINTVL WINE_AFD_IOC(303) +#define IOCTL_AFD_WINE_SET_TCP_KEEPINTVL WINE_AFD_IOC(304)
struct afd_iovec {