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>
This commit is contained in:
Anton Romanov 2017-01-11 21:27:08 -08:00 committed by Alexandre Julliard
parent 0bcc46874f
commit 531dcf2dd3
2 changed files with 73 additions and 2 deletions

View File

@ -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;

View File

@ -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);