Commit 1178a9dd authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ws2_32/tests: Add tests for SO_EXCLUSIVEADDRUSE.

parent d2307e41
......@@ -2013,9 +2013,10 @@ static void test_set_getsockopt(void)
}
}
static void test_so_reuseaddr(void)
static void test_reuseaddr(void)
{
static struct sockaddr_in6 saddr_in6_any, saddr_in6_loopback;
static struct sockaddr_in6 saddr_in6_any_v4mapped, saddr_in6_loopback_v4mapped;
static struct sockaddr_in saddr_in_any, saddr_in_loopback;
static const struct
......@@ -2030,10 +2031,132 @@ static void test_so_reuseaddr(void)
{ AF_INET, (struct sockaddr *)&saddr_in_any, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_any) },
{ AF_INET6, (struct sockaddr *)&saddr_in6_any, (struct sockaddr *)&saddr_in6_loopback, sizeof(saddr_in6_any) },
};
unsigned int rc, reuse;
static const struct
{
struct
{
int domain;
struct sockaddr *addr;
socklen_t addrlen;
BOOL exclusive;
}
s[2];
int error;
BOOL todo;
}
tests_exclusive[] =
{
{
{{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, }},
WSAEACCES, TRUE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_any, sizeof(saddr_in6_any), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, }},
WSAEACCES, TRUE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, }},
NOERROR,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, }},
WSAEACCES, TRUE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, }},
NOERROR,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, }},
WSAEADDRINUSE, TRUE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, },
{ AF_INET6, (struct sockaddr *)&saddr_in6_any, sizeof(saddr_in6_any), TRUE, }},
WSAEADDRINUSE, TRUE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback, sizeof(saddr_in6_loopback), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, }},
NOERROR,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback, sizeof(saddr_in6_loopback), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, }},
NOERROR,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback_v4mapped, sizeof(saddr_in6_loopback_v4mapped), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, }},
WSAEADDRINUSE, TRUE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_any, sizeof(saddr_in6_any), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, }},
WSAEACCES, TRUE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_any, sizeof(saddr_in6_any), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, }},
NOERROR, TRUE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), TRUE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_any, sizeof(saddr_in6_any), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, }},
NOERROR, TRUE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_any_v4mapped, sizeof(saddr_in6_any_v4mapped), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_any, sizeof(saddr_in_any), FALSE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback_v4mapped, sizeof(saddr_in6_loopback_v4mapped), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, },
{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback_v4mapped, sizeof(saddr_in6_loopback_v4mapped), FALSE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET6, (struct sockaddr *)&saddr_in6_loopback, sizeof(saddr_in6_loopback), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, }},
NOERROR,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, }},
WSAEADDRINUSE,
},
{
{{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), FALSE, },
{ AF_INET, (struct sockaddr *)&saddr_in_loopback, sizeof(saddr_in_loopback), TRUE, }},
WSAEADDRINUSE,
},
};
unsigned int rc, reuse, value;
struct sockaddr saddr;
SOCKET s1, s2, s3, s4;
unsigned int i;
unsigned int i, j;
int size;
saddr_in_any.sin_family = AF_INET;
......@@ -2048,6 +2171,14 @@ static void test_so_reuseaddr(void)
saddr_in6_loopback = saddr_in6_any;
inet_pton(AF_INET6, "::1", &saddr_in6_loopback.sin6_addr);
saddr_in6_loopback_v4mapped = saddr_in6_any;
rc = inet_pton(AF_INET6, "::ffff:127.0.0.1", &saddr_in6_loopback_v4mapped.sin6_addr);
ok(rc, "got error %d.\n", WSAGetLastError());
saddr_in6_any_v4mapped = saddr_in6_any;
rc = inet_pton(AF_INET6, "::ffff:0.0.0.0", &saddr_in6_any_v4mapped.sin6_addr);
ok(rc, "got error %d.\n", WSAGetLastError());
for (i = 0; i < ARRAY_SIZE(tests); ++i)
{
winetest_push_context("test %u", i);
......@@ -2210,6 +2341,75 @@ static void test_so_reuseaddr(void)
winetest_pop_context();
}
/* SO_REUSEADDR and SO_EXCLUSIVEADDRUSE are mutually exclusive. */
s1 = socket(AF_INET, SOCK_STREAM, 0);
ok(s1 != INVALID_SOCKET, "got error %d.\n", WSAGetLastError());
value = 1;
rc = setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
ok(!rc, "got error %d.\n", WSAGetLastError());
value = 1;
rc = setsockopt(s1, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&value, sizeof(value));
todo_wine ok(rc == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, "got rc %d, error %d.\n", rc, WSAGetLastError());
value = 0;
rc = setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
value = 1;
rc = setsockopt(s1, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&value, sizeof(value));
ok(!rc, "got error %d.\n", WSAGetLastError());
value = 1;
rc = setsockopt(s1, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(value));
todo_wine ok(rc == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, "got rc %d, error %d.\n", rc, WSAGetLastError());
closesocket(s1);
/* Test SO_EXCLUSIVEADDRUSE. */
for (i = 0; i < ARRAY_SIZE(tests_exclusive); ++i)
{
SOCKET s[2];
winetest_push_context("test %u", i);
for (j = 0; j < 2; ++j)
{
s[j] = socket(tests_exclusive[i].s[j].domain, SOCK_STREAM, 0);
ok(s[j] != INVALID_SOCKET, "got error %d.\n", WSAGetLastError());
if (tests_exclusive[i].s[j].exclusive)
{
value = 1;
rc = setsockopt(s[j], SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&value, sizeof(value));
ok(!rc, "got error %d.\n", WSAGetLastError());
}
if (tests_exclusive[i].s[j].domain == AF_INET6)
{
value = 0;
rc = setsockopt(s[j], IPPROTO_IPV6, IPV6_V6ONLY, (char*)&value, sizeof(value));
ok(!rc, "got error %d.\n", WSAGetLastError());
}
}
rc = bind(s[0], tests_exclusive[i].s[0].addr, tests_exclusive[i].s[0].addrlen);
ok(!rc, "got error %d.\n", WSAGetLastError());
rc = bind(s[1], tests_exclusive[i].s[1].addr, tests_exclusive[i].s[1].addrlen);
todo_wine_if(tests_exclusive[i].todo)
{
if (tests_exclusive[i].error)
ok(rc == SOCKET_ERROR && WSAGetLastError() == tests_exclusive[i].error,
"got rc %d, error %d, expected error %d.\n", rc, WSAGetLastError(), tests_exclusive[i].error);
else
ok(!rc, "got error %d.\n", WSAGetLastError());
}
closesocket(s[0]);
closesocket(s[1]);
winetest_pop_context();
}
}
#define IP_PKTINFO_LEN (sizeof(WSACMSGHDR) + WSA_CMSG_ALIGN(sizeof(struct in_pktinfo)))
......@@ -13389,7 +13589,7 @@ START_TEST( sock )
Init();
test_set_getsockopt();
test_so_reuseaddr();
test_reuseaddr();
test_ip_pktinfo();
test_ipv4_cmsg();
test_ipv6_cmsg();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment