From fd7b94bcd2b5d8ee48f329ec3705da9ef3fcf5ce Mon Sep 17 00:00:00 2001 From: Bruno Jesus <00cpxxx@gmail.com> Date: Tue, 13 Sep 2011 08:07:00 -0400 Subject: [PATCH] ws2_32: SO_OOBINLINE sockets must always return TRUE to SIOCATMARK request. --- dlls/ws2_32/socket.c | 23 ++++++++++++++++++++--- dlls/ws2_32/tests/sock.c | 23 ++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index bfe34ce8b52..b6d17ff4071 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3099,21 +3099,38 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID break; case WS_FIONREAD: - case WS_SIOCATMARK: { - int cmd = code == WS_FIONREAD ? FIONREAD : SIOCATMARK; if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff)) { WSASetLastError(WSAEFAULT); return SOCKET_ERROR; } if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; - if (ioctl(fd, cmd, out_buff ) == -1) + if (ioctl(fd, FIONREAD, out_buff ) == -1) status = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); release_sock_fd( s, fd ); break; } + case WS_SIOCATMARK: + { + unsigned int oob = 0, oobsize = sizeof(int), atmark = 0; + if (out_size != sizeof(WS_u_long) || IS_INTRESOURCE(out_buff)) + { + WSASetLastError(WSAEFAULT); + return SOCKET_ERROR; + } + if ((fd = get_sock_fd( s, 0, NULL )) == -1) return SOCKET_ERROR; + /* SO_OOBINLINE sockets must always return TRUE to SIOCATMARK */ + if ((getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, &oob, &oobsize ) == -1) + || (!oob && ioctl(fd, SIOCATMARK, &atmark ) == -1)) + status = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); + else + (*(WS_u_long *) out_buff) = oob | atmark; + release_sock_fd( s, fd ); + break; + } + case WS_FIOASYNC: WARN("Warning: WS1.1 shouldn't be using async I/O\n"); SetLastError(WSAEINVAL); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 37661864dcb..326b77d0575 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -2939,7 +2939,7 @@ static void test_ioctlsocket(void) { SOCKET sock; struct tcp_keepalive kalive; - int ret; + int ret, optval; static const LONG cmds[] = {FIONBIO, FIONREAD, SIOCATMARK}; UINT i; u_long arg = 0; @@ -2965,8 +2965,25 @@ static void test_ioctlsocket(void) * that normal(not urgent) data returns a non-zero value for SIOCATMARK. */ ret = ioctlsocket(sock, SIOCATMARK, &arg); - if(ret != SOCKET_ERROR) - todo_wine ok(arg, "expected a non-zero value\n"); + ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n"); + todo_wine ok(arg, "SIOCATMARK expected a non-zero value\n"); + + /* when SO_OOBINLINE is set SIOCATMARK must always return TRUE */ + optval = 1; + ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval)); + ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n"); + arg = 0; + ret = ioctlsocket(sock, SIOCATMARK, &arg); + ok(ret != SOCKET_ERROR, "ioctlsocket failed unexpectedly\n"); + ok(arg, "SIOCATMARK expected a non-zero value\n"); + + /* disable SO_OOBINLINE and get the same old bahavior */ + optval = 0; + ret = setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, (void *)&optval, sizeof(optval)); + ok(ret != SOCKET_ERROR, "setsockopt failed unexpectedly\n"); + arg = 0; + ret = ioctlsocket(sock, SIOCATMARK, &arg); + todo_wine ok(arg, "SIOCATMARK expected a non-zero value\n"); ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &arg, 0, NULL, 0, &arg, NULL, NULL); ok(ret == SOCKET_ERROR, "WSAIoctl succeeded unexpectedly\n");