ws2_32: Reimplement bind() and getsockname() on top of IOCTL_AFD_BIND and IOCTL_AFD_GETSOCKNAME respectively.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a997c3980f
commit
5c009c17b3
|
@ -160,44 +160,8 @@ static const WSAPROTOCOL_INFOW supported_protocols[] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
|
|
||||||
# define LINUX_BOUND_IF
|
|
||||||
struct interface_filter {
|
|
||||||
struct sock_filter iface_memaddr;
|
|
||||||
struct sock_filter iface_rule;
|
|
||||||
struct sock_filter ip_memaddr;
|
|
||||||
struct sock_filter ip_rule;
|
|
||||||
struct sock_filter return_keep;
|
|
||||||
struct sock_filter return_dump;
|
|
||||||
};
|
|
||||||
# define FILTER_JUMP_DUMP(here) (u_char)(offsetof(struct interface_filter, return_dump) \
|
|
||||||
-offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
|
|
||||||
/sizeof(struct sock_filter)
|
|
||||||
# define FILTER_JUMP_KEEP(here) (u_char)(offsetof(struct interface_filter, return_keep) \
|
|
||||||
-offsetof(struct interface_filter, here)-sizeof(struct sock_filter)) \
|
|
||||||
/sizeof(struct sock_filter)
|
|
||||||
# define FILTER_JUMP_NEXT() (u_char)(0)
|
|
||||||
# define SKF_NET_DESTIP 16 /* offset in the network header to the destination IP */
|
|
||||||
static struct interface_filter generic_interface_filter = {
|
|
||||||
/* This filter rule allows incoming packets on the specified interface, which works for all
|
|
||||||
* remotely generated packets and for locally generated broadcast packets. */
|
|
||||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_AD_OFF+SKF_AD_IFINDEX),
|
|
||||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(iface_rule), FILTER_JUMP_NEXT()),
|
|
||||||
/* This rule allows locally generated packets targeted at the specific IP address of the chosen
|
|
||||||
* adapter (local packets not destined for the broadcast address do not have IFINDEX set) */
|
|
||||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, SKF_NET_OFF+SKF_NET_DESTIP),
|
|
||||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0xdeadbeef, FILTER_JUMP_KEEP(ip_rule), FILTER_JUMP_DUMP(ip_rule)),
|
|
||||||
BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* keep packet */
|
|
||||||
BPF_STMT(BPF_RET+BPF_K, 0) /* dump packet */
|
|
||||||
};
|
|
||||||
#endif /* LINUX_BOUND_IF */
|
|
||||||
|
|
||||||
DECLARE_CRITICAL_SECTION(cs_if_addr_cache);
|
|
||||||
DECLARE_CRITICAL_SECTION(cs_socket_list);
|
DECLARE_CRITICAL_SECTION(cs_socket_list);
|
||||||
|
|
||||||
static in_addr_t *if_addr_cache;
|
|
||||||
static unsigned int if_addr_cache_size;
|
|
||||||
|
|
||||||
static SOCKET *socket_list;
|
static SOCKET *socket_list;
|
||||||
static unsigned int socket_list_size;
|
static unsigned int socket_list_size;
|
||||||
|
|
||||||
|
@ -1915,197 +1879,57 @@ static int WINAPI WS2_WSARecvMsg( SOCKET s, LPWSAMSG msg, LPDWORD lpNumberOfByte
|
||||||
lpOverlapped, lpCompletionRoutine, &msg->Control );
|
lpOverlapped, lpCompletionRoutine, &msg->Control );
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* interface_bind (INTERNAL)
|
|
||||||
*
|
|
||||||
* Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
|
|
||||||
* operating only on the specified interface. This restriction consists of two components:
|
|
||||||
* 1) An outgoing packet restriction suggesting the egress interface for all packets.
|
|
||||||
* 2) An incoming packet restriction dropping packets not meant for the interface.
|
|
||||||
* If the function succeeds in placing these restrictions (returns TRUE) then the name for the bind() may
|
|
||||||
* safely be changed to INADDR_ANY, permitting the transmission and receipt of broadcast packets on the
|
|
||||||
* socket. This behavior is only relevant to UDP sockets and is needed for applications that expect to be able
|
|
||||||
* to receive broadcast packets on a socket that is bound to a specific network interface.
|
|
||||||
*/
|
|
||||||
static BOOL interface_bind( SOCKET s, int fd, struct sockaddr *addr )
|
|
||||||
{
|
|
||||||
#if defined(HAVE_GETIFADDRS) && (defined(IP_BOUND_IF) || defined(LINUX_BOUND_IF))
|
|
||||||
struct sockaddr_in *in_sock = (struct sockaddr_in *) addr;
|
|
||||||
in_addr_t bind_addr = in_sock->sin_addr.s_addr;
|
|
||||||
struct ifaddrs *ifaddrs, *ifaddr;
|
|
||||||
unsigned int index;
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
int enable = 1;
|
|
||||||
|
|
||||||
if (bind_addr == htonl(INADDR_ANY) || bind_addr == htonl(INADDR_LOOPBACK))
|
|
||||||
return FALSE; /* Not binding to a network adapter, special interface binding unnecessary. */
|
|
||||||
if (_get_fd_type(fd) != SOCK_DGRAM)
|
|
||||||
return FALSE; /* Special interface binding is only necessary for UDP datagrams. */
|
|
||||||
|
|
||||||
if (getifaddrs( &ifaddrs ) < 0) return FALSE;
|
|
||||||
|
|
||||||
for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next)
|
|
||||||
{
|
|
||||||
if (ifaddr->ifa_addr && ifaddr->ifa_addr->sa_family == AF_INET
|
|
||||||
&& ((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr == bind_addr)
|
|
||||||
{
|
|
||||||
index = if_nametoindex( ifaddr->ifa_name );
|
|
||||||
if (!index)
|
|
||||||
{
|
|
||||||
ERR( "Unable to look up interface index for %s: %s\n", ifaddr->ifa_name, strerror( errno ) );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(IP_BOUND_IF)
|
|
||||||
/* IP_BOUND_IF sets both the incoming and outgoing restriction at once */
|
|
||||||
if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &index, sizeof(index)) != 0)
|
|
||||||
goto cleanup;
|
|
||||||
ret = TRUE;
|
|
||||||
#elif defined(LINUX_BOUND_IF)
|
|
||||||
{
|
|
||||||
in_addr_t ifindex = (in_addr_t) htonl(index);
|
|
||||||
struct interface_filter specific_interface_filter;
|
|
||||||
struct sock_fprog filter_prog;
|
|
||||||
|
|
||||||
if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)) != 0)
|
|
||||||
goto cleanup; /* Failed to suggest egress interface */
|
|
||||||
specific_interface_filter = generic_interface_filter;
|
|
||||||
specific_interface_filter.iface_rule.k = index;
|
|
||||||
specific_interface_filter.ip_rule.k = htonl(bind_addr);
|
|
||||||
filter_prog.len = sizeof(generic_interface_filter)/sizeof(struct sock_filter);
|
|
||||||
filter_prog.filter = (struct sock_filter *) &specific_interface_filter;
|
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) != 0)
|
|
||||||
goto cleanup; /* Failed to specify incoming packet filter */
|
|
||||||
ret = TRUE;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&cs_if_addr_cache);
|
|
||||||
if (if_addr_cache_size <= index)
|
|
||||||
{
|
|
||||||
unsigned int new_size;
|
|
||||||
in_addr_t *new;
|
|
||||||
|
|
||||||
new_size = max(if_addr_cache_size * 2, index + 1);
|
|
||||||
if (!(new = heap_realloc(if_addr_cache, sizeof(*if_addr_cache) * new_size)))
|
|
||||||
{
|
|
||||||
ERR("No memory.\n");
|
|
||||||
ret = FALSE;
|
|
||||||
LeaveCriticalSection(&cs_if_addr_cache);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memset(new + if_addr_cache_size, 0, sizeof(*if_addr_cache)
|
|
||||||
* (new_size - if_addr_cache_size));
|
|
||||||
if_addr_cache = new;
|
|
||||||
if_addr_cache_size = new_size;
|
|
||||||
}
|
|
||||||
if (if_addr_cache[index] && if_addr_cache[index] != bind_addr)
|
|
||||||
WARN("Adapter addr for iface index %u has changed.\n", index);
|
|
||||||
|
|
||||||
if_addr_cache[index] = bind_addr;
|
|
||||||
LeaveCriticalSection(&cs_if_addr_cache);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Will soon be switching to INADDR_ANY: permit address reuse */
|
|
||||||
if (ret && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == 0)
|
|
||||||
TRACE("Socket %04lx bound to interface index %d\n", s, index);
|
|
||||||
else
|
|
||||||
ret = FALSE;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if(!ret)
|
|
||||||
ERR("Failed to bind to interface, receiving broadcast packets will not work on socket %04lx.\n", s);
|
|
||||||
freeifaddrs( ifaddrs );
|
|
||||||
return ret;
|
|
||||||
#else
|
|
||||||
FIXME( "Broadcast packets on interface-bound sockets are not currently supported on this platform.\n" );
|
|
||||||
return FALSE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* bind (WS2_32.2)
|
* bind (ws2_32.2)
|
||||||
*/
|
*/
|
||||||
int WINAPI WS_bind(SOCKET s, const struct WS_sockaddr* name, int namelen)
|
int WINAPI WS_bind( SOCKET s, const struct WS_sockaddr *addr, int len )
|
||||||
{
|
{
|
||||||
int fd = get_sock_fd( s, 0, NULL );
|
struct afd_bind_params *params;
|
||||||
int res = SOCKET_ERROR;
|
struct WS_sockaddr *ret_addr;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
HANDLE sync_event;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
|
TRACE( "socket %#lx, addr %s\n", s, debugstr_sockaddr(addr) );
|
||||||
|
|
||||||
if (fd != -1)
|
if (!addr || (addr->sa_family && !supported_pf( addr->sa_family )))
|
||||||
{
|
{
|
||||||
if (!name || (name->sa_family && !supported_pf(name->sa_family)))
|
SetLastError( WSAEAFNOSUPPORT );
|
||||||
{
|
return -1;
|
||||||
SetLastError(WSAEAFNOSUPPORT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
union generic_unix_sockaddr uaddr;
|
|
||||||
unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
|
|
||||||
if (!uaddrlen)
|
|
||||||
{
|
|
||||||
SetLastError(WSAEFAULT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (name->sa_family == WS_AF_INET)
|
|
||||||
{
|
|
||||||
struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
|
|
||||||
if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
|
|
||||||
{
|
|
||||||
/* Trying to bind to the default host interface, using
|
|
||||||
* INADDR_ANY instead*/
|
|
||||||
WARN("Trying to bind to magic IP address, using "
|
|
||||||
"INADDR_ANY instead.\n");
|
|
||||||
in4->sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
}
|
|
||||||
else if (interface_bind(s, fd, &uaddr.addr))
|
|
||||||
in4->sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
}
|
|
||||||
if (bind(fd, &uaddr.addr, uaddrlen) < 0)
|
|
||||||
{
|
|
||||||
int loc_errno = errno;
|
|
||||||
WARN("\tfailure - errno = %i\n", errno);
|
|
||||||
errno = loc_errno;
|
|
||||||
switch (errno)
|
|
||||||
{
|
|
||||||
case EADDRNOTAVAIL:
|
|
||||||
SetLastError(WSAEINVAL);
|
|
||||||
break;
|
|
||||||
case EADDRINUSE:
|
|
||||||
{
|
|
||||||
int optval = 0;
|
|
||||||
socklen_t optlen = sizeof(optval);
|
|
||||||
/* Windows >= 2003 will return different results depending on
|
|
||||||
* SO_REUSEADDR, WSAEACCES may be returned representing that
|
|
||||||
* the socket hijacking protection prevented the bind */
|
|
||||||
if (!getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, &optlen) && optval)
|
|
||||||
{
|
|
||||||
SetLastError(WSAEACCES);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* fall through */
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
SetLastError(wsaErrno());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res=0; /* success */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
release_sock_fd( s, fd );
|
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
if (!(sync_event = get_sync_event())) return -1;
|
||||||
|
|
||||||
|
params = HeapAlloc( GetProcessHeap(), 0, sizeof(int) + len );
|
||||||
|
ret_addr = HeapAlloc( GetProcessHeap(), 0, len );
|
||||||
|
if (!params || !ret_addr)
|
||||||
|
{
|
||||||
|
HeapFree( GetProcessHeap(), 0, params );
|
||||||
|
HeapFree( GetProcessHeap(), 0, ret_addr );
|
||||||
|
SetLastError( WSAENOBUFS );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
params->unknown = 0;
|
||||||
|
memcpy( ¶ms->addr, addr, len );
|
||||||
|
|
||||||
|
status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_BIND,
|
||||||
|
params, sizeof(int) + len, ret_addr, len );
|
||||||
|
if (status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED)
|
||||||
|
return -1;
|
||||||
|
status = io.u.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree( GetProcessHeap(), 0, params );
|
||||||
|
HeapFree( GetProcessHeap(), 0, ret_addr );
|
||||||
|
|
||||||
|
SetLastError( status == STATUS_INVALID_PARAMETER ? WSAEFAULT : NtStatusToWSAError( status ) );
|
||||||
|
return status ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* closesocket (WS2_32.3)
|
* closesocket (WS2_32.3)
|
||||||
*/
|
*/
|
||||||
|
@ -2339,98 +2163,28 @@ int WINAPI WS_getpeername(SOCKET s, struct WS_sockaddr *name, int *namelen)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When binding to an UDP address with filter support the getsockname call on the socket
|
|
||||||
* will always return 0.0.0.0 instead of the filtered interface address. This function
|
|
||||||
* checks if the socket is interface-bound on UDP and return the correct address.
|
|
||||||
* This is required because applications often do a bind() with port zero followed by a
|
|
||||||
* getsockname() to retrieve the port and address acquired.
|
|
||||||
*/
|
|
||||||
static void interface_bind_check(int fd, struct sockaddr_in *addr)
|
|
||||||
{
|
|
||||||
#if !defined(IP_BOUND_IF) && !defined(LINUX_BOUND_IF)
|
|
||||||
return;
|
|
||||||
#else
|
|
||||||
unsigned int ifindex;
|
|
||||||
int ret;
|
|
||||||
socklen_t len;
|
|
||||||
|
|
||||||
/* Check for IPv4, address 0.0.0.0 and UDP socket */
|
|
||||||
if (addr->sin_family != AF_INET || addr->sin_addr.s_addr != 0)
|
|
||||||
return;
|
|
||||||
if (_get_fd_type(fd) != SOCK_DGRAM)
|
|
||||||
return;
|
|
||||||
|
|
||||||
len = sizeof(ifindex);
|
|
||||||
#if defined(IP_BOUND_IF)
|
|
||||||
ret = getsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &ifindex, &len);
|
|
||||||
#elif defined(LINUX_BOUND_IF)
|
|
||||||
ret = getsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, &len);
|
|
||||||
if (!ret) ifindex = ntohl(ifindex);
|
|
||||||
#endif
|
|
||||||
if (!ret && ifindex)
|
|
||||||
{
|
|
||||||
EnterCriticalSection(&cs_if_addr_cache);
|
|
||||||
if (ifindex < if_addr_cache_size)
|
|
||||||
addr->sin_addr.s_addr = if_addr_cache[ifindex];
|
|
||||||
else
|
|
||||||
ERR("No cache entry for ifindex %u.\n", ifindex);
|
|
||||||
LeaveCriticalSection(&cs_if_addr_cache);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* getsockname (WS2_32.6)
|
* getsockname (ws2_32.6)
|
||||||
*/
|
*/
|
||||||
int WINAPI WS_getsockname(SOCKET s, struct WS_sockaddr *name, int *namelen)
|
int WINAPI WS_getsockname( SOCKET s, struct WS_sockaddr *addr, int *len )
|
||||||
{
|
{
|
||||||
int fd;
|
IO_STATUS_BLOCK io;
|
||||||
int res;
|
NTSTATUS status;
|
||||||
|
|
||||||
TRACE("socket %04lx, ptr %p, len %08x\n", s, name, namelen ? *namelen : 0);
|
TRACE( "socket %#lx, addr %p, len %d\n", s, addr, len ? *len : 0 );
|
||||||
|
|
||||||
/* Check if what we've received is valid. Should we use IsBadReadPtr? */
|
if (!addr)
|
||||||
if( (name == NULL) || (namelen == NULL) )
|
|
||||||
{
|
{
|
||||||
SetLastError( WSAEFAULT );
|
SetLastError( WSAEFAULT );
|
||||||
return SOCKET_ERROR;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = get_sock_fd( s, 0, NULL );
|
status = NtDeviceIoControlFile( (HANDLE)s, NULL, NULL, NULL, &io, IOCTL_AFD_GETSOCKNAME, NULL, 0, addr, *len );
|
||||||
res = SOCKET_ERROR;
|
if (!status)
|
||||||
|
*len = io.Information;
|
||||||
if (fd != -1)
|
WSASetLastError( NtStatusToWSAError( status ) );
|
||||||
{
|
return status ? -1 : 0;
|
||||||
union generic_unix_sockaddr uaddr;
|
|
||||||
socklen_t uaddrlen;
|
|
||||||
int bound = is_fd_bound(fd, &uaddr, &uaddrlen);
|
|
||||||
|
|
||||||
if (bound <= 0)
|
|
||||||
{
|
|
||||||
SetLastError(bound == -1 ? wsaErrno() : WSAEINVAL);
|
|
||||||
}
|
|
||||||
else if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
|
|
||||||
{
|
|
||||||
/* The buffer was too small */
|
|
||||||
SetLastError(WSAEFAULT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
interface_bind_check(fd, (struct sockaddr_in*) &uaddr);
|
|
||||||
if (ws_sockaddr_u2ws(&uaddr.addr, name, namelen) != 0)
|
|
||||||
{
|
|
||||||
/* The buffer was too small */
|
|
||||||
SetLastError(WSAEFAULT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
res = 0;
|
|
||||||
TRACE("=> %s\n", debugstr_sockaddr(name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
release_sock_fd( s, fd );
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -1549,13 +1549,13 @@ static void test_getsockname(void)
|
||||||
memset(&addr, 0xcc, sizeof(addr));
|
memset(&addr, 0xcc, sizeof(addr));
|
||||||
ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
|
ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io,
|
||||||
IOCTL_AFD_GETSOCKNAME, NULL, 0, &addr, sizeof(addr));
|
IOCTL_AFD_GETSOCKNAME, NULL, 0, &addr, sizeof(addr));
|
||||||
todo_wine ok(!ret, "got %#x\n", ret);
|
ok(!ret, "got %#x\n", ret);
|
||||||
todo_wine ok(!io.Status, "got %#x\n", io.Status);
|
ok(!io.Status, "got %#x\n", io.Status);
|
||||||
todo_wine ok(io.Information == sizeof(addr), "got %#Ix\n", io.Information);
|
ok(io.Information == sizeof(addr), "got %#Ix\n", io.Information);
|
||||||
len = sizeof(addr2);
|
len = sizeof(addr2);
|
||||||
ret = getsockname(client, (struct sockaddr *)&addr2, &len);
|
ret = getsockname(client, (struct sockaddr *)&addr2, &len);
|
||||||
ok(!ret, "got error %u\n", WSAGetLastError());
|
ok(!ret, "got error %u\n", WSAGetLastError());
|
||||||
todo_wine ok(!memcmp(&addr, &addr2, sizeof(struct sockaddr)), "addresses didn't match\n");
|
ok(!memcmp(&addr, &addr2, sizeof(struct sockaddr)), "addresses didn't match\n");
|
||||||
|
|
||||||
closesocket(client);
|
closesocket(client);
|
||||||
|
|
||||||
|
|
|
@ -10292,7 +10292,7 @@ static void test_bind(void)
|
||||||
WSASetLastError(0xdeadbeef);
|
WSASetLastError(0xdeadbeef);
|
||||||
ret = bind(s, (const struct sockaddr *)&invalid_addr, sizeof(invalid_addr));
|
ret = bind(s, (const struct sockaddr *)&invalid_addr, sizeof(invalid_addr));
|
||||||
ok(ret == -1, "expected failure\n");
|
ok(ret == -1, "expected failure\n");
|
||||||
todo_wine ok(WSAGetLastError() == WSAEADDRNOTAVAIL, "got error %u\n", WSAGetLastError());
|
ok(WSAGetLastError() == WSAEADDRNOTAVAIL, "got error %u\n", WSAGetLastError());
|
||||||
|
|
||||||
WSASetLastError(0xdeadbeef);
|
WSASetLastError(0xdeadbeef);
|
||||||
ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
|
ret = bind(s, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
|
||||||
|
|
|
@ -89,9 +89,6 @@
|
||||||
# undef if_indextoname
|
# undef if_indextoname
|
||||||
# undef if_nametoindex
|
# undef if_nametoindex
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LINUX_FILTER_H
|
|
||||||
# include <linux/filter.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_IFADDRS_H
|
#ifdef HAVE_IFADDRS_H
|
||||||
# include <ifaddrs.h>
|
# include <ifaddrs.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -151,7 +148,6 @@
|
||||||
#include "winnt.h"
|
#include "winnt.h"
|
||||||
#define USE_WC_PREFIX /* For CMSG_DATA */
|
#define USE_WC_PREFIX /* For CMSG_DATA */
|
||||||
#include "iphlpapi.h"
|
#include "iphlpapi.h"
|
||||||
#include "netioapi.h"
|
|
||||||
#include "ip2string.h"
|
#include "ip2string.h"
|
||||||
#include "wine/afd.h"
|
#include "wine/afd.h"
|
||||||
#include "wine/server.h"
|
#include "wine/server.h"
|
||||||
|
|
Loading…
Reference in New Issue