X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/7440fd4419acfc9c784f142fb9dee3e64c9a18c2..142a7757ce23032acccf721411b24a69168d22ea:/winnet.c diff --git a/winnet.c b/winnet.c index 25cfc191..bcb22bf4 100644 --- a/winnet.c +++ b/winnet.c @@ -47,8 +47,8 @@ #include "network.h" #include "tree234.h" -#ifdef IPV6 #include +#ifdef IPV6 #include #endif @@ -168,6 +168,10 @@ DECL_WINSOCK_FUNCTION(static, int, ioctlsocket, DECL_WINSOCK_FUNCTION(static, SOCKET, accept, (SOCKET, struct sockaddr FAR *, int FAR *)); DECL_WINSOCK_FUNCTION(static, int, recv, (SOCKET, char FAR *, int, int)); +DECL_WINSOCK_FUNCTION(static, int, WSAIoctl, + (SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD, + LPDWORD, LPWSAOVERLAPPED, + LPWSAOVERLAPPED_COMPLETION_ROUTINE)); static HMODULE winsock_module; @@ -210,6 +214,7 @@ void sk_init(void) GET_WINSOCK_FUNCTION(ioctlsocket); GET_WINSOCK_FUNCTION(accept); GET_WINSOCK_FUNCTION(recv); + GET_WINSOCK_FUNCTION(WSAIoctl); if (p_WSAStartup(winsock_ver, &wsadata)) { fatalbox("Unable to initialise WinSock"); @@ -232,6 +237,8 @@ void sk_cleanup(void) for (i = 0; (s = index234(sktree, i)) != NULL; i++) { p_closesocket(s->s); } + freetree234(sktree); + sktree = NULL; } p_WSACleanup(); @@ -490,6 +497,37 @@ int sk_hostname_is_local(char *name) return !strcmp(name, "localhost"); } +static INTERFACE_INFO local_interfaces[16]; +static int n_local_interfaces; /* 0=not yet, -1=failed, >0=number */ + +static int ipv4_is_local_addr(struct in_addr addr) +{ + if (ipv4_is_loopback(addr)) + return 1; /* loopback addresses are local */ + if (!n_local_interfaces) { + SOCKET s = p_socket(AF_INET, SOCK_DGRAM, 0); + DWORD retbytes; + + if (p_WSAIoctl && + p_WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, + local_interfaces, sizeof(local_interfaces), + &retbytes, NULL, NULL) == 0) + n_local_interfaces = retbytes / sizeof(INTERFACE_INFO); + else + logevent(NULL, "Unable to get list of local IP addresses"); + } + if (n_local_interfaces > 0) { + int i; + for (i = 0; i < n_local_interfaces; i++) { + SOCKADDR_IN *address = + (SOCKADDR_IN *)&local_interfaces[i].iiAddress; + if (address->sin_addr.s_addr == addr.s_addr) + return 1; /* this address is local */ + } + } + return 0; /* this address is not local */ +} + int sk_address_is_local(SockAddr addr) { #ifdef IPV6 @@ -500,7 +538,7 @@ int sk_address_is_local(SockAddr addr) if (addr->family == AF_INET) { struct in_addr a; a.s_addr = p_htonl(addr->address); - return ipv4_is_loopback(a); + return ipv4_is_local_addr(a); } else { assert(addr->family == AF_UNSPEC); return 0; /* we don't know; assume not */ @@ -620,7 +658,7 @@ Socket sk_register(void *sock, Plug plug) } Socket sk_new(SockAddr addr, int port, int privport, int oobinline, - int nodelay, Plug plug) + int nodelay, int keepalive, Plug plug) { static const struct socket_function_table fn_table = { sk_tcp_plug, @@ -684,6 +722,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, p_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b)); } + if (keepalive) { + BOOL b = TRUE; + p_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b)); + } + /* * Bind to local address. */ @@ -1200,7 +1243,7 @@ int select_result(WPARAM wParam, LPARAM lParam) break; } - if (s->localhost_only && !ipv4_is_loopback(isa.sin_addr)) { + if (s->localhost_only && !ipv4_is_local_addr(isa.sin_addr)) { p_closesocket(t); /* dodgy WinSock let nonlocal through */ } else if (plug_accepting(s->plug, (void*)t)) { p_closesocket(t); /* denied or error */ @@ -1319,3 +1362,11 @@ int net_service_lookup(char *service) else return 0; } + +SockAddr platform_get_x11_unix_address(int displaynum, char **canonicalname) +{ + SockAddr ret = snew(struct SockAddr_tag); + memset(ret, 0, sizeof(struct SockAddr_tag)); + ret->error = "unix sockets not supported on this platform"; + return ret; +}