1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Support AF_UNIX listening sockets on Windows.

Not all Windows toolchains have this yet, so we have to put the
whole lot under #ifdef.
This commit is contained in:
Simon Tatham 2022-01-27 20:37:32 +00:00
parent 3d15342fe8
commit 018236da29
4 changed files with 61 additions and 9 deletions

View File

@ -8,6 +8,7 @@
#cmakedefine01 HAVE_WINRES_H
#cmakedefine01 HAVE_WIN_H
#cmakedefine01 HAVE_NO_STDINT_H
#cmakedefine01 HAVE_AFUNIX_H
#cmakedefine01 HAVE_GCP_RESULTSW
#cmakedefine01 HAVE_ADDDLLDIRECTORY
#cmakedefine01 HAVE_GETNAMEDPIPECLIENTPROCESSID

View File

@ -41,6 +41,8 @@ define_negation(NO_MULTIMON HAVE_MULTIMON_H)
check_include_files("windows.h;htmlhelp.h" HAVE_HTMLHELP_H)
define_negation(NO_HTMLHELP HAVE_HTMLHELP_H)
check_include_files("winsock2.h;afunix.h" HAVE_AFUNIX_H)
check_symbol_exists(strtoumax "inttypes.h" HAVE_STRTOUMAX)
check_symbol_exists(AddDllDirectory "windows.h" HAVE_ADDDLLDIRECTORY)
check_symbol_exists(SetDefaultDllDirectories "windows.h"

View File

@ -20,6 +20,10 @@
#include <ws2tcpip.h>
#if HAVE_AFUNIX_H
#include <afunix.h>
#endif
#ifndef NO_IPV6
#ifdef __clang__
#pragma clang diagnostic push
@ -83,13 +87,17 @@ struct NetSocket {
* Top-level discriminator for SockAddr.
*
* UNRESOLVED means a host name not yet put through DNS; IP means a
* resolved IP address (or list of them); NAMEDPIPE indicates that
* resolved IP address (or list of them); UNIX indicates the AF_UNIX
* network family (which Windows also has); NAMEDPIPE indicates that
* this SockAddr is phony, holding a Windows named pipe pathname
* instead of any address WinSock can understand.
*/
typedef enum SuperFamily {
UNRESOLVED,
IP,
#if HAVE_AFUNIX_H
UNIX,
#endif
NAMEDPIPE
} SuperFamily;
@ -107,9 +115,9 @@ struct SockAddr {
/*
* Which address family this address belongs to. AF_INET for IPv4;
* AF_INET6 for IPv6; AF_UNSPEC indicates that name resolution has
* not been done and a simple host name is held in this SockAddr
* structure.
* AF_INET6 for IPv6; AF_UNIX for Unix-domain sockets; AF_UNSPEC
* indicates that name resolution has not been done and a simple host
* name is held in this SockAddr structure.
*/
static inline int sockaddr_family(SockAddr *addr, SockAddrStep step)
{
@ -120,6 +128,10 @@ static inline int sockaddr_family(SockAddr *addr, SockAddrStep step)
return step.ai->ai_family;
#endif
return AF_INET;
#if HAVE_AFUNIX_H
case UNIX:
return AF_UNIX;
#endif
default:
return AF_UNSPEC;
}
@ -586,6 +598,13 @@ SockAddr *sk_namedpipe_addr(const char *pipename)
return sk_special_addr(NAMEDPIPE, pipename);
}
#if HAVE_AFUNIX_H
SockAddr *sk_unix_addr(const char *sockpath)
{
return sk_special_addr(UNIX, sockpath);
}
#endif
static bool sk_nextaddr(SockAddr *addr, SockAddrStep *step)
{
#ifndef NO_IPV6
@ -670,7 +689,11 @@ static SockAddr sk_extractaddr_tmp(
bool sk_addr_needs_port(SockAddr *addr)
{
return addr->superfamily != NAMEDPIPE;
return addr->superfamily != NAMEDPIPE
#if HAVE_AFUNIX_H
&& addr->superfamily != UNIX
#endif
;
}
bool sk_hostname_is_local(const char *name)
@ -1132,10 +1155,13 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
bool local_host_only, int orig_address_family)
{
SOCKET s;
SOCKADDR_IN a;
#ifndef NO_IPV6
SOCKADDR_IN6 a6;
#endif
SOCKADDR_IN a;
#if HAVE_AFUNIX_H
SOCKADDR_UN au;
#endif
struct sockaddr *bindaddr;
unsigned bindsize;
@ -1189,6 +1215,9 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
ret->oobinline = false;
#if HAVE_AFUNIX_H
if (address_family != AF_UNIX)
#endif
{
BOOL on = true;
p_setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
@ -1261,6 +1290,15 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
bindsize = sizeof(a);
break;
}
#if HAVE_AFUNIX_H
case AF_UNIX: {
au.sun_family = AF_UNIX;
strncpy(au.sun_path, srcaddr, sizeof(au.sun_path));
bindaddr = (struct sockaddr *)&au;
bindsize = sizeof(au);
break;
}
#endif
default:
unreachable("bad address family in sk_newlistener_internal");
}
@ -1337,6 +1375,16 @@ Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
address_family);
}
Socket *sk_newlistener_unix(const char *path, Plug *plug)
{
#if HAVE_AFUNIX_H
return sk_newlistener_internal(path, 0, plug, false, AF_UNIX);
#else
return new_error_socket_fmt(
plug, "AF_UNIX support not compiled into this program");
#endif
}
static void sk_net_close(Socket *sock)
{
NetSocket *s = container_of(sock, NetSocket, sock);
@ -1676,7 +1724,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
#ifdef NO_IPV6
struct sockaddr_in isa;
#else
struct sockaddr_storage isa;
struct sockaddr_storage isa; // FIXME: also if Unix and no IPv6
#endif
int addrlen = sizeof(isa);
SOCKET t; /* socket of connection */
@ -1732,7 +1780,7 @@ static SocketPeerInfo *sk_net_peer_info(Socket *sock)
#ifdef NO_IPV6
struct sockaddr_in addr;
#else
struct sockaddr_storage addr;
struct sockaddr_storage addr; // FIXME: also if Unix and no IPv6
char buf[INET6_ADDRSTRLEN];
#endif
int addrlen = sizeof(addr);
@ -1851,7 +1899,7 @@ SockAddr *platform_get_x11_unix_address(const char *display, int displaynum)
{
SockAddr *ret = snew(SockAddr);
memset(ret, 0, sizeof(SockAddr));
ret->error = "unix sockets not supported on this platform";
ret->error = "unix sockets for X11 not supported on this platform";
ret->refcount = 1;
return ret;
}

View File

@ -293,6 +293,7 @@ void socket_reselect_all(void);
SockAddr *sk_namedpipe_addr(const char *pipename);
/* Turn a WinSock error code into a string. */
const char *winsock_error_string(int error);
Socket *sk_newlistener_unix(const char *socketpath, Plug *plug);
/*
* network.c dynamically loads WinSock 2 or WinSock 1 depending on