server: Support passing to bind a zero sin6_scope_id.
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d3b64637a0
commit
9b257ed63f
|
@ -10679,27 +10679,24 @@ static void test_bind(void)
|
|||
|
||||
addr6.sin6_scope_id = 0;
|
||||
ret = bind(s, (struct sockaddr *)&addr6, sizeof(addr6));
|
||||
todo_wine ok(!ret, "got error %u\n", WSAGetLastError());
|
||||
todo_wine_if (!((const struct sockaddr_in6 *)unicast_addr->Address.lpSockaddr)->sin6_scope_id)
|
||||
ok(!ret, "got error %u\n", WSAGetLastError());
|
||||
|
||||
memcpy(&addr6, unicast_addr->Address.lpSockaddr, sizeof(addr6));
|
||||
|
||||
len = sizeof(struct sockaddr_in6_old);
|
||||
ret = getsockname(s, (struct sockaddr *)&ret_addr6, &len);
|
||||
ok(ret == -1, "expected failure\n");
|
||||
todo_wine_if (addr6.sin6_scope_id)
|
||||
ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
|
||||
ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
|
||||
|
||||
len = sizeof(ret_addr6);
|
||||
memset(&ret_addr6, 0, sizeof(ret_addr6));
|
||||
ret = getsockname(s, (struct sockaddr *)&ret_addr6, &len);
|
||||
todo_wine_if (addr6.sin6_scope_id)
|
||||
{
|
||||
ok(!ret, "got error %u\n", WSAGetLastError());
|
||||
ok(ret_addr6.sin6_family == AF_INET6, "got family %u\n", ret_addr6.sin6_family);
|
||||
ok(ret_addr6.sin6_port != 0, "expected nonzero port\n");
|
||||
ok(!memcmp(&ret_addr6.sin6_addr, &addr6.sin6_addr, sizeof(addr6.sin6_addr)), "address didn't match\n");
|
||||
ok(ret_addr6.sin6_scope_id == addr6.sin6_scope_id, "got scope %u\n", ret_addr6.sin6_scope_id);
|
||||
}
|
||||
ok(!ret, "got error %u\n", WSAGetLastError());
|
||||
ok(ret_addr6.sin6_family == AF_INET6, "got family %u\n", ret_addr6.sin6_family);
|
||||
ok(ret_addr6.sin6_port != 0, "expected nonzero port\n");
|
||||
ok(!memcmp(&ret_addr6.sin6_addr, &addr6.sin6_addr, sizeof(addr6.sin6_addr)), "address didn't match\n");
|
||||
ok(ret_addr6.sin6_scope_id == addr6.sin6_scope_id, "got scope %u\n", ret_addr6.sin6_scope_id);
|
||||
|
||||
closesocket(s);
|
||||
}
|
||||
|
|
|
@ -1849,6 +1849,38 @@ static int bind_to_interface( struct sock *sock, const struct sockaddr_in *addr
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||
static unsigned int get_ipv6_interface_index( const struct in6_addr *addr )
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifaddr;
|
||||
|
||||
if (getifaddrs( &ifaddrs ) < 0) return 0;
|
||||
|
||||
for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next)
|
||||
{
|
||||
if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET6
|
||||
&& !memcmp( &((struct sockaddr_in6 *)ifaddr->ifa_addr)->sin6_addr, addr, sizeof(*addr) ))
|
||||
{
|
||||
unsigned int index = if_nametoindex( ifaddr->ifa_name );
|
||||
|
||||
if (!index)
|
||||
{
|
||||
if (debug_level)
|
||||
fprintf( stderr, "Unable to look up interface index for %s: %s\n",
|
||||
ifaddr->ifa_name, strerror( errno ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
freeifaddrs( ifaddrs );
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs( ifaddrs );
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return an errno value mapped to a WSA error */
|
||||
static unsigned int sock_get_error( int err )
|
||||
{
|
||||
|
@ -2477,12 +2509,22 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
|
|||
}
|
||||
bind_addr = unix_addr;
|
||||
|
||||
if (unix_addr.addr.sa_family == WS_AF_INET)
|
||||
if (unix_addr.addr.sa_family == AF_INET)
|
||||
{
|
||||
if (!memcmp( &unix_addr.in.sin_addr, magic_loopback_addr, 4 )
|
||||
|| bind_to_interface( sock, &unix_addr.in ))
|
||||
bind_addr.in.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
}
|
||||
else if (unix_addr.addr.sa_family == AF_INET6)
|
||||
{
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||
/* Windows allows specifying zero to use the default scope. Linux
|
||||
* interprets it as an interface index and requires that it be
|
||||
* nonzero. */
|
||||
if (!unix_addr.in6.sin6_scope_id)
|
||||
bind_addr.in6.sin6_scope_id = get_ipv6_interface_index( &unix_addr.in6.sin6_addr );
|
||||
#endif
|
||||
}
|
||||
|
||||
if (bind( unix_fd, &bind_addr.addr, unix_len ) < 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue