X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/96d9eb896c2115f032379d4d1e2a7fc211408fdc..79bf227ba7ba02e32ac710621b672e2789f9ef50:/winnet.c diff --git a/winnet.c b/winnet.c index 7cadf86f..bcb22bf4 100644 --- a/winnet.c +++ b/winnet.c @@ -38,14 +38,6 @@ */ /* #define IPV6 1 */ -#ifdef IPV6 -#include -#include -#include -#else -#include -#endif -#include #include #include #include @@ -55,8 +47,16 @@ #include "network.h" #include "tree234.h" +#include +#ifdef IPV6 +#include +#endif + +#define ipv4_is_loopback(addr) \ + ((p_ntohl(addr.s_addr) & 0xFF000000L) == 0x7F000000L) + struct Socket_tag { - struct socket_function_table *fn; + const struct socket_function_table *fn; /* the above variable absolutely *must* be the first in this structure */ char *error; SOCKET s; @@ -87,12 +87,18 @@ typedef struct Socket_tag *Actual_Socket; struct SockAddr_tag { char *error; - /* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */ + /* + * 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. + */ int family; unsigned long address; /* Address IPv4 style. */ #ifdef IPV6 struct addrinfo *ai; /* Address IPv6 style. */ #endif + char hostname[512]; /* Store an unresolved host name. */ }; static tree234 *sktree; @@ -119,8 +125,106 @@ static int cmpforsearch(void *av, void *bv) return 0; } +#define NOTHING +#define DECL_WINSOCK_FUNCTION(linkage, rettype, name, params) \ + typedef rettype (WINAPI *t_##name) params; \ + linkage t_##name p_##name +#define GET_WINSOCK_FUNCTION(name) \ + p_##name = (t_##name) GetProcAddress(winsock_module, #name) + +DECL_WINSOCK_FUNCTION(NOTHING, int, WSAAsyncSelect, + (SOCKET, HWND, u_int, long)); +DECL_WINSOCK_FUNCTION(NOTHING, int, WSAEventSelect, (SOCKET, WSAEVENT, long)); +DECL_WINSOCK_FUNCTION(NOTHING, int, select, + (int, fd_set FAR *, fd_set FAR *, + fd_set FAR *, const struct timeval FAR *)); +DECL_WINSOCK_FUNCTION(NOTHING, int, WSAGetLastError, (void)); +DECL_WINSOCK_FUNCTION(NOTHING, int, WSAEnumNetworkEvents, + (SOCKET, WSAEVENT, LPWSANETWORKEVENTS)); +DECL_WINSOCK_FUNCTION(static, int, WSAStartup, (WORD, LPWSADATA)); +DECL_WINSOCK_FUNCTION(static, int, WSACleanup, (void)); +DECL_WINSOCK_FUNCTION(static, int, closesocket, (SOCKET)); +DECL_WINSOCK_FUNCTION(static, u_long, ntohl, (u_long)); +DECL_WINSOCK_FUNCTION(static, u_long, htonl, (u_long)); +DECL_WINSOCK_FUNCTION(static, u_short, htons, (u_short)); +DECL_WINSOCK_FUNCTION(static, u_short, ntohs, (u_short)); +DECL_WINSOCK_FUNCTION(static, struct hostent FAR *, gethostbyname, + (const char FAR *)); +DECL_WINSOCK_FUNCTION(static, struct servent FAR *, getservbyname, + (const char FAR *, const char FAR *)); +DECL_WINSOCK_FUNCTION(static, unsigned long, inet_addr, (const char FAR *)); +DECL_WINSOCK_FUNCTION(static, char FAR *, inet_ntoa, (struct in_addr)); +DECL_WINSOCK_FUNCTION(static, int, connect, + (SOCKET, const struct sockaddr FAR *, int)); +DECL_WINSOCK_FUNCTION(static, int, bind, + (SOCKET, const struct sockaddr FAR *, int)); +DECL_WINSOCK_FUNCTION(static, int, setsockopt, + (SOCKET, int, int, const char FAR *, int)); +DECL_WINSOCK_FUNCTION(static, SOCKET, socket, (int, int, int)); +DECL_WINSOCK_FUNCTION(static, int, listen, (SOCKET, int)); +DECL_WINSOCK_FUNCTION(static, int, send, (SOCKET, const char FAR *, int, int)); +DECL_WINSOCK_FUNCTION(static, int, ioctlsocket, + (SOCKET, long, u_long FAR *)); +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; + void sk_init(void) { + WORD winsock_ver; + WSADATA wsadata; + + winsock_ver = MAKEWORD(2, 0); + winsock_module = LoadLibrary("WS2_32.DLL"); + if (!winsock_module) { + winsock_module = LoadLibrary("WSOCK32.DLL"); + winsock_ver = MAKEWORD(1, 1); + } + if (!winsock_module) + fatalbox("Unable to load any WinSock library"); + + GET_WINSOCK_FUNCTION(WSAAsyncSelect); + GET_WINSOCK_FUNCTION(WSAEventSelect); + GET_WINSOCK_FUNCTION(select); + GET_WINSOCK_FUNCTION(WSAGetLastError); + GET_WINSOCK_FUNCTION(WSAEnumNetworkEvents); + GET_WINSOCK_FUNCTION(WSAStartup); + GET_WINSOCK_FUNCTION(WSACleanup); + GET_WINSOCK_FUNCTION(closesocket); + GET_WINSOCK_FUNCTION(ntohl); + GET_WINSOCK_FUNCTION(htonl); + GET_WINSOCK_FUNCTION(htons); + GET_WINSOCK_FUNCTION(ntohs); + GET_WINSOCK_FUNCTION(gethostbyname); + GET_WINSOCK_FUNCTION(getservbyname); + GET_WINSOCK_FUNCTION(inet_addr); + GET_WINSOCK_FUNCTION(inet_ntoa); + GET_WINSOCK_FUNCTION(connect); + GET_WINSOCK_FUNCTION(bind); + GET_WINSOCK_FUNCTION(setsockopt); + GET_WINSOCK_FUNCTION(socket); + GET_WINSOCK_FUNCTION(listen); + GET_WINSOCK_FUNCTION(send); + 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"); + } + if (LOBYTE(wsadata.wVersion) != LOBYTE(winsock_ver)) { + p_WSACleanup(); + fatalbox("WinSock version is incompatible with %d.%d", + LOBYTE(winsock_ver), HIBYTE(winsock_ver)); + } + sktree = newtree234(cmpfortree); } @@ -131,9 +235,15 @@ void sk_cleanup(void) if (sktree) { for (i = 0; (s = index234(sktree, i)) != NULL; i++) { - closesocket(s->s); + p_closesocket(s->s); } + freetree234(sktree); + sktree = NULL; } + + p_WSACleanup(); + if (winsock_module) + FreeLibrary(winsock_module); } char *winsock_error_string(int error) @@ -215,9 +325,9 @@ char *winsock_error_string(int error) } } -SockAddr sk_namelookup(char *host, char **canonicalname) +SockAddr sk_namelookup(const char *host, char **canonicalname) { - SockAddr ret = smalloc(sizeof(struct SockAddr_tag)); + SockAddr ret = snew(struct SockAddr_tag); unsigned long a; struct hostent *h = NULL; char realhost[8192]; @@ -227,7 +337,7 @@ SockAddr sk_namelookup(char *host, char **canonicalname) ret->family = 0; /* We set this one when we have resolved the host. */ *realhost = '\0'; - if ((a = inet_addr(host)) == (unsigned long) INADDR_NONE) { + if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) { #ifdef IPV6 /* Try to get the getaddrinfo() function from wship6.dll */ @@ -263,14 +373,14 @@ SockAddr sk_namelookup(char *host, char **canonicalname) */ if (ret->family == 0) { /*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */ - if ( (h = gethostbyname(host)) ) + if ( (h = p_gethostbyname(host)) ) ret->family = AF_INET; } } /*debug(("Done resolving...(family is %d) AF_INET = %d, AF_INET6 = %d\n", ret->family, AF_INET, AF_INET6)); */ if (ret->family == 0) { - DWORD err = WSAGetLastError(); + DWORD err = p_WSAGetLastError(); ret->error = (err == WSAENETDOWN ? "Network is down" : err == WSAHOST_NOT_FOUND ? "Host does not exist" : err @@ -346,46 +456,117 @@ SockAddr sk_namelookup(char *host, char **canonicalname) ret->family = AF_INET; strncpy(realhost, host, sizeof(realhost)); } - ret->address = ntohl(a); + ret->address = p_ntohl(a); realhost[lenof(realhost)-1] = '\0'; - *canonicalname = smalloc(1+strlen(realhost)); + *canonicalname = snewn(1+strlen(realhost), char); strcpy(*canonicalname, realhost); return ret; } +SockAddr sk_nonamelookup(const char *host) +{ + SockAddr ret = snew(struct SockAddr_tag); + ret->error = NULL; + ret->family = AF_UNSPEC; + strncpy(ret->hostname, host, lenof(ret->hostname)); + ret->hostname[lenof(ret->hostname)-1] = '\0'; + return ret; +} + void sk_getaddr(SockAddr addr, char *buf, int buflen) { #ifdef IPV6 - if (addr->family == AF_INET) { + if (addr->family == AF_INET6) { + FIXME; /* I don't know how to get a text form of an IPv6 address. */ + } else #endif + if (addr->family == AF_INET) { struct in_addr a; - a.s_addr = htonl(addr->address); - strncpy(buf, inet_ntoa(a), buflen); -#ifdef IPV6 + a.s_addr = p_htonl(addr->address); + strncpy(buf, p_inet_ntoa(a), buflen); + buf[buflen-1] = '\0'; } else { - FIXME; /* I don't know how to get a text form of an IPv6 address. */ + assert(addr->family == AF_UNSPEC); + strncpy(buf, addr->hostname, buflen); + buf[buflen-1] = '\0'; } +} + +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 + if (addr->family == AF_INET6) { + FIXME; /* someone who can compile for IPV6 had better do this bit */ + } else #endif + if (addr->family == AF_INET) { + struct in_addr a; + a.s_addr = p_htonl(addr->address); + return ipv4_is_local_addr(a); + } else { + assert(addr->family == AF_UNSPEC); + return 0; /* we don't know; assume not */ + } } int sk_addrtype(SockAddr addr) { - return addr->family; + return (addr->family == AF_INET ? ADDRTYPE_IPV4 : +#ifdef IPV6 + addr->family == AF_INET6 ? ADDRTYPE_IPV6 : +#endif + ADDRTYPE_NAME); } void sk_addrcopy(SockAddr addr, char *buf) { + assert(addr->family != AF_UNSPEC); #ifdef IPV6 - if (addr->family == AF_INET) { + if (addr->family == AF_INET6) { + memcpy(buf, (char*) addr->ai, 16); + } else #endif + if (addr->family == AF_INET) { struct in_addr a; - a.s_addr = htonl(addr->address); + a.s_addr = p_htonl(addr->address); memcpy(buf, (char*) &a.s_addr, 4); -#ifdef IPV6 - } else { - memcpy(buf, (char*) addr->ai, 16); } -#endif } void sk_addr_free(SockAddr addr) @@ -411,18 +592,18 @@ static void sk_tcp_flush(Socket s) } static void sk_tcp_close(Socket s); -static int sk_tcp_write(Socket s, char *data, int len); -static int sk_tcp_write_oob(Socket s, char *data, int len); +static int sk_tcp_write(Socket s, const char *data, int len); +static int sk_tcp_write_oob(Socket s, const char *data, int len); static void sk_tcp_set_private_ptr(Socket s, void *ptr); static void *sk_tcp_get_private_ptr(Socket s); static void sk_tcp_set_frozen(Socket s, int is_frozen); -static char *sk_tcp_socket_error(Socket s); +static const char *sk_tcp_socket_error(Socket s); extern char *do_select(SOCKET skt, int startup); Socket sk_register(void *sock, Plug plug) { - static struct socket_function_table fn_table = { + static const struct socket_function_table fn_table = { sk_tcp_plug, sk_tcp_close, sk_tcp_write, @@ -441,7 +622,7 @@ Socket sk_register(void *sock, Plug plug) /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); + ret = snew(struct Socket_tag); ret->fn = &fn_table; ret->error = NULL; ret->plug = plug; @@ -456,7 +637,7 @@ Socket sk_register(void *sock, Plug plug) ret->s = (SOCKET)sock; if (ret->s == INVALID_SOCKET) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); ret->error = winsock_error_string(err); return (Socket) ret; } @@ -477,9 +658,9 @@ 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 struct socket_function_table fn_table = { + static const struct socket_function_table fn_table = { sk_tcp_plug, sk_tcp_close, sk_tcp_write, @@ -504,7 +685,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); + ret = snew(struct Socket_tag); ret->fn = &fn_table; ret->error = NULL; ret->plug = plug; @@ -520,11 +701,12 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, /* * Open socket. */ - s = socket(addr->family, SOCK_STREAM, 0); + assert(addr->family != AF_UNSPEC); + s = p_socket(addr->family, SOCK_STREAM, 0); ret->s = s; if (s == INVALID_SOCKET) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); ret->error = winsock_error_string(err); return (Socket) ret; } @@ -532,12 +714,17 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, ret->oobinline = oobinline; if (oobinline) { BOOL b = TRUE; - setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b)); + p_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b)); } if (nodelay) { BOOL b = TRUE; - setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b)); + 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)); } /* @@ -557,28 +744,28 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, memset(&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; /*a6.sin6_addr = in6addr_any; *//* == 0 */ - a6.sin6_port = htons(localport); + a6.sin6_port = p_htons(localport); } else #endif { a.sin_family = AF_INET; - a.sin_addr.s_addr = htonl(INADDR_ANY); - a.sin_port = htons(localport); + a.sin_addr.s_addr = p_htonl(INADDR_ANY); + a.sin_port = p_htons(localport); } #ifdef IPV6 - retcode = bind(s, (addr->family == AF_INET6 ? + retcode = p_bind(s, (addr->family == AF_INET6 ? (struct sockaddr *) &a6 : (struct sockaddr *) &a), (addr->family == AF_INET6 ? sizeof(a6) : sizeof(a))); #else - retcode = bind(s, (struct sockaddr *) &a, sizeof(a)); + retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a)); #endif if (retcode != SOCKET_ERROR) { err = 0; break; /* done */ } else { - err = WSAGetLastError(); + err = p_WSAGetLastError(); if (err != WSAEADDRINUSE) /* failed, for a bad reason */ break; } @@ -602,15 +789,15 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, if (addr->family == AF_INET6) { memset(&a, 0, sizeof(a)); a6.sin6_family = AF_INET6; - a6.sin6_port = htons((short) port); + a6.sin6_port = p_htons((short) port); a6.sin6_addr = ((struct sockaddr_in6 *) addr->ai->ai_addr)->sin6_addr; } else #endif { a.sin_family = AF_INET; - a.sin_addr.s_addr = htonl(addr->address); - a.sin_port = htons((short) port); + a.sin_addr.s_addr = p_htonl(addr->address); + a.sin_port = p_htons((short) port); } /* Set up a select mechanism. This could be an AsyncSelect on a @@ -623,14 +810,14 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, if (( #ifdef IPV6 - connect(s, ((addr->family == AF_INET6) ? + p_connect(s, ((addr->family == AF_INET6) ? (struct sockaddr *) &a6 : (struct sockaddr *) &a), (addr->family == AF_INET6) ? sizeof(a6) : sizeof(a)) #else - connect(s, (struct sockaddr *) &a, sizeof(a)) + p_connect(s, (struct sockaddr *) &a, sizeof(a)) #endif ) == SOCKET_ERROR) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); /* * We expect a potential EWOULDBLOCK here, because the * chances are the front end has done a select for @@ -651,12 +838,15 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline, add234(sktree, ret); + /* We're done with 'addr' now. */ + sk_addr_free(addr); + return (Socket) ret; } -Socket sk_newlistener(int port, Plug plug, int local_host_only) +Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only) { - static struct socket_function_table fn_table = { + static const struct socket_function_table fn_table = { sk_tcp_plug, sk_tcp_close, sk_tcp_write, @@ -682,7 +872,7 @@ Socket sk_newlistener(int port, Plug plug, int local_host_only) /* * Create Socket structure. */ - ret = smalloc(sizeof(struct Socket_tag)); + ret = snew(struct Socket_tag); ret->fn = &fn_table; ret->error = NULL; ret->plug = plug; @@ -697,53 +887,74 @@ Socket sk_newlistener(int port, Plug plug, int local_host_only) /* * Open socket. */ - s = socket(AF_INET, SOCK_STREAM, 0); + s = p_socket(AF_INET, SOCK_STREAM, 0); ret->s = s; if (s == INVALID_SOCKET) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); ret->error = winsock_error_string(err); return (Socket) ret; } ret->oobinline = 0; - - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)); - + p_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)); #ifdef IPV6 if (addr->family == AF_INET6) { memset(&a6, 0, sizeof(a6)); a6.sin6_family = AF_INET6; + /* FIXME: srcaddr is ignored for IPv6, because I (SGT) don't + * know how to do it. :-) */ if (local_host_only) a6.sin6_addr = in6addr_loopback; else a6.sin6_addr = in6addr_any; - a6.sin6_port = htons(port); + a6.sin6_port = p_htons(port); } else #endif { + int got_addr = 0; a.sin_family = AF_INET; - if (local_host_only) - a.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - else - a.sin_addr.s_addr = htonl(INADDR_ANY); - a.sin_port = htons((short)port); + + /* + * Bind to source address. First try an explicitly + * specified one... + */ + if (srcaddr) { + a.sin_addr.s_addr = p_inet_addr(srcaddr); + if (a.sin_addr.s_addr != INADDR_NONE) { + /* Override localhost_only with specified listen addr. */ + ret->localhost_only = ipv4_is_loopback(a.sin_addr); + got_addr = 1; + } + } + + /* + * ... and failing that, go with one of the standard ones. + */ + if (!got_addr) { + if (local_host_only) + a.sin_addr.s_addr = p_htonl(INADDR_LOOPBACK); + else + a.sin_addr.s_addr = p_htonl(INADDR_ANY); + } + + a.sin_port = p_htons((short)port); } #ifdef IPV6 - retcode = bind(s, (addr->family == AF_INET6 ? + retcode = p_bind(s, (addr->family == AF_INET6 ? (struct sockaddr *) &a6 : (struct sockaddr *) &a), (addr->family == AF_INET6 ? sizeof(a6) : sizeof(a))); #else - retcode = bind(s, (struct sockaddr *) &a, sizeof(a)); + retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a)); #endif if (retcode != SOCKET_ERROR) { err = 0; } else { - err = WSAGetLastError(); + err = p_WSAGetLastError(); } if (err) { @@ -752,8 +963,8 @@ Socket sk_newlistener(int port, Plug plug, int local_host_only) } - if (listen(s, SOMAXCONN) == SOCKET_ERROR) { - closesocket(s); + if (p_listen(s, SOMAXCONN) == SOCKET_ERROR) { + p_closesocket(s); ret->error = winsock_error_string(err); return (Socket) ret; } @@ -778,7 +989,7 @@ static void sk_tcp_close(Socket sock) del234(sktree, s); do_select(s->s, 0); - closesocket(s->s); + p_closesocket(s->s); sfree(s); } @@ -802,10 +1013,10 @@ void try_send(Actual_Socket s) urgentflag = 0; bufchain_prefix(&s->output_data, &data, &len); } - nsent = send(s->s, data, len, urgentflag); + nsent = p_send(s->s, data, len, urgentflag); noise_ultralight(nsent); if (nsent <= 0) { - err = (nsent < 0 ? WSAGetLastError() : 0); + err = (nsent < 0 ? p_WSAGetLastError() : 0); if ((err < WSABASEERR && nsent < 0) || err == WSAEWOULDBLOCK) { /* * Perfectly normal: we've sent all we can for the moment. @@ -833,7 +1044,9 @@ void try_send(Actual_Socket s) s->pending_error = err; return; } else { - logevent(winsock_error_string(err)); + /* We're inside the Windows frontend here, so we know + * that the frontend handle is unnecessary. */ + logevent(NULL, winsock_error_string(err)); fatalbox("%s", winsock_error_string(err)); } } else { @@ -851,7 +1064,7 @@ void try_send(Actual_Socket s) } } -static int sk_tcp_write(Socket sock, char *buf, int len) +static int sk_tcp_write(Socket sock, const char *buf, int len) { Actual_Socket s = (Actual_Socket) sock; @@ -869,7 +1082,7 @@ static int sk_tcp_write(Socket sock, char *buf, int len) return bufchain_size(&s->output_data); } -static int sk_tcp_write_oob(Socket sock, char *buf, int len) +static int sk_tcp_write_oob(Socket sock, const char *buf, int len) { Actual_Socket s = (Actual_Socket) sock; @@ -899,6 +1112,10 @@ int select_result(WPARAM wParam, LPARAM lParam) u_long atmark; /* wParam is the socket itself */ + + if (wParam == 0) + return 1; /* boggle */ + s = find234(sktree, (void *) wParam, cmpforsearch); if (!s) return 1; /* boggle */ @@ -932,7 +1149,7 @@ int select_result(WPARAM wParam, LPARAM lParam) */ if (s->oobinline) { atmark = 1; - ioctlsocket(s->s, SIOCATMARK, &atmark); + p_ioctlsocket(s->s, SIOCATMARK, &atmark); /* * Avoid checking the return value from ioctlsocket(), * on the grounds that some WinSock wrappers don't @@ -943,10 +1160,10 @@ int select_result(WPARAM wParam, LPARAM lParam) } else atmark = 1; - ret = recv(s->s, buf, sizeof(buf), 0); + ret = p_recv(s->s, buf, sizeof(buf), 0); noise_ultralight(ret); if (ret < 0) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); if (err == WSAEWOULDBLOCK) { break; } @@ -967,12 +1184,14 @@ int select_result(WPARAM wParam, LPARAM lParam) * and get back OOB data, which we will send to the back * end with type==2 (urgent data). */ - ret = recv(s->s, buf, sizeof(buf), MSG_OOB); + ret = p_recv(s->s, buf, sizeof(buf), MSG_OOB); noise_ultralight(ret); if (ret <= 0) { char *str = (ret == 0 ? "Internal networking trouble" : - winsock_error_string(WSAGetLastError())); - logevent(str); + winsock_error_string(p_WSAGetLastError())); + /* We're inside the Windows frontend here, so we know + * that the frontend handle is unnecessary. */ + logevent(NULL, str); fatalbox("%s", str); } else { return plug_receive(s->plug, 2, buf, ret); @@ -993,9 +1212,9 @@ int select_result(WPARAM wParam, LPARAM lParam) /* Signal a close on the socket. First read any outstanding data. */ open = 1; do { - ret = recv(s->s, buf, sizeof(buf), 0); + ret = p_recv(s->s, buf, sizeof(buf), 0); if (ret < 0) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); if (err == WSAEWOULDBLOCK) break; return plug_closing(s->plug, winsock_error_string(err), @@ -1016,19 +1235,18 @@ int select_result(WPARAM wParam, LPARAM lParam) memset(&isa, 0, sizeof(struct sockaddr_in)); err = 0; - t = accept(s->s,(struct sockaddr *)&isa,&addrlen); + t = p_accept(s->s,(struct sockaddr *)&isa,&addrlen); if (t == INVALID_SOCKET) { - err = WSAGetLastError(); + err = p_WSAGetLastError(); if (err == WSATRY_AGAIN) break; } - if (s->localhost_only && - ntohl(isa.sin_addr.s_addr) != INADDR_LOOPBACK) { - closesocket(t); /* dodgy WinSock let nonlocal through */ + 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)) { - closesocket(t); /* denied or error */ + p_closesocket(t); /* denied or error */ } } } @@ -1095,11 +1313,11 @@ static void *sk_tcp_get_private_ptr(Socket sock) * if there's a problem. These functions extract an error message, * or return NULL if there's no problem. */ -char *sk_addr_error(SockAddr addr) +const char *sk_addr_error(SockAddr addr) { return addr->error; } -static char *sk_tcp_socket_error(Socket sock) +static const char *sk_tcp_socket_error(Socket sock) { Actual_Socket s = (Actual_Socket) sock; return s->error; @@ -1113,7 +1331,7 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen) s->frozen = is_frozen; if (!is_frozen && s->frozen_readable) { char c; - recv(s->s, &c, 1, MSG_PEEK); + p_recv(s->s, &c, 1, MSG_PEEK); } s->frozen_readable = 0; } @@ -1134,3 +1352,21 @@ SOCKET next_socket(int *state) Actual_Socket s = index234(sktree, (*state)++); return s ? s->s : INVALID_SOCKET; } + +int net_service_lookup(char *service) +{ + struct servent *se; + se = p_getservbyname(service, NULL); + if (se != NULL) + return p_ntohs(se->s_port); + 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; +}