mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 06:00:45 +00:00
ws2_32: Fix the default behavior of IPV6_V6ONLY.
Signed-off-by: Roman Pišl <rpisl@seznam.cz> Signed-off-by: Bruno Jesus <00cpxxx@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d787f0d9c6
commit
96eb36e4bb
@ -3240,20 +3240,6 @@ int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef IPV6_V6ONLY
|
||||
const struct sockaddr_in6 *in6 = (const struct sockaddr_in6*) &uaddr;
|
||||
if (name->sa_family == WS_AF_INET6 &&
|
||||
!memcmp(&in6->sin6_addr, &in6addr_any, sizeof(struct in6_addr)))
|
||||
{
|
||||
int enable = 1;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)) == -1)
|
||||
{
|
||||
release_sock_fd( s, fd );
|
||||
SetLastError(WSAEAFNOSUPPORT);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (name->sa_family == WS_AF_INET)
|
||||
{
|
||||
struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
|
||||
@ -7241,6 +7227,21 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
|
||||
TRACE("\tcreated %04lx\n", ret );
|
||||
if (ipxptype > 0)
|
||||
set_ipx_packettype(ret, ipxptype);
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
if (unixaf == AF_INET6)
|
||||
{
|
||||
int fd = get_sock_fd(ret, 0, NULL);
|
||||
if (fd != -1)
|
||||
{
|
||||
/* IPV6_V6ONLY is set by default on Windows */
|
||||
int enable = 1;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)))
|
||||
WARN("\tsetting IPV6_V6ONLY failed - errno = %i\n", errno);
|
||||
release_sock_fd(ret, fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1732,7 +1732,7 @@ static void test_so_reuseaddr(void)
|
||||
DWORD err;
|
||||
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(9375);
|
||||
saddr.sin_port = htons(SERVERPORT+1);
|
||||
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
s1=socket(AF_INET, SOCK_STREAM, 0);
|
||||
@ -6105,11 +6105,10 @@ end:
|
||||
|
||||
static void test_ipv6only(void)
|
||||
{
|
||||
SOCKET v4 = INVALID_SOCKET,
|
||||
v6 = INVALID_SOCKET;
|
||||
SOCKET v4 = INVALID_SOCKET, v6;
|
||||
struct sockaddr_in sin4;
|
||||
struct sockaddr_in6 sin6;
|
||||
int ret;
|
||||
int ret, enabled, len = sizeof(enabled);
|
||||
|
||||
memset(&sin4, 0, sizeof(sin4));
|
||||
sin4.sin_family = AF_INET;
|
||||
@ -6120,27 +6119,83 @@ static void test_ipv6only(void)
|
||||
sin6.sin6_port = htons(SERVERPORT);
|
||||
|
||||
v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (v6 == INVALID_SOCKET) {
|
||||
skip("Could not create IPv6 socket (LastError: %d; %d expected if IPv6 not available).\n",
|
||||
WSAGetLastError(), WSAEAFNOSUPPORT);
|
||||
if (v6 == INVALID_SOCKET)
|
||||
{
|
||||
skip("Could not create IPv6 socket (LastError: %d)\n", WSAGetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
enabled = 2;
|
||||
ret = getsockopt(v6, 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);
|
||||
|
||||
ret = bind(v6, (struct sockaddr*)&sin6, sizeof(sin6));
|
||||
if (ret) {
|
||||
skip("Could not bind IPv6 address (LastError: %d).\n",
|
||||
WSAGetLastError());
|
||||
if (ret)
|
||||
{
|
||||
skip("Could not bind IPv6 address (LastError: %d)\n", WSAGetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (v4 == INVALID_SOCKET) {
|
||||
skip("Could not create IPv4 socket (LastError: %d).\n",
|
||||
WSAGetLastError());
|
||||
goto end;
|
||||
}
|
||||
ok(v4 != INVALID_SOCKET, "Could not create IPv6 socket (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; %d expected if IPv6 binds to IPv4 as well).\n",
|
||||
WSAGetLastError(), WSAEADDRINUSE);
|
||||
ok(!ret, "Could not bind IPv4 address (LastError: %d)\n", WSAGetLastError());
|
||||
|
||||
closesocket(v4);
|
||||
closesocket(v6);
|
||||
|
||||
/* Test again, this time disabling IPV6_V6ONLY. */
|
||||
sin4.sin_port = htons(SERVERPORT+2);
|
||||
sin6.sin6_port = htons(SERVERPORT+2);
|
||||
|
||||
v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
ok(v6 != INVALID_SOCKET, "Could not create IPv6 socket (LastError: %d; %d expected if IPv6 not available).\n",
|
||||
WSAGetLastError(), WSAEAFNOSUPPORT);
|
||||
|
||||
enabled = 0;
|
||||
ret = setsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, len);
|
||||
ok(!ret, "Could not disable IPV6_V6ONLY (LastError: %d).\n", WSAGetLastError());
|
||||
|
||||
enabled = 2;
|
||||
ret = getsockopt(v6, 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);
|
||||
|
||||
/*
|
||||
Observaition:
|
||||
On Windows, bind on both IPv4 and IPv6 with IPV6_V6ONLY disabled succeeds by default.
|
||||
Application must set SO_EXCLUSIVEADDRUSE on first socket to disallow another successful bind.
|
||||
In general, a standard application should not use SO_REUSEADDR.
|
||||
Setting both SO_EXCLUSIVEADDRUSE and SO_REUSEADDR on the same socket is not possible in
|
||||
either order, the later setsockopt call always fails.
|
||||
*/
|
||||
enabled = 1;
|
||||
ret = setsockopt(v6, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&enabled, len);
|
||||
ok(!ret, "Could not set SO_EXCLUSIVEADDRUSE on IPv6 socket (LastError: %d)\n", WSAGetLastError());
|
||||
|
||||
ret = bind(v6, (struct sockaddr*)&sin6, sizeof(sin6));
|
||||
ok(!ret, "Could not bind IPv6 address (LastError: %d)\n", WSAGetLastError());
|
||||
|
||||
enabled = 2;
|
||||
len = sizeof(enabled);
|
||||
getsockopt(v6, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&enabled, &len);
|
||||
ok(!ret, "getsockopt(IPV6_ONLY) failed (LastError: %d)\n", WSAGetLastError());
|
||||
ok(!enabled, "IPV6_V6ONLY is enabled after bind\n");
|
||||
|
||||
v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
ok(v4 != INVALID_SOCKET, "Could not create IPv4 socket (LastError: %d)\n", WSAGetLastError());
|
||||
|
||||
enabled = 1;
|
||||
ret = setsockopt(v4, SOL_SOCKET, SO_REUSEADDR, (char*)&enabled, len);
|
||||
ok(!ret, "Could not set SO_REUSEADDR on IPv4 socket (LastError: %d)\n", WSAGetLastError());
|
||||
|
||||
WSASetLastError(0xdeadbeef);
|
||||
ret = bind(v4, (struct sockaddr*)&sin4, sizeof(sin4));
|
||||
ok(ret, "bind succeeded unexpectedly for the IPv4 socket\n");
|
||||
ok(WSAGetLastError() == WSAEACCES, "Expected 10013, got %d\n", WSAGetLastError());
|
||||
|
||||
end:
|
||||
if (v4 != INVALID_SOCKET)
|
||||
@ -8024,7 +8079,7 @@ static void test_TransmitFile(void)
|
||||
/* Setup a properly connected socket for transfers */
|
||||
memset(&bindAddress, 0, sizeof(bindAddress));
|
||||
bindAddress.sin_family = AF_INET;
|
||||
bindAddress.sin_port = htons(9375);
|
||||
bindAddress.sin_port = htons(SERVERPORT+1);
|
||||
bindAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
iret = bind(server, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
|
||||
if (iret != 0)
|
||||
|
Loading…
Reference in New Issue
Block a user