Module: wine Branch: master Commit: 531dcf2dd3b1c5e9848afce422a6e0f2ee497597 URL: http://source.winehq.org/git/wine.git/?a=commit;h=531dcf2dd3b1c5e9848afce422...
Author: Anton Romanov theli.ua@gmail.com Date: Wed Jan 11 21:27:08 2017 -0800
ws2_32: Ignore IPV6_V6ONLY setsockopt for AF_INET sockets.
Signed-off-by: Anton Romanov theli.ua@gmail.com Signed-off-by: Bruno Jesus 00cpxxx@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ws2_32/socket.c | 25 +++++++++++++++++++++++- dlls/ws2_32/tests/sock.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 6bf3c9d..4977bbf 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -6016,7 +6016,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_MULTICAST_HOPS: case WS_IPV6_MULTICAST_LOOP: case WS_IPV6_UNICAST_HOPS: - case WS_IPV6_V6ONLY: #ifdef IPV6_UNICAST_IF case WS_IPV6_UNICAST_IF: #endif @@ -6027,6 +6026,30 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IPV6_PROTECTION_LEVEL: FIXME("IPV6_PROTECTION_LEVEL is ignored!\n"); return 0; + case WS_IPV6_V6ONLY: + { + union generic_unix_sockaddr uaddr; + socklen_t uaddrlen; + int bound; + + fd = get_sock_fd( s, 0, NULL ); + if (fd == -1) return SOCKET_ERROR; + + bound = is_fd_bound(fd, &uaddr, &uaddrlen); + release_sock_fd( s, fd ); + if (bound == 0 && uaddr.addr.sa_family == AF_INET) + { + /* Changing IPV6_V6ONLY succeeds on AF_INET (IPv4) socket + * on Windows (with IPv6 support) if the socket is unbound. + * It is essentially a noop, though Windows does store the value + */ + WARN("Silently ignoring IPPROTO_IPV6+IPV6_V6ONLY on AF_INET socket\n"); + return 0; + } + level = IPPROTO_IPV6; + optname = IPV6_V6ONLY; + break; + } default: FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname); return SOCKET_ERROR; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ba755a5..5856718 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6189,12 +6189,60 @@ static void test_ipv6only(void) }
v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - ok(v4 != INVALID_SOCKET, "Could not create IPv6 socket (LastError: %d)\n", WSAGetLastError()); + ok(v4 != INVALID_SOCKET, "Could not create IPv4 socket (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 0; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(!enabled, "expected 0, got %d\n", enabled); +} + + enabled = 1; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(!ret, "setsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
/* bind on IPv4 socket should succeed - IPV6_V6ONLY is enabled by default */ ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4)); ok(!ret, "Could not bind IPv4 address (LastError: %d)\n", WSAGetLastError());
+todo_wine { + enabled = 2; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 0; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError()); + +todo_wine { + enabled = 0; + ret = getsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len); + ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError()); + ok(enabled == 1, "expected 1, got %d\n", enabled); +} + + enabled = 1; + len = sizeof(enabled); + ret = setsockopt(v4, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len); + ok(ret, "setsockopt(IPV6_ONLY) succeeded (LastError: %d)\n", WSAGetLastError()); + closesocket(v4); closesocket(v6);