ws2_32: Track SO_EXCLUSIVEADDRUSE option value.

This commit is contained in:
Paul Gofman 2022-10-31 12:46:08 -06:00 committed by Alexandre Julliard
parent 1178a9dd3a
commit d656cb2024
4 changed files with 49 additions and 6 deletions

View file

@ -1818,6 +1818,11 @@ int WINAPI getsockopt( SOCKET s, int level, int optname, char *optval, int *optl
if (!ret && *optlen < sizeof(DWORD)) *optlen = 1;
return ret;
case SO_EXCLUSIVEADDRUSE:
ret = server_getsockopt( s, IOCTL_AFD_WINE_GET_SO_EXCLUSIVEADDRUSE, optval, optlen );
if (!ret && *optlen < sizeof(DWORD)) *optlen = 1;
return ret;
case SO_SNDBUF:
if (*optlen < sizeof(DWORD) || !optval)
{
@ -3215,6 +3220,15 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
memcpy( &value, optval, min( optlen, sizeof(value) ));
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_REUSEADDR, (char *)&value, sizeof(value) );
case SO_EXCLUSIVEADDRUSE:
if (!optval)
{
SetLastError( WSAEFAULT );
return SOCKET_ERROR;
}
memcpy( &value, optval, min( optlen, sizeof(value) ));
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_EXCLUSIVEADDRUSE, (char *)&value, sizeof(value) );
case SO_SNDBUF:
if (optlen < 0) optlen = 4;
return server_setsockopt( s, IOCTL_AFD_WINE_SET_SO_SNDBUF, optval, optlen );
@ -3240,12 +3254,6 @@ int WINAPI setsockopt( SOCKET s, int level, int optname, const char *optval, int
SetLastError( ERROR_SUCCESS );
return 0;
/* Stops two sockets from being bound to the same port. Always happens
* on unix systems, so just drop it. */
case SO_EXCLUSIVEADDRUSE:
TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
return 0;
/* After a ConnectEx call succeeds, the socket can't be used with half of the
* normal winsock functions on windows. We don't have that problem. */
case SO_UPDATE_CONNECT_CONTEXT:

View file

@ -1209,6 +1209,7 @@ static void test_set_getsockopt(void)
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_DONTROUTE, TRUE, {1, 1, 1}, {0}, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_RCVTIMEO, FALSE, {1, 2, 4}, {0}, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR, TRUE, {1, 1, 4}, {0, 0xdead0001, 0}, TRUE, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, TRUE, {1, 1, 4}, {0, 0xdead0001, 0}, TRUE, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_SNDBUF, FALSE, {1, 2, 4}, {0xdeadbe00, 0xdead0000}, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_SNDTIMEO, FALSE, {1, 2, 4}, {0}, TRUE},
{AF_INET, SOCK_STREAM, SOL_SOCKET, SO_OPENTYPE, FALSE, {1, 2, 4}, {0}, TRUE},

View file

@ -283,6 +283,8 @@ C_ASSERT( sizeof(struct afd_get_events_params) == 56 );
#define IOCTL_AFD_WINE_SET_IP_RECVTTL WINE_AFD_IOC(294)
#define IOCTL_AFD_WINE_GET_IP_RECVTOS WINE_AFD_IOC(295)
#define IOCTL_AFD_WINE_SET_IP_RECVTOS WINE_AFD_IOC(296)
#define IOCTL_AFD_WINE_GET_SO_EXCLUSIVEADDRUSE WINE_AFD_IOC(297)
#define IOCTL_AFD_WINE_SET_SO_EXCLUSIVEADDRUSE WINE_AFD_IOC(298)
struct afd_iovec
{

View file

@ -256,6 +256,7 @@ struct sock
unsigned int bound : 1; /* is the socket bound? */
unsigned int reset : 1; /* did we get a TCP reset? */
unsigned int reuseaddr : 1; /* winsock SO_REUSEADDR option value */
unsigned int exclusiveaddruse : 1; /* winsock SO_EXCLUSIVEADDRUSE option value */
};
static int is_tcp_socket( struct sock *sock )
@ -1697,6 +1698,7 @@ static struct sock *create_socket(void)
sock->bound = 0;
sock->reset = 0;
sock->reuseaddr = 0;
sock->exclusiveaddruse = 0;
sock->rcvbuf = 0;
sock->sndbuf = 0;
sock->rcvtimeo = 0;
@ -3103,6 +3105,21 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
return;
}
case IOCTL_AFD_WINE_SET_SO_EXCLUSIVEADDRUSE:
{
int exclusive;
if (get_req_data_size() < sizeof(exclusive))
{
set_error( STATUS_BUFFER_TOO_SMALL );
return;
}
exclusive = *(int *)get_req_data();
sock->exclusiveaddruse = !!exclusive;
return;
}
case IOCTL_AFD_WINE_GET_SO_SNDBUF:
{
int sndbuf = sock->sndbuf;
@ -3205,6 +3222,21 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
return;
}
case IOCTL_AFD_WINE_GET_SO_EXCLUSIVEADDRUSE:
{
int exclusive;
if (!get_reply_max_size())
{
set_error( STATUS_BUFFER_TOO_SMALL );
return;
}
exclusive = sock->exclusiveaddruse;
set_reply_data( &exclusive, min( sizeof(exclusive), get_reply_max_size() ));
return;
}
case IOCTL_AFD_POLL:
{
if (get_reply_max_size() < get_req_data_size())