sws: fix binding to unix socket on Windows

Windows 10.17063+ (having unix socket support) fails to set for unix
sockets the `SO_REUSEADDR` option, with error 10045 (`WSAEOPNOTSUPP`),
and also fails to set `SO_KEEPALIVE` with error 10042 (`WSAENOPROTOOPT`).

Fix by not enabling these socket options on Windows for unix sockets.

Also:
- fixing test 1435, 1436 to run in CI.
- fixing the `socksd` test server for test 1467, 1468, 1470. But, also
  disable these for now due to another Windows issue: #19825

Ref: https://stackoverflow.com/questions/68791319/unix-domain-socket-bind-failed-in-windows/68794755#68794755
Ref: #19810
Closes #19812
This commit is contained in:
Viktor Szakats 2025-12-02 17:45:18 +01:00
parent dfd781ff62
commit f97e62ff14
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
5 changed files with 70 additions and 45 deletions

View file

@ -30,9 +30,11 @@ Funny-head: yesyes
#
# Client-side
<client>
# --socks5 cannot accept Windows absolute paths
<features>
proxy
UnixSockets
!win32
</features>
<server>
http

View file

@ -31,9 +31,11 @@ Funny-head: yesyes
#
# Client-side
<client>
# --socks5h cannot accept Windows absolute paths
<features>
proxy
UnixSockets
!win32
</features>
<server>
http

View file

@ -32,9 +32,11 @@ Funny-head: yesyes
#
# Client-side
<client>
# --proxy cannot accept Windows absolute paths
<features>
proxy
UnixSockets
!win32
</features>
<server>
https

View file

@ -1863,14 +1863,20 @@ static curl_socket_t accept_connection(curl_socket_t sock)
return CURL_SOCKET_BAD;
}
if(setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE,
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_KEEPALIVE) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
sclose(msgsock);
return CURL_SOCKET_BAD;
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
if(socket_domain != AF_UNIX) {
#endif
if(setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE,
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_KEEPALIVE) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
sclose(msgsock);
return CURL_SOCKET_BAD;
}
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
}
#endif
/*
** As soon as this server accepts a connection from the test harness it
@ -2176,13 +2182,20 @@ static int test_sws(int argc, char *argv[])
goto sws_cleanup;
}
flag = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
goto sws_cleanup;
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
if(socket_domain != AF_UNIX) {
#endif
flag = 1;
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void *)&flag, sizeof(flag))) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
goto sws_cleanup;
}
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
}
#endif
if(curlx_nonblock(sock, TRUE)) {
error = SOCKERRNO;
logmsg("curlx_nonblock failed with error (%d) %s",

View file

@ -763,42 +763,48 @@ curl_socket_t sockdaemon(curl_socket_t sock,
(void)unix_socket;
#endif
do {
attempt++;
flag = 1;
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void *)&flag, sizeof(flag));
if(rc) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
if(maxretr) {
rc = curlx_wait_ms(delay);
if(rc) {
/* should not happen */
error = SOCKERRNO;
logmsg("curlx_wait_ms() failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
sclose(sock);
return CURL_SOCKET_BAD;
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
if(socket_domain != AF_UNIX) {
#endif
do {
attempt++;
flag = 1;
rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(void *)&flag, sizeof(flag));
if(rc) {
error = SOCKERRNO;
logmsg("setsockopt(SO_REUSEADDR) failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
if(maxretr) {
rc = curlx_wait_ms(delay);
if(rc) {
/* should not happen */
error = SOCKERRNO;
logmsg("curlx_wait_ms() failed with error (%d) %s",
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
sclose(sock);
return CURL_SOCKET_BAD;
}
if(got_exit_signal) {
logmsg("signalled to die, exiting...");
sclose(sock);
return CURL_SOCKET_BAD;
}
totdelay += delay;
delay *= 2; /* double the sleep for next attempt */
}
if(got_exit_signal) {
logmsg("signalled to die, exiting...");
sclose(sock);
return CURL_SOCKET_BAD;
}
totdelay += delay;
delay *= 2; /* double the sleep for next attempt */
}
}
} while(rc && maxretr--);
} while(rc && maxretr--);
if(rc) {
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. Error (%d) %s",
attempt, totdelay,
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
logmsg("Continuing anyway...");
if(rc) {
logmsg("setsockopt(SO_REUSEADDR) failed %d times in %d ms. "
"Error (%d) %s", attempt, totdelay,
error, curlx_strerror(error, errbuf, sizeof(errbuf)));
logmsg("Continuing anyway...");
}
#if defined(_WIN32) && defined(USE_UNIX_SOCKETS)
}
#endif
/* When the specified listener port is zero, it is actually a
request to let the system choose a non-zero available port. */