The special treatment of Alt-resize (to cause resizing to affect the
[u/mdw/putty] / windows / winnet.c
CommitLineData
2f75bae1 1/*
2 * Windows networking abstraction.
c4d8e107 3 *
05581745 4 * For the IPv6 code in here I am indebted to Jeroen Massar and
5 * unfix.org.
2f75bae1 6 */
7
2f75bae1 8#include <stdio.h>
49bad831 9#include <stdlib.h>
5471d09a 10#include <assert.h>
2f75bae1 11
7e78000d 12#define DEFINE_PLUG_METHOD_MACROS
2f75bae1 13#include "putty.h"
14#include "network.h"
15#include "tree234.h"
16
7440fd44 17#include <ws2tcpip.h>
05581745 18
19#ifndef NO_IPV6
20const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
21const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
7440fd44 22#endif
23
6ee9b735 24#define ipv4_is_loopback(addr) \
7440fd44 25 ((p_ntohl(addr.s_addr) & 0xFF000000L) == 0x7F000000L)
6ee9b735 26
ae400b95 27/*
28 * We used to typedef struct Socket_tag *Socket.
29 *
30 * Since we have made the networking abstraction slightly more
31 * abstract, Socket no longer means a tcp socket (it could mean
32 * an ssl socket). So now we must use Actual_Socket when we know
33 * we are talking about a tcp socket.
34 */
35typedef struct Socket_tag *Actual_Socket;
36
facf7568 37/*
38 * Mutable state that goes with a SockAddr: stores information
39 * about where in the list of candidate IP(v*) addresses we've
40 * currently got to.
41 */
42typedef struct SockAddrStep_tag SockAddrStep;
43struct SockAddrStep_tag {
44#ifndef NO_IPV6
45 struct addrinfo *ai; /* steps along addr->ais */
46#endif
47 int curraddr;
48};
49
2f75bae1 50struct Socket_tag {
c85623f9 51 const struct socket_function_table *fn;
7e78000d 52 /* the above variable absolutely *must* be the first in this structure */
2f75bae1 53 char *error;
54 SOCKET s;
7e78000d 55 Plug plug;
2f75bae1 56 void *private_ptr;
5471d09a 57 bufchain output_data;
3ad9d396 58 int connected;
2f75bae1 59 int writable;
5471d09a 60 int frozen; /* this causes readability notifications to be ignored */
61 int frozen_readable; /* this means we missed at least one readability
62 * notification while we were frozen */
bc4802a1 63 int localhost_only; /* for listening sockets */
5471d09a 64 char oobdata[1];
1ad4eb6f 65 int sending_oob;
7555d6a5 66 int oobinline, nodelay, keepalive, privport;
67 SockAddr addr;
facf7568 68 SockAddrStep step;
7555d6a5 69 int port;
7732d38a 70 int pending_error; /* in case send() returns error */
ae400b95 71 /*
72 * We sometimes need pairs of Socket structures to be linked:
73 * if we are listening on the same IPv6 and v4 port, for
74 * example. So here we define `parent' and `child' pointers to
75 * track this link.
76 */
77 Actual_Socket parent, child;
2f75bae1 78};
79
80struct SockAddr_tag {
5025a993 81 int refcount;
2f75bae1 82 char *error;
facf7568 83 int resolved;
05581745 84#ifndef NO_IPV6
7555d6a5 85 struct addrinfo *ais; /* Addresses IPv6 style. */
c4d8e107 86#endif
7555d6a5 87 unsigned long *addresses; /* Addresses IPv4 style. */
facf7568 88 int naddresses;
b7a189f3 89 char hostname[512]; /* Store an unresolved host name. */
2f75bae1 90};
91
facf7568 92/*
93 * Which address family this address belongs to. AF_INET for IPv4;
94 * AF_INET6 for IPv6; AF_UNSPEC indicates that name resolution has
95 * not been done and a simple host name is held in this SockAddr
96 * structure.
97 */
98#ifndef NO_IPV6
99#define SOCKADDR_FAMILY(addr, step) \
100 (!(addr)->resolved ? AF_UNSPEC : \
101 (step).ai ? (step).ai->ai_family : AF_INET)
102#else
103#define SOCKADDR_FAMILY(addr, step) \
104 (!(addr)->resolved ? AF_UNSPEC : AF_INET)
105#endif
106
107/*
108 * Start a SockAddrStep structure to step through multiple
109 * addresses.
110 */
111#ifndef NO_IPV6
112#define START_STEP(addr, step) \
113 ((step).ai = (addr)->ais, (step).curraddr = 0)
114#else
115#define START_STEP(addr, step) \
116 ((step).curraddr = 0)
117#endif
118
2f75bae1 119static tree234 *sktree;
120
32874aea 121static int cmpfortree(void *av, void *bv)
122{
123 Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
124 unsigned long as = (unsigned long) a->s, bs = (unsigned long) b->s;
125 if (as < bs)
126 return -1;
127 if (as > bs)
128 return +1;
b34544ba 129 if (a < b)
130 return -1;
131 if (a > b)
132 return +1;
2f75bae1 133 return 0;
134}
135
32874aea 136static int cmpforsearch(void *av, void *bv)
137{
138 Actual_Socket b = (Actual_Socket) bv;
139 unsigned long as = (unsigned long) av, bs = (unsigned long) b->s;
140 if (as < bs)
141 return -1;
142 if (as > bs)
143 return +1;
2f75bae1 144 return 0;
145}
146
65d1432e 147DECL_WINDOWS_FUNCTION(static, int, WSAStartup, (WORD, LPWSADATA));
148DECL_WINDOWS_FUNCTION(static, int, WSACleanup, (void));
149DECL_WINDOWS_FUNCTION(static, int, closesocket, (SOCKET));
150DECL_WINDOWS_FUNCTION(static, u_long, ntohl, (u_long));
151DECL_WINDOWS_FUNCTION(static, u_long, htonl, (u_long));
152DECL_WINDOWS_FUNCTION(static, u_short, htons, (u_short));
153DECL_WINDOWS_FUNCTION(static, u_short, ntohs, (u_short));
154DECL_WINDOWS_FUNCTION(static, int, gethostname, (char *, int));
155DECL_WINDOWS_FUNCTION(static, struct hostent FAR *, gethostbyname,
7440fd44 156 (const char FAR *));
65d1432e 157DECL_WINDOWS_FUNCTION(static, struct servent FAR *, getservbyname,
7440fd44 158 (const char FAR *, const char FAR *));
65d1432e 159DECL_WINDOWS_FUNCTION(static, unsigned long, inet_addr, (const char FAR *));
160DECL_WINDOWS_FUNCTION(static, char FAR *, inet_ntoa, (struct in_addr));
161DECL_WINDOWS_FUNCTION(static, int, connect,
7440fd44 162 (SOCKET, const struct sockaddr FAR *, int));
65d1432e 163DECL_WINDOWS_FUNCTION(static, int, bind,
7440fd44 164 (SOCKET, const struct sockaddr FAR *, int));
65d1432e 165DECL_WINDOWS_FUNCTION(static, int, setsockopt,
7440fd44 166 (SOCKET, int, int, const char FAR *, int));
65d1432e 167DECL_WINDOWS_FUNCTION(static, SOCKET, socket, (int, int, int));
168DECL_WINDOWS_FUNCTION(static, int, listen, (SOCKET, int));
169DECL_WINDOWS_FUNCTION(static, int, send, (SOCKET, const char FAR *, int, int));
170DECL_WINDOWS_FUNCTION(static, int, ioctlsocket,
7440fd44 171 (SOCKET, long, u_long FAR *));
65d1432e 172DECL_WINDOWS_FUNCTION(static, SOCKET, accept,
7440fd44 173 (SOCKET, struct sockaddr FAR *, int FAR *));
65d1432e 174DECL_WINDOWS_FUNCTION(static, int, recv, (SOCKET, char FAR *, int, int));
175DECL_WINDOWS_FUNCTION(static, int, WSAIoctl,
a143ea0a 176 (SOCKET, DWORD, LPVOID, DWORD, LPVOID, DWORD,
177 LPDWORD, LPWSAOVERLAPPED,
178 LPWSAOVERLAPPED_COMPLETION_ROUTINE));
7555d6a5 179#ifndef NO_IPV6
65d1432e 180DECL_WINDOWS_FUNCTION(static, int, getaddrinfo,
7555d6a5 181 (const char *nodename, const char *servname,
182 const struct addrinfo *hints, struct addrinfo **res));
65d1432e 183DECL_WINDOWS_FUNCTION(static, void, freeaddrinfo, (struct addrinfo *res));
184DECL_WINDOWS_FUNCTION(static, int, getnameinfo,
7555d6a5 185 (const struct sockaddr FAR * sa, socklen_t salen,
186 char FAR * host, size_t hostlen, char FAR * serv,
187 size_t servlen, int flags));
65d1432e 188DECL_WINDOWS_FUNCTION(static, char *, gai_strerror, (int ecode));
189DECL_WINDOWS_FUNCTION(static, int, WSAAddressToStringA,
c9ef99df 190 (LPSOCKADDR, DWORD, LPWSAPROTOCOL_INFO,
6acea9a6 191 LPSTR, LPDWORD));
7555d6a5 192#endif
7440fd44 193
c9ef99df 194static HMODULE winsock_module = NULL;
195static WSADATA wsadata;
7555d6a5 196#ifndef NO_IPV6
c9ef99df 197static HMODULE winsock2_module = NULL;
198static HMODULE wship6_module = NULL;
7555d6a5 199#endif
7440fd44 200
c9ef99df 201int sk_startup(int hi, int lo)
32874aea 202{
7440fd44 203 WORD winsock_ver;
7440fd44 204
c9ef99df 205 winsock_ver = MAKEWORD(hi, lo);
206
207 if (p_WSAStartup(winsock_ver, &wsadata)) {
208 return FALSE;
209 }
210
211 if (LOBYTE(wsadata.wVersion) != LOBYTE(winsock_ver)) {
212 return FALSE;
213 }
214
215#ifdef NET_SETUP_DIAGNOSTICS
216 {
217 char buf[80];
218 sprintf(buf, "Using WinSock %d.%d", hi, lo);
219 logevent(NULL, buf);
220 }
221#endif
222 return TRUE;
223}
224
225void sk_init(void)
226{
b72210b4 227#ifndef NO_IPV6
228 winsock2_module =
229#endif
bda368a5 230 winsock_module = load_system32_dll("ws2_32.dll");
7440fd44 231 if (!winsock_module) {
bda368a5 232 winsock_module = load_system32_dll("wsock32.dll");
7440fd44 233 }
234 if (!winsock_module)
235 fatalbox("Unable to load any WinSock library");
236
7555d6a5 237#ifndef NO_IPV6
c9ef99df 238 /* Check if we have getaddrinfo in Winsock */
239 if (GetProcAddress(winsock_module, "getaddrinfo") != NULL) {
240#ifdef NET_SETUP_DIAGNOSTICS
241 logevent(NULL, "Native WinSock IPv6 support detected");
242#endif
65d1432e 243 GET_WINDOWS_FUNCTION(winsock_module, getaddrinfo);
244 GET_WINDOWS_FUNCTION(winsock_module, freeaddrinfo);
245 GET_WINDOWS_FUNCTION(winsock_module, getnameinfo);
246 GET_WINDOWS_FUNCTION(winsock_module, gai_strerror);
c9ef99df 247 } else {
248 /* Fall back to wship6.dll for Windows 2000 */
bda368a5 249 wship6_module = load_system32_dll("wship6.dll");
c9ef99df 250 if (wship6_module) {
251#ifdef NET_SETUP_DIAGNOSTICS
252 logevent(NULL, "WSH IPv6 support detected");
253#endif
65d1432e 254 GET_WINDOWS_FUNCTION(wship6_module, getaddrinfo);
255 GET_WINDOWS_FUNCTION(wship6_module, freeaddrinfo);
256 GET_WINDOWS_FUNCTION(wship6_module, getnameinfo);
257 GET_WINDOWS_FUNCTION(wship6_module, gai_strerror);
c9ef99df 258 } else {
259#ifdef NET_SETUP_DIAGNOSTICS
260 logevent(NULL, "No IPv6 support detected");
261#endif
262 }
7555d6a5 263 }
65d1432e 264 GET_WINDOWS_FUNCTION(winsock2_module, WSAAddressToStringA);
c9ef99df 265#else
266#ifdef NET_SETUP_DIAGNOSTICS
267 logevent(NULL, "PuTTY was built without IPv6 support");
268#endif
7555d6a5 269#endif
270
65d1432e 271 GET_WINDOWS_FUNCTION(winsock_module, WSAAsyncSelect);
272 GET_WINDOWS_FUNCTION(winsock_module, WSAEventSelect);
273 GET_WINDOWS_FUNCTION(winsock_module, select);
274 GET_WINDOWS_FUNCTION(winsock_module, WSAGetLastError);
275 GET_WINDOWS_FUNCTION(winsock_module, WSAEnumNetworkEvents);
276 GET_WINDOWS_FUNCTION(winsock_module, WSAStartup);
277 GET_WINDOWS_FUNCTION(winsock_module, WSACleanup);
278 GET_WINDOWS_FUNCTION(winsock_module, closesocket);
279 GET_WINDOWS_FUNCTION(winsock_module, ntohl);
280 GET_WINDOWS_FUNCTION(winsock_module, htonl);
281 GET_WINDOWS_FUNCTION(winsock_module, htons);
282 GET_WINDOWS_FUNCTION(winsock_module, ntohs);
283 GET_WINDOWS_FUNCTION(winsock_module, gethostname);
284 GET_WINDOWS_FUNCTION(winsock_module, gethostbyname);
285 GET_WINDOWS_FUNCTION(winsock_module, getservbyname);
286 GET_WINDOWS_FUNCTION(winsock_module, inet_addr);
287 GET_WINDOWS_FUNCTION(winsock_module, inet_ntoa);
288 GET_WINDOWS_FUNCTION(winsock_module, connect);
289 GET_WINDOWS_FUNCTION(winsock_module, bind);
290 GET_WINDOWS_FUNCTION(winsock_module, setsockopt);
291 GET_WINDOWS_FUNCTION(winsock_module, socket);
292 GET_WINDOWS_FUNCTION(winsock_module, listen);
293 GET_WINDOWS_FUNCTION(winsock_module, send);
294 GET_WINDOWS_FUNCTION(winsock_module, ioctlsocket);
295 GET_WINDOWS_FUNCTION(winsock_module, accept);
296 GET_WINDOWS_FUNCTION(winsock_module, recv);
297 GET_WINDOWS_FUNCTION(winsock_module, WSAIoctl);
7440fd44 298
c9ef99df 299 /* Try to get the best WinSock version we can get */
300 if (!sk_startup(2,2) &&
301 !sk_startup(2,0) &&
302 !sk_startup(1,1)) {
7440fd44 303 fatalbox("Unable to initialise WinSock");
304 }
7440fd44 305
2f75bae1 306 sktree = newtree234(cmpfortree);
307}
308
93b581bd 309void sk_cleanup(void)
310{
311 Actual_Socket s;
312 int i;
313
314 if (sktree) {
315 for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
7440fd44 316 p_closesocket(s->s);
93b581bd 317 }
679539d7 318 freetree234(sktree);
319 sktree = NULL;
93b581bd 320 }
7440fd44 321
13874a7c 322 if (p_WSACleanup)
323 p_WSACleanup();
7440fd44 324 if (winsock_module)
325 FreeLibrary(winsock_module);
635d063d 326#ifndef NO_IPV6
7555d6a5 327 if (wship6_module)
328 FreeLibrary(wship6_module);
635d063d 329#endif
93b581bd 330}
331
32874aea 332char *winsock_error_string(int error)
333{
e74fbad9 334 switch (error) {
32874aea 335 case WSAEACCES:
336 return "Network error: Permission denied";
337 case WSAEADDRINUSE:
338 return "Network error: Address already in use";
339 case WSAEADDRNOTAVAIL:
340 return "Network error: Cannot assign requested address";
341 case WSAEAFNOSUPPORT:
342 return
343 "Network error: Address family not supported by protocol family";
344 case WSAEALREADY:
345 return "Network error: Operation already in progress";
346 case WSAECONNABORTED:
347 return "Network error: Software caused connection abort";
348 case WSAECONNREFUSED:
349 return "Network error: Connection refused";
350 case WSAECONNRESET:
351 return "Network error: Connection reset by peer";
352 case WSAEDESTADDRREQ:
353 return "Network error: Destination address required";
354 case WSAEFAULT:
355 return "Network error: Bad address";
356 case WSAEHOSTDOWN:
357 return "Network error: Host is down";
358 case WSAEHOSTUNREACH:
359 return "Network error: No route to host";
360 case WSAEINPROGRESS:
361 return "Network error: Operation now in progress";
362 case WSAEINTR:
363 return "Network error: Interrupted function call";
364 case WSAEINVAL:
365 return "Network error: Invalid argument";
366 case WSAEISCONN:
367 return "Network error: Socket is already connected";
368 case WSAEMFILE:
369 return "Network error: Too many open files";
370 case WSAEMSGSIZE:
371 return "Network error: Message too long";
372 case WSAENETDOWN:
373 return "Network error: Network is down";
374 case WSAENETRESET:
375 return "Network error: Network dropped connection on reset";
376 case WSAENETUNREACH:
377 return "Network error: Network is unreachable";
378 case WSAENOBUFS:
379 return "Network error: No buffer space available";
380 case WSAENOPROTOOPT:
381 return "Network error: Bad protocol option";
382 case WSAENOTCONN:
383 return "Network error: Socket is not connected";
384 case WSAENOTSOCK:
385 return "Network error: Socket operation on non-socket";
386 case WSAEOPNOTSUPP:
387 return "Network error: Operation not supported";
388 case WSAEPFNOSUPPORT:
389 return "Network error: Protocol family not supported";
390 case WSAEPROCLIM:
391 return "Network error: Too many processes";
392 case WSAEPROTONOSUPPORT:
393 return "Network error: Protocol not supported";
394 case WSAEPROTOTYPE:
395 return "Network error: Protocol wrong type for socket";
396 case WSAESHUTDOWN:
397 return "Network error: Cannot send after socket shutdown";
398 case WSAESOCKTNOSUPPORT:
399 return "Network error: Socket type not supported";
400 case WSAETIMEDOUT:
401 return "Network error: Connection timed out";
402 case WSAEWOULDBLOCK:
403 return "Network error: Resource temporarily unavailable";
404 case WSAEDISCON:
405 return "Network error: Graceful shutdown in progress";
406 default:
407 return "Unknown network error";
e74fbad9 408 }
409}
410
05581745 411SockAddr sk_namelookup(const char *host, char **canonicalname,
412 int address_family)
c4d8e107 413{
3d88e64d 414 SockAddr ret = snew(struct SockAddr_tag);
2f75bae1 415 unsigned long a;
6e1ebb76 416 char realhost[8192];
facf7568 417 int hint_family;
2f75bae1 418
facf7568 419 /* Default to IPv4. */
420 hint_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
05581745 421#ifndef NO_IPV6
422 address_family == ADDRTYPE_IPV6 ? AF_INET6 :
423#endif
424 AF_UNSPEC);
facf7568 425
426 /* Clear the structure and default to IPv4. */
427 memset(ret, 0, sizeof(struct SockAddr_tag));
1822a5e7 428#ifndef NO_IPV6
facf7568 429 ret->ais = NULL;
1822a5e7 430#endif
2cd38976 431 ret->addresses = NULL;
facf7568 432 ret->resolved = FALSE;
5025a993 433 ret->refcount = 1;
6e1ebb76 434 *realhost = '\0';
c4d8e107 435
7440fd44 436 if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
7e480357 437 struct hostent *h = NULL;
438 int err;
05581745 439#ifndef NO_IPV6
c4d8e107 440 /*
7555d6a5 441 * Use getaddrinfo when it's available
c4d8e107 442 */
7555d6a5 443 if (p_getaddrinfo) {
38bd69cd 444 struct addrinfo hints;
c9ef99df 445#ifdef NET_SETUP_DIAGNOSTICS
446 logevent(NULL, "Using getaddrinfo() for resolving");
447#endif
38bd69cd 448 memset(&hints, 0, sizeof(hints));
facf7568 449 hints.ai_family = hint_family;
ac0c8510 450 hints.ai_flags = AI_CANONNAME;
7555d6a5 451 if ((err = p_getaddrinfo(host, NULL, &hints, &ret->ais)) == 0)
facf7568 452 ret->resolved = TRUE;
32874aea 453 } else
c4d8e107 454#endif
32874aea 455 {
c9ef99df 456#ifdef NET_SETUP_DIAGNOSTICS
457 logevent(NULL, "Using gethostbyname() for resolving");
458#endif
c4d8e107 459 /*
460 * Otherwise use the IPv4-only gethostbyname...
05581745 461 * (NOTE: we don't use gethostbyname as a fallback!)
c4d8e107 462 */
38bd69cd 463 if ( (h = p_gethostbyname(host)) )
facf7568 464 ret->resolved = TRUE;
38bd69cd 465 else
466 err = p_WSAGetLastError();
c4d8e107 467 }
c4d8e107 468
facf7568 469 if (!ret->resolved) {
c4d8e107 470 ret->error = (err == WSAENETDOWN ? "Network is down" :
38bd69cd 471 err == WSAHOST_NOT_FOUND ? "Host does not exist" :
472 err == WSATRY_AGAIN ? "Host not found" :
05581745 473#ifndef NO_IPV6
c9ef99df 474 p_getaddrinfo&&p_gai_strerror ? p_gai_strerror(err) :
c4d8e107 475#endif
476 "gethostbyname: unknown error");
32874aea 477 } else {
c4d8e107 478 ret->error = NULL;
479
05581745 480#ifndef NO_IPV6
c4d8e107 481 /* If we got an address info use that... */
facf7568 482 if (ret->ais) {
c4d8e107 483 /* Are we in IPv4 fallback mode? */
484 /* We put the IPv4 address into the a variable so we can further-on use the IPv4 code... */
facf7568 485 if (ret->ais->ai_family == AF_INET)
32874aea 486 memcpy(&a,
facf7568 487 (char *) &((SOCKADDR_IN *) ret->ais->
32874aea 488 ai_addr)->sin_addr, sizeof(a));
c4d8e107 489
facf7568 490 if (ret->ais->ai_canonname)
491 strncpy(realhost, ret->ais->ai_canonname, lenof(realhost));
ac0c8510 492 else
493 strncpy(realhost, host, lenof(realhost));
c4d8e107 494 }
495 /* We used the IPv4-only gethostbyname()... */
496 else
c4d8e107 497#endif
32874aea 498 {
7555d6a5 499 int n;
500 for (n = 0; h->h_addr_list[n]; n++);
501 ret->addresses = snewn(n, unsigned long);
502 ret->naddresses = n;
503 for (n = 0; n < ret->naddresses; n++) {
504 memcpy(&a, h->h_addr_list[n], sizeof(a));
505 ret->addresses[n] = p_ntohl(a);
506 }
c4d8e107 507 memcpy(&a, h->h_addr, sizeof(a));
508 /* This way we are always sure the h->h_name is valid :) */
6e1ebb76 509 strncpy(realhost, h->h_name, sizeof(realhost));
c4d8e107 510 }
c4d8e107 511 }
32874aea 512 } else {
87ed061f 513 /*
514 * This must be a numeric IPv4 address because it caused a
515 * success return from inet_addr.
516 */
7555d6a5 517 ret->addresses = snewn(1, unsigned long);
518 ret->naddresses = 1;
7555d6a5 519 ret->addresses[0] = p_ntohl(a);
facf7568 520 ret->resolved = TRUE;
6e1ebb76 521 strncpy(realhost, host, sizeof(realhost));
2f75bae1 522 }
6e1ebb76 523 realhost[lenof(realhost)-1] = '\0';
3d88e64d 524 *canonicalname = snewn(1+strlen(realhost), char);
6e1ebb76 525 strcpy(*canonicalname, realhost);
2f75bae1 526 return ret;
527}
528
e8fa8f62 529SockAddr sk_nonamelookup(const char *host)
b7a189f3 530{
3d88e64d 531 SockAddr ret = snew(struct SockAddr_tag);
ab0873ab 532 ret->error = NULL;
facf7568 533 ret->resolved = FALSE;
1822a5e7 534#ifndef NO_IPV6
facf7568 535 ret->ais = NULL;
1822a5e7 536#endif
2cd38976 537 ret->addresses = NULL;
1822a5e7 538 ret->naddresses = 0;
5025a993 539 ret->refcount = 1;
b7a189f3 540 strncpy(ret->hostname, host, lenof(ret->hostname));
541 ret->hostname[lenof(ret->hostname)-1] = '\0';
542 return ret;
543}
544
facf7568 545int sk_nextaddr(SockAddr addr, SockAddrStep *step)
7555d6a5 546{
547#ifndef NO_IPV6
facf7568 548 if (step->ai) {
549 if (step->ai->ai_next) {
550 step->ai = step->ai->ai_next;
7555d6a5 551 return TRUE;
552 } else
553 return FALSE;
554 }
555#endif
facf7568 556 if (step->curraddr+1 < addr->naddresses) {
557 step->curraddr++;
7555d6a5 558 return TRUE;
559 } else {
560 return FALSE;
561 }
562}
563
3ad9d396 564void sk_getaddr(SockAddr addr, char *buf, int buflen)
565{
facf7568 566 SockAddrStep step;
567 START_STEP(addr, step);
568
05581745 569#ifndef NO_IPV6
facf7568 570 if (step.ai) {
1c51badd 571 int err = 0;
c9ef99df 572 if (p_WSAAddressToStringA) {
1c51badd 573 DWORD dwbuflen = buflen;
574 err = p_WSAAddressToStringA(step.ai->ai_addr, step.ai->ai_addrlen,
575 NULL, buf, &dwbuflen);
c9ef99df 576 } else
1c51badd 577 err = -1;
578 if (err) {
579 strncpy(buf, addr->hostname, buflen);
580 if (!buf[0])
581 strncpy(buf, "<unknown>", buflen);
582 buf[buflen-1] = '\0';
583 }
b7a189f3 584 } else
3ad9d396 585#endif
facf7568 586 if (SOCKADDR_FAMILY(addr, step) == AF_INET) {
3ad9d396 587 struct in_addr a;
facf7568 588 assert(addr->addresses && step.curraddr < addr->naddresses);
589 a.s_addr = p_htonl(addr->addresses[step.curraddr]);
7440fd44 590 strncpy(buf, p_inet_ntoa(a), buflen);
b7a189f3 591 buf[buflen-1] = '\0';
3ad9d396 592 } else {
b7a189f3 593 strncpy(buf, addr->hostname, buflen);
594 buf[buflen-1] = '\0';
3ad9d396 595 }
3ad9d396 596}
597
b804e1e5 598int sk_hostname_is_local(char *name)
599{
db74a69d 600 return !strcmp(name, "localhost") ||
601 !strcmp(name, "::1") ||
602 !strncmp(name, "127.", 4);
b804e1e5 603}
604
a143ea0a 605static INTERFACE_INFO local_interfaces[16];
606static int n_local_interfaces; /* 0=not yet, -1=failed, >0=number */
607
608static int ipv4_is_local_addr(struct in_addr addr)
609{
610 if (ipv4_is_loopback(addr))
611 return 1; /* loopback addresses are local */
612 if (!n_local_interfaces) {
613 SOCKET s = p_socket(AF_INET, SOCK_DGRAM, 0);
614 DWORD retbytes;
615
616 if (p_WSAIoctl &&
617 p_WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0,
618 local_interfaces, sizeof(local_interfaces),
619 &retbytes, NULL, NULL) == 0)
620 n_local_interfaces = retbytes / sizeof(INTERFACE_INFO);
621 else
622 logevent(NULL, "Unable to get list of local IP addresses");
623 }
624 if (n_local_interfaces > 0) {
625 int i;
626 for (i = 0; i < n_local_interfaces; i++) {
627 SOCKADDR_IN *address =
628 (SOCKADDR_IN *)&local_interfaces[i].iiAddress;
629 if (address->sin_addr.s_addr == addr.s_addr)
630 return 1; /* this address is local */
631 }
632 }
633 return 0; /* this address is not local */
634}
635
b804e1e5 636int sk_address_is_local(SockAddr addr)
637{
facf7568 638 SockAddrStep step;
639 int family;
640 START_STEP(addr, step);
641 family = SOCKADDR_FAMILY(addr, step);
642
05581745 643#ifndef NO_IPV6
facf7568 644 if (family == AF_INET6) {
645 return IN6_IS_ADDR_LOOPBACK((const struct in6_addr *)step.ai->ai_addr);
b7a189f3 646 } else
b804e1e5 647#endif
facf7568 648 if (family == AF_INET) {
2b4bbb9b 649#ifndef NO_IPV6
facf7568 650 if (step.ai) {
651 return ipv4_is_local_addr(((struct sockaddr_in *)step.ai->ai_addr)
2b4bbb9b 652 ->sin_addr);
653 } else
654#endif
655 {
656 struct in_addr a;
facf7568 657 assert(addr->addresses && step.curraddr < addr->naddresses);
658 a.s_addr = p_htonl(addr->addresses[step.curraddr]);
2b4bbb9b 659 return ipv4_is_local_addr(a);
660 }
b804e1e5 661 } else {
facf7568 662 assert(family == AF_UNSPEC);
b7a189f3 663 return 0; /* we don't know; assume not */
b804e1e5 664 }
b804e1e5 665}
666
6971bbe7 667int sk_addrtype(SockAddr addr)
668{
facf7568 669 SockAddrStep step;
670 int family;
671 START_STEP(addr, step);
672 family = SOCKADDR_FAMILY(addr, step);
673
674 return (family == AF_INET ? ADDRTYPE_IPV4 :
05581745 675#ifndef NO_IPV6
facf7568 676 family == AF_INET6 ? ADDRTYPE_IPV6 :
b7a189f3 677#endif
678 ADDRTYPE_NAME);
6971bbe7 679}
680
681void sk_addrcopy(SockAddr addr, char *buf)
682{
facf7568 683 SockAddrStep step;
684 int family;
685 START_STEP(addr, step);
686 family = SOCKADDR_FAMILY(addr, step);
687
688 assert(family != AF_UNSPEC);
05581745 689#ifndef NO_IPV6
facf7568 690 if (step.ai) {
691 if (family == AF_INET)
692 memcpy(buf, &((struct sockaddr_in *)step.ai->ai_addr)->sin_addr,
7555d6a5 693 sizeof(struct in_addr));
facf7568 694 else if (family == AF_INET6)
695 memcpy(buf, &((struct sockaddr_in6 *)step.ai->ai_addr)->sin6_addr,
7555d6a5 696 sizeof(struct in6_addr));
697 else
698 assert(FALSE);
b7a189f3 699 } else
6971bbe7 700#endif
facf7568 701 if (family == AF_INET) {
6971bbe7 702 struct in_addr a;
facf7568 703 assert(addr->addresses && step.curraddr < addr->naddresses);
704 a.s_addr = p_htonl(addr->addresses[step.curraddr]);
96d9eb89 705 memcpy(buf, (char*) &a.s_addr, 4);
6971bbe7 706 }
6971bbe7 707}
708
32874aea 709void sk_addr_free(SockAddr addr)
710{
5025a993 711 if (--addr->refcount > 0)
712 return;
7555d6a5 713#ifndef NO_IPV6
714 if (addr->ais && p_freeaddrinfo)
715 p_freeaddrinfo(addr->ais);
716#endif
717 if (addr->addresses)
718 sfree(addr->addresses);
2f75bae1 719 sfree(addr);
720}
721
5025a993 722SockAddr sk_addr_dup(SockAddr addr)
723{
724 addr->refcount++;
725 return addr;
726}
727
32874aea 728static Plug sk_tcp_plug(Socket sock, Plug p)
729{
7e78000d 730 Actual_Socket s = (Actual_Socket) sock;
731 Plug ret = s->plug;
32874aea 732 if (p)
733 s->plug = p;
7e78000d 734 return ret;
735}
736
32874aea 737static void sk_tcp_flush(Socket s)
738{
7e78000d 739 /*
740 * We send data to the socket as soon as we can anyway,
741 * so we don't need to do anything here. :-)
742 */
743}
744
2d466ffd 745static void sk_tcp_close(Socket s);
e0e7dff8 746static int sk_tcp_write(Socket s, const char *data, int len);
747static int sk_tcp_write_oob(Socket s, const char *data, int len);
8eebd221 748static void sk_tcp_set_private_ptr(Socket s, void *ptr);
749static void *sk_tcp_get_private_ptr(Socket s);
750static void sk_tcp_set_frozen(Socket s, int is_frozen);
cbe2d68f 751static const char *sk_tcp_socket_error(Socket s);
7e78000d 752
d74d141c 753extern char *do_select(SOCKET skt, int startup);
754
755Socket sk_register(void *sock, Plug plug)
756{
c85623f9 757 static const struct socket_function_table fn_table = {
d74d141c 758 sk_tcp_plug,
759 sk_tcp_close,
760 sk_tcp_write,
761 sk_tcp_write_oob,
762 sk_tcp_flush,
8eebd221 763 sk_tcp_set_private_ptr,
764 sk_tcp_get_private_ptr,
765 sk_tcp_set_frozen,
d74d141c 766 sk_tcp_socket_error
767 };
768
769 DWORD err;
770 char *errstr;
771 Actual_Socket ret;
772
773 /*
774 * Create Socket structure.
775 */
3d88e64d 776 ret = snew(struct Socket_tag);
d74d141c 777 ret->fn = &fn_table;
778 ret->error = NULL;
779 ret->plug = plug;
5471d09a 780 bufchain_init(&ret->output_data);
d74d141c 781 ret->writable = 1; /* to start with */
782 ret->sending_oob = 0;
783 ret->frozen = 1;
5471d09a 784 ret->frozen_readable = 0;
bc4802a1 785 ret->localhost_only = 0; /* unused, but best init anyway */
7732d38a 786 ret->pending_error = 0;
ae400b95 787 ret->parent = ret->child = NULL;
7555d6a5 788 ret->addr = NULL;
d74d141c 789
790 ret->s = (SOCKET)sock;
791
792 if (ret->s == INVALID_SOCKET) {
7440fd44 793 err = p_WSAGetLastError();
d74d141c 794 ret->error = winsock_error_string(err);
795 return (Socket) ret;
796 }
797
798 ret->oobinline = 0;
799
800 /* Set up a select mechanism. This could be an AsyncSelect on a
801 * window, or an EventSelect on an event object. */
802 errstr = do_select(ret->s, 1);
803 if (errstr) {
804 ret->error = errstr;
805 return (Socket) ret;
806 }
807
808 add234(sktree, ret);
809
810 return (Socket) ret;
811}
812
7555d6a5 813static DWORD try_connect(Actual_Socket sock)
7e78000d 814{
2f75bae1 815 SOCKET s;
05581745 816#ifndef NO_IPV6
c4d8e107 817 SOCKADDR_IN6 a6;
818#endif
2f75bae1 819 SOCKADDR_IN a;
820 DWORD err;
821 char *errstr;
c91409da 822 short localport;
7555d6a5 823 int family;
2f75bae1 824
7555d6a5 825 if (sock->s != INVALID_SOCKET) {
826 do_select(sock->s, 0);
827 p_closesocket(sock->s);
828 }
829
830 plug_log(sock->plug, 0, sock->addr, sock->port, NULL, 0);
2f75bae1 831
832 /*
833 * Open socket.
834 */
facf7568 835 family = SOCKADDR_FAMILY(sock->addr, sock->step);
7555d6a5 836
b34544ba 837 /*
838 * Remove the socket from the tree before we overwrite its
839 * internal socket id, because that forms part of the tree's
840 * sorting criterion. We'll add it back before exiting this
841 * function, whether we changed anything or not.
842 */
843 del234(sktree, sock);
844
7555d6a5 845 s = p_socket(family, SOCK_STREAM, 0);
846 sock->s = s;
2f75bae1 847
848 if (s == INVALID_SOCKET) {
7440fd44 849 err = p_WSAGetLastError();
7555d6a5 850 sock->error = winsock_error_string(err);
851 goto ret;
2f75bae1 852 }
4b1e8acc 853
7555d6a5 854 if (sock->oobinline) {
1ad4eb6f 855 BOOL b = TRUE;
7440fd44 856 p_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
1ad4eb6f 857 }
2f75bae1 858
7555d6a5 859 if (sock->nodelay) {
2184a5d9 860 BOOL b = TRUE;
7440fd44 861 p_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
2184a5d9 862 }
863
7555d6a5 864 if (sock->keepalive) {
79bf227b 865 BOOL b = TRUE;
866 p_setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b));
867 }
868
2f75bae1 869 /*
870 * Bind to local address.
871 */
7555d6a5 872 if (sock->privport)
32874aea 873 localport = 1023; /* count from 1023 downwards */
c4d8e107 874 else
32874aea 875 localport = 0; /* just use port 0 (ie winsock picks) */
c91409da 876
877 /* Loop round trying to bind */
878 while (1) {
7555d6a5 879 int sockcode;
c91409da 880
05581745 881#ifndef NO_IPV6
7555d6a5 882 if (family == AF_INET6) {
32874aea 883 memset(&a6, 0, sizeof(a6));
884 a6.sin6_family = AF_INET6;
05581745 885 /*a6.sin6_addr = in6addr_any; */ /* == 0 done by memset() */
7440fd44 886 a6.sin6_port = p_htons(localport);
32874aea 887 } else
c4d8e107 888#endif
32874aea 889 {
890 a.sin_family = AF_INET;
7440fd44 891 a.sin_addr.s_addr = p_htonl(INADDR_ANY);
892 a.sin_port = p_htons(localport);
32874aea 893 }
05581745 894#ifndef NO_IPV6
facf7568 895 sockcode = p_bind(s, (family == AF_INET6 ?
896 (struct sockaddr *) &a6 :
897 (struct sockaddr *) &a),
898 (family == AF_INET6 ? sizeof(a6) : sizeof(a)));
c4d8e107 899#else
7555d6a5 900 sockcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
c4d8e107 901#endif
7555d6a5 902 if (sockcode != SOCKET_ERROR) {
32874aea 903 err = 0;
904 break; /* done */
905 } else {
7440fd44 906 err = p_WSAGetLastError();
32874aea 907 if (err != WSAEADDRINUSE) /* failed, for a bad reason */
908 break;
909 }
910
911 if (localport == 0)
912 break; /* we're only looping once */
913 localport--;
914 if (localport == 0)
915 break; /* we might have got to the end */
c91409da 916 }
917
32874aea 918 if (err) {
7555d6a5 919 sock->error = winsock_error_string(err);
920 goto ret;
2f75bae1 921 }
922
923 /*
924 * Connect to remote address.
925 */
05581745 926#ifndef NO_IPV6
facf7568 927 if (sock->step.ai) {
7555d6a5 928 if (family == AF_INET6) {
929 a6.sin6_family = AF_INET6;
930 a6.sin6_port = p_htons((short) sock->port);
931 a6.sin6_addr =
facf7568 932 ((struct sockaddr_in6 *) sock->step.ai->ai_addr)->sin6_addr;
933 a6.sin6_flowinfo = ((struct sockaddr_in6 *) sock->step.ai->ai_addr)->sin6_flowinfo;
934 a6.sin6_scope_id = ((struct sockaddr_in6 *) sock->step.ai->ai_addr)->sin6_scope_id;
7555d6a5 935 } else {
936 a.sin_family = AF_INET;
937 a.sin_addr =
facf7568 938 ((struct sockaddr_in *) sock->step.ai->ai_addr)->sin_addr;
7555d6a5 939 a.sin_port = p_htons((short) sock->port);
940 }
32874aea 941 } else
c4d8e107 942#endif
32874aea 943 {
facf7568 944 assert(sock->addr->addresses && sock->step.curraddr < sock->addr->naddresses);
c4d8e107 945 a.sin_family = AF_INET;
facf7568 946 a.sin_addr.s_addr = p_htonl(sock->addr->addresses[sock->step.curraddr]);
7555d6a5 947 a.sin_port = p_htons((short) sock->port);
c4d8e107 948 }
3ad9d396 949
950 /* Set up a select mechanism. This could be an AsyncSelect on a
951 * window, or an EventSelect on an event object. */
952 errstr = do_select(s, 1);
953 if (errstr) {
7555d6a5 954 sock->error = errstr;
955 err = 1;
956 goto ret;
3ad9d396 957 }
958
32874aea 959 if ((
05581745 960#ifndef NO_IPV6
7555d6a5 961 p_connect(s,
962 ((family == AF_INET6) ? (struct sockaddr *) &a6 :
963 (struct sockaddr *) &a),
964 (family == AF_INET6) ? sizeof(a6) : sizeof(a))
c4d8e107 965#else
7440fd44 966 p_connect(s, (struct sockaddr *) &a, sizeof(a))
c4d8e107 967#endif
32874aea 968 ) == SOCKET_ERROR) {
7440fd44 969 err = p_WSAGetLastError();
3ad9d396 970 /*
971 * We expect a potential EWOULDBLOCK here, because the
972 * chances are the front end has done a select for
973 * FD_CONNECT, so that connect() will complete
974 * asynchronously.
975 */
976 if ( err != WSAEWOULDBLOCK ) {
7555d6a5 977 sock->error = winsock_error_string(err);
978 goto ret;
3ad9d396 979 }
980 } else {
981 /*
982 * If we _don't_ get EWOULDBLOCK, the connect has completed
983 * and we should set the socket as writable.
984 */
7555d6a5 985 sock->writable = 1;
2f75bae1 986 }
987
7555d6a5 988 err = 0;
989
990 ret:
b34544ba 991
992 /*
993 * No matter what happened, put the socket back in the tree.
994 */
995 add234(sktree, sock);
996
7555d6a5 997 if (err)
998 plug_log(sock->plug, 1, sock->addr, sock->port, sock->error, err);
999 return err;
1000}
1001
1002Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
1003 int nodelay, int keepalive, Plug plug)
1004{
1005 static const struct socket_function_table fn_table = {
1006 sk_tcp_plug,
1007 sk_tcp_close,
1008 sk_tcp_write,
1009 sk_tcp_write_oob,
1010 sk_tcp_flush,
1011 sk_tcp_set_private_ptr,
1012 sk_tcp_get_private_ptr,
1013 sk_tcp_set_frozen,
1014 sk_tcp_socket_error
1015 };
1016
1017 Actual_Socket ret;
1018 DWORD err;
1019
1020 /*
1021 * Create Socket structure.
1022 */
1023 ret = snew(struct Socket_tag);
1024 ret->fn = &fn_table;
1025 ret->error = NULL;
1026 ret->plug = plug;
1027 bufchain_init(&ret->output_data);
1028 ret->connected = 0; /* to start with */
1029 ret->writable = 0; /* to start with */
1030 ret->sending_oob = 0;
1031 ret->frozen = 0;
1032 ret->frozen_readable = 0;
1033 ret->localhost_only = 0; /* unused, but best init anyway */
1034 ret->pending_error = 0;
1035 ret->parent = ret->child = NULL;
1036 ret->oobinline = oobinline;
1037 ret->nodelay = nodelay;
1038 ret->keepalive = keepalive;
1039 ret->privport = privport;
1040 ret->port = port;
1041 ret->addr = addr;
facf7568 1042 START_STEP(ret->addr, ret->step);
7555d6a5 1043 ret->s = INVALID_SOCKET;
1044
1045 err = 0;
1046 do {
1047 err = try_connect(ret);
facf7568 1048 } while (err && sk_nextaddr(ret->addr, &ret->step));
f85e6f6e 1049
7e78000d 1050 return (Socket) ret;
2f75bae1 1051}
1052
05581745 1053Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only,
ae400b95 1054 int orig_address_family)
d74d141c 1055{
c85623f9 1056 static const struct socket_function_table fn_table = {
d74d141c 1057 sk_tcp_plug,
1058 sk_tcp_close,
1059 sk_tcp_write,
1060 sk_tcp_write_oob,
1061 sk_tcp_flush,
8eebd221 1062 sk_tcp_set_private_ptr,
1063 sk_tcp_get_private_ptr,
1064 sk_tcp_set_frozen,
d74d141c 1065 sk_tcp_socket_error
1066 };
1067
1068 SOCKET s;
05581745 1069#ifndef NO_IPV6
d74d141c 1070 SOCKADDR_IN6 a6;
1071#endif
1072 SOCKADDR_IN a;
05581745 1073
d74d141c 1074 DWORD err;
1075 char *errstr;
1076 Actual_Socket ret;
1077 int retcode;
1078 int on = 1;
1079
ae400b95 1080 int address_family;
1081
d74d141c 1082 /*
1083 * Create Socket structure.
1084 */
3d88e64d 1085 ret = snew(struct Socket_tag);
d74d141c 1086 ret->fn = &fn_table;
1087 ret->error = NULL;
1088 ret->plug = plug;
5471d09a 1089 bufchain_init(&ret->output_data);
d74d141c 1090 ret->writable = 0; /* to start with */
1091 ret->sending_oob = 0;
1092 ret->frozen = 0;
5471d09a 1093 ret->frozen_readable = 0;
bc4802a1 1094 ret->localhost_only = local_host_only;
7732d38a 1095 ret->pending_error = 0;
ae400b95 1096 ret->parent = ret->child = NULL;
7555d6a5 1097 ret->addr = NULL;
d74d141c 1098
1099 /*
05581745 1100 * Translate address_family from platform-independent constants
1101 * into local reality.
1102 */
ae400b95 1103 address_family = (orig_address_family == ADDRTYPE_IPV4 ? AF_INET :
05581745 1104#ifndef NO_IPV6
ae400b95 1105 orig_address_family == ADDRTYPE_IPV6 ? AF_INET6 :
05581745 1106#endif
1107 AF_UNSPEC);
ae400b95 1108
1109 /*
1110 * Our default, if passed the `don't care' value
1111 * ADDRTYPE_UNSPEC, is to listen on IPv4. If IPv6 is supported,
1112 * we will also set up a second socket listening on IPv6, but
1113 * the v4 one is primary since that ought to work even on
1114 * non-v6-supporting systems.
1115 */
1116 if (address_family == AF_UNSPEC) address_family = AF_INET;
05581745 1117
1118 /*
d74d141c 1119 * Open socket.
1120 */
05581745 1121 s = p_socket(address_family, SOCK_STREAM, 0);
d74d141c 1122 ret->s = s;
1123
1124 if (s == INVALID_SOCKET) {
7440fd44 1125 err = p_WSAGetLastError();
d74d141c 1126 ret->error = winsock_error_string(err);
1127 return (Socket) ret;
1128 }
1129
1130 ret->oobinline = 0;
1131
7440fd44 1132 p_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
d74d141c 1133
05581745 1134#ifndef NO_IPV6
1135 if (address_family == AF_INET6) {
d74d141c 1136 memset(&a6, 0, sizeof(a6));
1137 a6.sin6_family = AF_INET6;
6ee9b735 1138 /* FIXME: srcaddr is ignored for IPv6, because I (SGT) don't
05581745 1139 * know how to do it. :-)
1140 * (jeroen:) saddr is specified as an address.. eg 2001:db8::1
1141 * Thus we need either a parser that understands [2001:db8::1]:80
1142 * style addresses and/or enhance this to understand hostnames too. */
bcce45ed 1143 if (local_host_only)
1144 a6.sin6_addr = in6addr_loopback;
1145 else
1146 a6.sin6_addr = in6addr_any;
7440fd44 1147 a6.sin6_port = p_htons(port);
d74d141c 1148 } else
1149#endif
1150 {
6ee9b735 1151 int got_addr = 0;
d74d141c 1152 a.sin_family = AF_INET;
6ee9b735 1153
1154 /*
1155 * Bind to source address. First try an explicitly
1156 * specified one...
1157 */
1158 if (srcaddr) {
7440fd44 1159 a.sin_addr.s_addr = p_inet_addr(srcaddr);
6ee9b735 1160 if (a.sin_addr.s_addr != INADDR_NONE) {
1161 /* Override localhost_only with specified listen addr. */
1162 ret->localhost_only = ipv4_is_loopback(a.sin_addr);
1163 got_addr = 1;
1164 }
1165 }
1166
1167 /*
1168 * ... and failing that, go with one of the standard ones.
1169 */
1170 if (!got_addr) {
1171 if (local_host_only)
7440fd44 1172 a.sin_addr.s_addr = p_htonl(INADDR_LOOPBACK);
6ee9b735 1173 else
7440fd44 1174 a.sin_addr.s_addr = p_htonl(INADDR_ANY);
6ee9b735 1175 }
1176
7440fd44 1177 a.sin_port = p_htons((short)port);
d74d141c 1178 }
05581745 1179#ifndef NO_IPV6
1180 retcode = p_bind(s, (address_family == AF_INET6 ?
d74d141c 1181 (struct sockaddr *) &a6 :
1182 (struct sockaddr *) &a),
05581745 1183 (address_family ==
d74d141c 1184 AF_INET6 ? sizeof(a6) : sizeof(a)));
1185#else
7440fd44 1186 retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
d74d141c 1187#endif
1188 if (retcode != SOCKET_ERROR) {
1189 err = 0;
1190 } else {
7440fd44 1191 err = p_WSAGetLastError();
d74d141c 1192 }
1193
1194 if (err) {
ae400b95 1195 p_closesocket(s);
d74d141c 1196 ret->error = winsock_error_string(err);
1197 return (Socket) ret;
1198 }
1199
1200
7440fd44 1201 if (p_listen(s, SOMAXCONN) == SOCKET_ERROR) {
1202 p_closesocket(s);
d74d141c 1203 ret->error = winsock_error_string(err);
1204 return (Socket) ret;
1205 }
1206
1207 /* Set up a select mechanism. This could be an AsyncSelect on a
1208 * window, or an EventSelect on an event object. */
1209 errstr = do_select(s, 1);
1210 if (errstr) {
ae400b95 1211 p_closesocket(s);
d74d141c 1212 ret->error = errstr;
1213 return (Socket) ret;
1214 }
1215
1216 add234(sktree, ret);
1217
ae400b95 1218#ifndef NO_IPV6
1219 /*
1220 * If we were given ADDRTYPE_UNSPEC, we must also create an
1221 * IPv6 listening socket and link it to this one.
1222 */
1223 if (address_family == AF_INET && orig_address_family == ADDRTYPE_UNSPEC) {
1224 Actual_Socket other;
1225
1226 other = (Actual_Socket) sk_newlistener(srcaddr, port, plug,
1227 local_host_only, ADDRTYPE_IPV6);
1228
1229 if (other) {
1230 if (!other->error) {
1231 other->parent = ret;
1232 ret->child = other;
1233 } else {
1234 sfree(other);
1235 }
1236 }
1237 }
1238#endif
1239
d74d141c 1240 return (Socket) ret;
1241}
1242
32874aea 1243static void sk_tcp_close(Socket sock)
1244{
9c964e85 1245 extern char *do_select(SOCKET skt, int startup);
7e78000d 1246 Actual_Socket s = (Actual_Socket) sock;
9c964e85 1247
ae400b95 1248 if (s->child)
1249 sk_tcp_close((Socket)s->child);
1250
2f75bae1 1251 del234(sktree, s);
1252 do_select(s->s, 0);
7440fd44 1253 p_closesocket(s->s);
7555d6a5 1254 if (s->addr)
1255 sk_addr_free(s->addr);
dcbde236 1256 sfree(s);
2f75bae1 1257}
1258
2f75bae1 1259/*
1260 * The function which tries to send on a socket once it's deemed
1261 * writable.
1262 */
32874aea 1263void try_send(Actual_Socket s)
1264{
5471d09a 1265 while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
2f75bae1 1266 int nsent;
1267 DWORD err;
5471d09a 1268 void *data;
32874aea 1269 int len, urgentflag;
1270
1271 if (s->sending_oob) {
1272 urgentflag = MSG_OOB;
1273 len = s->sending_oob;
5471d09a 1274 data = &s->oobdata;
32874aea 1275 } else {
1276 urgentflag = 0;
5471d09a 1277 bufchain_prefix(&s->output_data, &data, &len);
32874aea 1278 }
7440fd44 1279 nsent = p_send(s->s, data, len, urgentflag);
32874aea 1280 noise_ultralight(nsent);
2f75bae1 1281 if (nsent <= 0) {
7440fd44 1282 err = (nsent < 0 ? p_WSAGetLastError() : 0);
e5eb3a1c 1283 if ((err < WSABASEERR && nsent < 0) || err == WSAEWOULDBLOCK) {
d40a94b9 1284 /*
1285 * Perfectly normal: we've sent all we can for the moment.
1286 *
e5eb3a1c 1287 * (Some WinSock send() implementations can return
1288 * <0 but leave no sensible error indication -
1289 * WSAGetLastError() is called but returns zero or
1290 * a small number - so we check that case and treat
1291 * it just like WSAEWOULDBLOCK.)
d40a94b9 1292 */
2f75bae1 1293 s->writable = FALSE;
32874aea 1294 return;
2f75bae1 1295 } else if (nsent == 0 ||
32874aea 1296 err == WSAECONNABORTED || err == WSAECONNRESET) {
1297 /*
7732d38a 1298 * If send() returns CONNABORTED or CONNRESET, we
1299 * unfortunately can't just call plug_closing(),
1300 * because it's quite likely that we're currently
1301 * _in_ a call from the code we'd be calling back
1302 * to, so we'd have to make half the SSH code
1303 * reentrant. Instead we flag a pending error on
1304 * the socket, to be dealt with (by calling
1305 * plug_closing()) at some suitable future moment.
32874aea 1306 */
7732d38a 1307 s->pending_error = err;
1308 return;
2f75bae1 1309 } else {
a8327734 1310 /* We're inside the Windows frontend here, so we know
1311 * that the frontend handle is unnecessary. */
1312 logevent(NULL, winsock_error_string(err));
247308b5 1313 fatalbox("%s", winsock_error_string(err));
2f75bae1 1314 }
1315 } else {
5471d09a 1316 if (s->sending_oob) {
1317 if (nsent < len) {
1318 memmove(s->oobdata, s->oobdata+nsent, len-nsent);
1319 s->sending_oob = len - nsent;
1320 } else {
1321 s->sending_oob = 0;
1322 }
1323 } else {
1324 bufchain_consume(&s->output_data, nsent);
2f75bae1 1325 }
1326 }
1327 }
1328}
1329
e0e7dff8 1330static int sk_tcp_write(Socket sock, const char *buf, int len)
32874aea 1331{
7e78000d 1332 Actual_Socket s = (Actual_Socket) sock;
1333
2f75bae1 1334 /*
1335 * Add the data to the buffer list on the socket.
1336 */
5471d09a 1337 bufchain_add(&s->output_data, buf, len);
2f75bae1 1338
1339 /*
1340 * Now try sending from the start of the buffer list.
1341 */
1342 if (s->writable)
1343 try_send(s);
5471d09a 1344
1345 return bufchain_size(&s->output_data);
2f75bae1 1346}
1347
e0e7dff8 1348static int sk_tcp_write_oob(Socket sock, const char *buf, int len)
32874aea 1349{
7e78000d 1350 Actual_Socket s = (Actual_Socket) sock;
1351
2f75bae1 1352 /*
1353 * Replace the buffer list on the socket with the data.
1354 */
5471d09a 1355 bufchain_clear(&s->output_data);
1356 assert(len <= sizeof(s->oobdata));
1357 memcpy(s->oobdata, buf, len);
2f75bae1 1358 s->sending_oob = len;
1359
1360 /*
1361 * Now try sending from the start of the buffer list.
1362 */
1363 if (s->writable)
1364 try_send(s);
5471d09a 1365
1366 return s->sending_oob;
2f75bae1 1367}
1368
32874aea 1369int select_result(WPARAM wParam, LPARAM lParam)
1370{
f9d3f227 1371 int ret, open;
2f75bae1 1372 DWORD err;
b675c612 1373 char buf[20480]; /* nice big buffer for plenty of speed */
7e78000d 1374 Actual_Socket s;
49bad831 1375 u_long atmark;
2f75bae1 1376
1377 /* wParam is the socket itself */
cc8b0ee9 1378
ce6fcfa5 1379 if (wParam == 0)
1380 return 1; /* boggle */
cc8b0ee9 1381
32874aea 1382 s = find234(sktree, (void *) wParam, cmpforsearch);
2f75bae1 1383 if (!s)
1384 return 1; /* boggle */
1385
1386 if ((err = WSAGETSELECTERROR(lParam)) != 0) {
32874aea 1387 /*
1388 * An error has occurred on this socket. Pass it to the
1389 * plug.
1390 */
7555d6a5 1391 if (s->addr) {
1392 plug_log(s->plug, 1, s->addr, s->port,
1393 winsock_error_string(err), err);
facf7568 1394 while (s->addr && sk_nextaddr(s->addr, &s->step)) {
7555d6a5 1395 err = try_connect(s);
1396 }
1397 }
1398 if (err != 0)
1399 return plug_closing(s->plug, winsock_error_string(err), err, 0);
1400 else
1401 return 1;
2f75bae1 1402 }
1403
7d6ee6ff 1404 noise_ultralight(lParam);
1405
2f75bae1 1406 switch (WSAGETSELECTEVENT(lParam)) {
3ad9d396 1407 case FD_CONNECT:
1408 s->connected = s->writable = 1;
7555d6a5 1409 /*
1410 * Once a socket is connected, we can stop falling
1411 * back through the candidate addresses to connect
1412 * to.
1413 */
1414 if (s->addr) {
1415 sk_addr_free(s->addr);
1416 s->addr = NULL;
1417 }
3ad9d396 1418 break;
2f75bae1 1419 case FD_READ:
d74d141c 1420 /* In the case the socket is still frozen, we don't even bother */
5471d09a 1421 if (s->frozen) {
1422 s->frozen_readable = 1;
d74d141c 1423 break;
5471d09a 1424 }
d74d141c 1425
32874aea 1426 /*
1427 * We have received data on the socket. For an oobinline
1428 * socket, this might be data _before_ an urgent pointer,
1429 * in which case we send it to the back end with type==1
1430 * (data prior to urgent).
1431 */
1432 if (s->oobinline) {
1433 atmark = 1;
7440fd44 1434 p_ioctlsocket(s->s, SIOCATMARK, &atmark);
32874aea 1435 /*
1436 * Avoid checking the return value from ioctlsocket(),
1437 * on the grounds that some WinSock wrappers don't
1438 * support it. If it does nothing, we get atmark==1,
1439 * which is equivalent to `no OOB pending', so the
1440 * effect will be to non-OOB-ify any OOB data.
1441 */
1442 } else
1443 atmark = 1;
4b1e8acc 1444
7440fd44 1445 ret = p_recv(s->s, buf, sizeof(buf), 0);
32874aea 1446 noise_ultralight(ret);
2f75bae1 1447 if (ret < 0) {
7440fd44 1448 err = p_WSAGetLastError();
2f75bae1 1449 if (err == WSAEWOULDBLOCK) {
1450 break;
1451 }
1452 }
1453 if (ret < 0) {
32874aea 1454 return plug_closing(s->plug, winsock_error_string(err), err,
1455 0);
7e78000d 1456 } else if (0 == ret) {
32874aea 1457 return plug_closing(s->plug, NULL, 0, 0);
2f75bae1 1458 } else {
32874aea 1459 return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
2f75bae1 1460 }
1461 break;
1462 case FD_OOB:
32874aea 1463 /*
1464 * This will only happen on a non-oobinline socket. It
1465 * indicates that we can immediately perform an OOB read
1466 * and get back OOB data, which we will send to the back
1467 * end with type==2 (urgent data).
1468 */
7440fd44 1469 ret = p_recv(s->s, buf, sizeof(buf), MSG_OOB);
32874aea 1470 noise_ultralight(ret);
1471 if (ret <= 0) {
247308b5 1472 char *str = (ret == 0 ? "Internal networking trouble" :
7440fd44 1473 winsock_error_string(p_WSAGetLastError()));
a8327734 1474 /* We're inside the Windows frontend here, so we know
1475 * that the frontend handle is unnecessary. */
1476 logevent(NULL, str);
247308b5 1477 fatalbox("%s", str);
32874aea 1478 } else {
1479 return plug_receive(s->plug, 2, buf, ret);
1480 }
1481 break;
2f75bae1 1482 case FD_WRITE:
5471d09a 1483 {
1484 int bufsize_before, bufsize_after;
1485 s->writable = 1;
1486 bufsize_before = s->sending_oob + bufchain_size(&s->output_data);
1487 try_send(s);
1488 bufsize_after = s->sending_oob + bufchain_size(&s->output_data);
1489 if (bufsize_after < bufsize_before)
1490 plug_sent(s->plug, bufsize_after);
1491 }
2f75bae1 1492 break;
1493 case FD_CLOSE:
f9d3f227 1494 /* Signal a close on the socket. First read any outstanding data. */
32874aea 1495 open = 1;
1496 do {
7440fd44 1497 ret = p_recv(s->s, buf, sizeof(buf), 0);
32874aea 1498 if (ret < 0) {
7440fd44 1499 err = p_WSAGetLastError();
32874aea 1500 if (err == WSAEWOULDBLOCK)
1501 break;
1502 return plug_closing(s->plug, winsock_error_string(err),
1503 err, 0);
1504 } else {
1505 if (ret)
1506 open &= plug_receive(s->plug, 0, buf, ret);
1507 else
1508 open &= plug_closing(s->plug, NULL, 0, 0);
7e78000d 1509 }
f9d3f227 1510 } while (ret > 0);
32874aea 1511 return open;
d74d141c 1512 case FD_ACCEPT:
1513 {
05581745 1514#ifdef NO_IPV6
bc4802a1 1515 struct sockaddr_in isa;
05581745 1516#else
1517 struct sockaddr_storage isa;
1518#endif
1519 int addrlen = sizeof(isa);
bcce45ed 1520 SOCKET t; /* socket of connection */
1521
05581745 1522 memset(&isa, 0, sizeof(isa));
bcce45ed 1523 err = 0;
7440fd44 1524 t = p_accept(s->s,(struct sockaddr *)&isa,&addrlen);
bcce45ed 1525 if (t == INVALID_SOCKET)
1526 {
7440fd44 1527 err = p_WSAGetLastError();
bcce45ed 1528 if (err == WSATRY_AGAIN)
1529 break;
1530 }
05581745 1531#ifndef NO_IPV6
1532 if (isa.ss_family == AF_INET &&
1533 s->localhost_only &&
9f7ebadc 1534 !ipv4_is_local_addr(((struct sockaddr_in *)&isa)->sin_addr))
05581745 1535#else
9f7ebadc 1536 if (s->localhost_only && !ipv4_is_local_addr(isa.sin_addr))
05581745 1537#endif
9f7ebadc 1538 {
7440fd44 1539 p_closesocket(t); /* dodgy WinSock let nonlocal through */
bc4802a1 1540 } else if (plug_accepting(s->plug, (void*)t)) {
7440fd44 1541 p_closesocket(t); /* denied or error */
bcce45ed 1542 }
d74d141c 1543 }
2f75bae1 1544 }
1545
1546 return 1;
1547}
1548
1549/*
7732d38a 1550 * Deal with socket errors detected in try_send().
1551 */
1552void net_pending_errors(void)
1553{
1554 int i;
1555 Actual_Socket s;
1556
1557 /*
1558 * This might be a fiddly business, because it's just possible
1559 * that handling a pending error on one socket might cause
1560 * others to be closed. (I can't think of any reason this might
1561 * happen in current SSH implementation, but to maintain
1562 * generality of this network layer I'll assume the worst.)
1563 *
1564 * So what we'll do is search the socket list for _one_ socket
1565 * with a pending error, and then handle it, and then search
1566 * the list again _from the beginning_. Repeat until we make a
1567 * pass with no socket errors present. That way we are
1568 * protected against the socket list changing under our feet.
1569 */
1570
1571 do {
1572 for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
1573 if (s->pending_error) {
1574 /*
1575 * An error has occurred on this socket. Pass it to the
1576 * plug.
1577 */
1578 plug_closing(s->plug,
1579 winsock_error_string(s->pending_error),
1580 s->pending_error, 0);
1581 break;
1582 }
1583 }
1584 } while (s);
1585}
1586
1587/*
2f75bae1 1588 * Each socket abstraction contains a `void *' private field in
1589 * which the client can keep state.
1590 */
8eebd221 1591static void sk_tcp_set_private_ptr(Socket sock, void *ptr)
32874aea 1592{
7e78000d 1593 Actual_Socket s = (Actual_Socket) sock;
2f75bae1 1594 s->private_ptr = ptr;
1595}
32874aea 1596
8eebd221 1597static void *sk_tcp_get_private_ptr(Socket sock)
32874aea 1598{
7e78000d 1599 Actual_Socket s = (Actual_Socket) sock;
2f75bae1 1600 return s->private_ptr;
1601}
1602
1603/*
1604 * Special error values are returned from sk_namelookup and sk_new
1605 * if there's a problem. These functions extract an error message,
1606 * or return NULL if there's no problem.
1607 */
cbe2d68f 1608const char *sk_addr_error(SockAddr addr)
32874aea 1609{
2f75bae1 1610 return addr->error;
1611}
cbe2d68f 1612static const char *sk_tcp_socket_error(Socket sock)
32874aea 1613{
7e78000d 1614 Actual_Socket s = (Actual_Socket) sock;
2f75bae1 1615 return s->error;
1616}
1617
8eebd221 1618static void sk_tcp_set_frozen(Socket sock, int is_frozen)
d74d141c 1619{
1620 Actual_Socket s = (Actual_Socket) sock;
5471d09a 1621 if (s->frozen == is_frozen)
1622 return;
d74d141c 1623 s->frozen = is_frozen;
615cdc1f 1624 if (!is_frozen) {
1625 do_select(s->s, 1);
1626 if (s->frozen_readable) {
1627 char c;
1628 p_recv(s->s, &c, 1, MSG_PEEK);
1629 }
d74d141c 1630 }
5471d09a 1631 s->frozen_readable = 0;
d74d141c 1632}
1633
9f7ebadc 1634void socket_reselect_all(void)
1635{
1636 Actual_Socket s;
1637 int i;
1638
1639 for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
1640 if (!s->frozen)
1641 do_select(s->s, 1);
1642 }
1643}
1644
2f75bae1 1645/*
1646 * For Plink: enumerate all sockets currently active.
1647 */
32874aea 1648SOCKET first_socket(int *state)
1649{
d2371c81 1650 Actual_Socket s;
1651 *state = 0;
1652 s = index234(sktree, (*state)++);
2f75bae1 1653 return s ? s->s : INVALID_SOCKET;
1654}
32874aea 1655
1656SOCKET next_socket(int *state)
1657{
d2371c81 1658 Actual_Socket s = index234(sktree, (*state)++);
2f75bae1 1659 return s ? s->s : INVALID_SOCKET;
1660}
68a49acb 1661
39934deb 1662extern int socket_writable(SOCKET skt)
1663{
1664 Actual_Socket s = find234(sktree, (void *)skt, cmpforsearch);
1665
1666 if (s)
1667 return bufchain_size(&s->output_data) > 0;
1668 else
1669 return 0;
1670}
1671
68a49acb 1672int net_service_lookup(char *service)
1673{
1674 struct servent *se;
7440fd44 1675 se = p_getservbyname(service, NULL);
68a49acb 1676 if (se != NULL)
7440fd44 1677 return p_ntohs(se->s_port);
68a49acb 1678 else
1679 return 0;
1680}
fc0f17db 1681
42547ed9 1682char *get_hostname(void)
1683{
1684 int len = 128;
1685 char *hostname = NULL;
1686 do {
1687 len *= 2;
1688 hostname = sresize(hostname, len, char);
1689 if (p_gethostname(hostname, len) < 0) {
1690 sfree(hostname);
1691 hostname = NULL;
1692 break;
1693 }
1694 } while (strlen(hostname) >= len-1);
1695 return hostname;
1696}
1697
48806a46 1698SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
1699 char **canonicalname)
fc0f17db 1700{
1701 SockAddr ret = snew(struct SockAddr_tag);
1702 memset(ret, 0, sizeof(struct SockAddr_tag));
1703 ret->error = "unix sockets not supported on this platform";
5025a993 1704 ret->refcount = 1;
fc0f17db 1705 return ret;
1706}