1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 09:58:01 +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_WINRES_H
#cmakedefine01 HAVE_WIN_H #cmakedefine01 HAVE_WIN_H
#cmakedefine01 HAVE_NO_STDINT_H #cmakedefine01 HAVE_NO_STDINT_H
#cmakedefine01 HAVE_AFUNIX_H
#cmakedefine01 HAVE_GCP_RESULTSW #cmakedefine01 HAVE_GCP_RESULTSW
#cmakedefine01 HAVE_ADDDLLDIRECTORY #cmakedefine01 HAVE_ADDDLLDIRECTORY
#cmakedefine01 HAVE_GETNAMEDPIPECLIENTPROCESSID #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) check_include_files("windows.h;htmlhelp.h" HAVE_HTMLHELP_H)
define_negation(NO_HTMLHELP 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(strtoumax "inttypes.h" HAVE_STRTOUMAX)
check_symbol_exists(AddDllDirectory "windows.h" HAVE_ADDDLLDIRECTORY) check_symbol_exists(AddDllDirectory "windows.h" HAVE_ADDDLLDIRECTORY)
check_symbol_exists(SetDefaultDllDirectories "windows.h" check_symbol_exists(SetDefaultDllDirectories "windows.h"

View File

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

View File

@ -293,6 +293,7 @@ void socket_reselect_all(void);
SockAddr *sk_namedpipe_addr(const char *pipename); SockAddr *sk_namedpipe_addr(const char *pipename);
/* Turn a WinSock error code into a string. */ /* Turn a WinSock error code into a string. */
const char *winsock_error_string(int error); 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 * network.c dynamically loads WinSock 2 or WinSock 1 depending on