]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - winnet.c
Bah. Add winspool.lib to libraries list. Maybe _now_ the nightly
[PuTTY.git] / winnet.c
1 /*
2  * Windows networking abstraction.
3  *
4  * Due to this clean abstraction it was possible
5  * to easily implement IPv6 support :)
6  *
7  * IPv6 patch 1 (27 October 2000) Jeroen Massar <jeroen@unfix.org>
8  *  - Preliminary hacked IPv6 support.
9  *    - Connecting to IPv6 address (eg fec0:4242:4242:100:2d0:b7ff:fe8f:5d42) works.
10  *    - Connecting to IPv6 hostname (eg heaven.ipv6.unfix.org) works.
11  *  - Compiles as either IPv4 or IPv6.
12  *
13  * IPv6 patch 2 (29 October 2000) Jeroen Massar <jeroen@unfix.org>
14  *  - When compiled as IPv6 it also allows connecting to IPv4 hosts.
15  *  - Added some more documentation.
16  *
17  * IPv6 patch 3 (18 November 2000) Jeroen Massar <jeroen@unfix.org>
18  *  - It now supports dynamically loading the IPv6 resolver dll's.
19  *    This way we should be able to distribute one (1) binary
20  *    which supports both IPv4 and IPv6.
21  *  - getaddrinfo() and getnameinfo() are loaded dynamicaly if possible.
22  *  - in6addr_any is defined in this file so we don't need to link to wship6.lib
23  *  - The patch is now more unified so that we can still
24  *    remove all IPv6 support by undef'ing IPV6.
25  *    But where it fallsback to IPv4 it uses the IPv4 code which is already in place...
26  *  - Canonical name resolving works.
27  *
28  * IPv6 patch 4 (07 January 2001) Jeroen Massar <jeroen@unfix.org>
29  *  - patch against CVS of today, will be submitted to the bugs list
30  *    as a 'cvs diff -u' on Simon's request...
31  *
32  */
33
34 /*
35  * Define IPV6 to have IPv6 on-the-fly-loading support.
36  * This means that one doesn't have to have an IPv6 stack to use it.
37  * But if an IPv6 stack is found it is used with a fallback to IPv4.
38  */
39 /* #define IPV6 1 */
40
41 #ifdef IPV6
42 #include <winsock2.h>
43 #include <ws2tcpip.h>
44 #include <tpipv6.h>
45 #else
46 #include <winsock.h>
47 #endif
48 #include <windows.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <assert.h>
52
53 #define DEFINE_PLUG_METHOD_MACROS
54 #include "putty.h"
55 #include "network.h"
56 #include "tree234.h"
57
58 struct Socket_tag {
59     struct socket_function_table *fn;
60     /* the above variable absolutely *must* be the first in this structure */
61     char *error;
62     SOCKET s;
63     Plug plug;
64     void *private_ptr;
65     bufchain output_data;
66     int connected;
67     int writable;
68     int frozen; /* this causes readability notifications to be ignored */
69     int frozen_readable; /* this means we missed at least one readability
70                           * notification while we were frozen */
71     int localhost_only;                /* for listening sockets */
72     char oobdata[1];
73     int sending_oob;
74     int oobinline;
75     int pending_error;                 /* in case send() returns error */
76 };
77
78 /*
79  * We used to typedef struct Socket_tag *Socket.
80  *
81  * Since we have made the networking abstraction slightly more
82  * abstract, Socket no longer means a tcp socket (it could mean
83  * an ssl socket).  So now we must use Actual_Socket when we know
84  * we are talking about a tcp socket.
85  */
86 typedef struct Socket_tag *Actual_Socket;
87
88 struct SockAddr_tag {
89     char *error;
90     /* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */
91     int family;
92     unsigned long address;             /* Address IPv4 style. */
93 #ifdef IPV6
94     struct addrinfo *ai;               /* Address IPv6 style. */
95 #endif
96 };
97
98 static tree234 *sktree;
99
100 static int cmpfortree(void *av, void *bv)
101 {
102     Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
103     unsigned long as = (unsigned long) a->s, bs = (unsigned long) b->s;
104     if (as < bs)
105         return -1;
106     if (as > bs)
107         return +1;
108     return 0;
109 }
110
111 static int cmpforsearch(void *av, void *bv)
112 {
113     Actual_Socket b = (Actual_Socket) bv;
114     unsigned long as = (unsigned long) av, bs = (unsigned long) b->s;
115     if (as < bs)
116         return -1;
117     if (as > bs)
118         return +1;
119     return 0;
120 }
121
122 void sk_init(void)
123 {
124     sktree = newtree234(cmpfortree);
125 }
126
127 void sk_cleanup(void)
128 {
129     Actual_Socket s;
130     int i;
131
132     if (sktree) {
133         for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
134             closesocket(s->s);
135         }
136     }
137 }
138
139 char *winsock_error_string(int error)
140 {
141     switch (error) {
142       case WSAEACCES:
143         return "Network error: Permission denied";
144       case WSAEADDRINUSE:
145         return "Network error: Address already in use";
146       case WSAEADDRNOTAVAIL:
147         return "Network error: Cannot assign requested address";
148       case WSAEAFNOSUPPORT:
149         return
150             "Network error: Address family not supported by protocol family";
151       case WSAEALREADY:
152         return "Network error: Operation already in progress";
153       case WSAECONNABORTED:
154         return "Network error: Software caused connection abort";
155       case WSAECONNREFUSED:
156         return "Network error: Connection refused";
157       case WSAECONNRESET:
158         return "Network error: Connection reset by peer";
159       case WSAEDESTADDRREQ:
160         return "Network error: Destination address required";
161       case WSAEFAULT:
162         return "Network error: Bad address";
163       case WSAEHOSTDOWN:
164         return "Network error: Host is down";
165       case WSAEHOSTUNREACH:
166         return "Network error: No route to host";
167       case WSAEINPROGRESS:
168         return "Network error: Operation now in progress";
169       case WSAEINTR:
170         return "Network error: Interrupted function call";
171       case WSAEINVAL:
172         return "Network error: Invalid argument";
173       case WSAEISCONN:
174         return "Network error: Socket is already connected";
175       case WSAEMFILE:
176         return "Network error: Too many open files";
177       case WSAEMSGSIZE:
178         return "Network error: Message too long";
179       case WSAENETDOWN:
180         return "Network error: Network is down";
181       case WSAENETRESET:
182         return "Network error: Network dropped connection on reset";
183       case WSAENETUNREACH:
184         return "Network error: Network is unreachable";
185       case WSAENOBUFS:
186         return "Network error: No buffer space available";
187       case WSAENOPROTOOPT:
188         return "Network error: Bad protocol option";
189       case WSAENOTCONN:
190         return "Network error: Socket is not connected";
191       case WSAENOTSOCK:
192         return "Network error: Socket operation on non-socket";
193       case WSAEOPNOTSUPP:
194         return "Network error: Operation not supported";
195       case WSAEPFNOSUPPORT:
196         return "Network error: Protocol family not supported";
197       case WSAEPROCLIM:
198         return "Network error: Too many processes";
199       case WSAEPROTONOSUPPORT:
200         return "Network error: Protocol not supported";
201       case WSAEPROTOTYPE:
202         return "Network error: Protocol wrong type for socket";
203       case WSAESHUTDOWN:
204         return "Network error: Cannot send after socket shutdown";
205       case WSAESOCKTNOSUPPORT:
206         return "Network error: Socket type not supported";
207       case WSAETIMEDOUT:
208         return "Network error: Connection timed out";
209       case WSAEWOULDBLOCK:
210         return "Network error: Resource temporarily unavailable";
211       case WSAEDISCON:
212         return "Network error: Graceful shutdown in progress";
213       default:
214         return "Unknown network error";
215     }
216 }
217
218 SockAddr sk_namelookup(char *host, char **canonicalname)
219 {
220     SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
221     unsigned long a;
222     struct hostent *h = NULL;
223     char realhost[8192];
224
225     /* Clear the structure and default to IPv4. */
226     memset(ret, 0, sizeof(struct SockAddr_tag));
227     ret->family = 0;                   /* We set this one when we have resolved the host. */
228     *realhost = '\0';
229
230     if ((a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
231 #ifdef IPV6
232
233         /* Try to get the getaddrinfo() function from wship6.dll */
234         /* This way one doesn't need to have IPv6 dll's to use PuTTY and
235          * it will fallback to IPv4. */
236         typedef int (CALLBACK * FGETADDRINFO) (const char *nodename,
237                                                const char *servname,
238                                                const struct addrinfo *
239                                                hints,
240                                                struct addrinfo ** res);
241         FGETADDRINFO fGetAddrInfo = NULL;
242
243         HINSTANCE dllWSHIP6 = LoadLibrary("wship6.dll");
244         if (dllWSHIP6)
245             fGetAddrInfo = (FGETADDRINFO) GetProcAddress(dllWSHIP6,
246                                                          "getaddrinfo");
247
248         /*
249          * Use fGetAddrInfo when it's available (which usually also
250          * means IPv6 is installed...)
251          */
252         if (fGetAddrInfo) {
253             /*debug(("Resolving \"%s\" with getaddrinfo()  (IPv4+IPv6 capable)...\n", host)); */
254             if (fGetAddrInfo(host, NULL, NULL, &ret->ai) == 0)
255                 ret->family = ret->ai->ai_family;
256         } else
257 #endif
258         {
259             /*
260              * Otherwise use the IPv4-only gethostbyname...
261              * (NOTE: we don't use gethostbyname as a
262              * fallback!)
263              */
264             if (ret->family == 0) {
265                 /*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */
266                 if ( (h = gethostbyname(host)) )
267                     ret->family = AF_INET;
268             }
269         }
270         /*debug(("Done resolving...(family is %d) AF_INET = %d, AF_INET6 = %d\n", ret->family, AF_INET, AF_INET6)); */
271
272         if (ret->family == 0) {
273             DWORD err = WSAGetLastError();
274             ret->error = (err == WSAENETDOWN ? "Network is down" :
275                           err ==
276                           WSAHOST_NOT_FOUND ? "Host does not exist" : err
277                           == WSATRY_AGAIN ? "Host not found" :
278 #ifdef IPV6
279                           fGetAddrInfo ? "getaddrinfo: unknown error" :
280 #endif
281                           "gethostbyname: unknown error");
282 #ifdef DEBUG
283             {
284                 LPVOID lpMsgBuf;
285                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
286                               FORMAT_MESSAGE_FROM_SYSTEM |
287                               FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
288                               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
289                               (LPTSTR) & lpMsgBuf, 0, NULL);
290                 /*debug(("Error %ld: %s (h=%lx)\n", err, lpMsgBuf, h)); */
291                 /* Free the buffer. */
292                 LocalFree(lpMsgBuf);
293             }
294 #endif
295         } else {
296             ret->error = NULL;
297
298 #ifdef IPV6
299             /* If we got an address info use that... */
300             if (ret->ai) {
301                 typedef int (CALLBACK * FGETNAMEINFO)
302                  (const struct sockaddr FAR * sa, socklen_t salen,
303                   char FAR * host, size_t hostlen, char FAR * serv,
304                   size_t servlen, int flags);
305                 FGETNAMEINFO fGetNameInfo = NULL;
306
307                 /* Are we in IPv4 fallback mode? */
308                 /* We put the IPv4 address into the a variable so we can further-on use the IPv4 code... */
309                 if (ret->family == AF_INET)
310                     memcpy(&a,
311                            (char *) &((SOCKADDR_IN *) ret->ai->
312                                       ai_addr)->sin_addr, sizeof(a));
313
314                 /* Now let's find that canonicalname... */
315                 if ((dllWSHIP6)
316                     && (fGetNameInfo =
317                         (FGETNAMEINFO) GetProcAddress(dllWSHIP6,
318                                                       "getnameinfo"))) {
319                     if (fGetNameInfo
320                         ((struct sockaddr *) ret->ai->ai_addr,
321                          ret->family ==
322                          AF_INET ? sizeof(SOCKADDR_IN) :
323                          sizeof(SOCKADDR_IN6), realhost,
324                          sizeof(realhost), NULL, 0, 0) != 0) {
325                         strncpy(realhost, host, sizeof(realhost));
326                     }
327                 }
328             }
329             /* We used the IPv4-only gethostbyname()... */
330             else
331 #endif
332             {
333                 memcpy(&a, h->h_addr, sizeof(a));
334                 /* This way we are always sure the h->h_name is valid :) */
335                 strncpy(realhost, h->h_name, sizeof(realhost));
336             }
337         }
338 #ifdef IPV6
339         FreeLibrary(dllWSHIP6);
340 #endif
341     } else {
342         /*
343          * This must be a numeric IPv4 address because it caused a
344          * success return from inet_addr.
345          */
346         ret->family = AF_INET;
347         strncpy(realhost, host, sizeof(realhost));
348     }
349     ret->address = ntohl(a);
350     realhost[lenof(realhost)-1] = '\0';
351     *canonicalname = smalloc(1+strlen(realhost));
352     strcpy(*canonicalname, realhost);
353     return ret;
354 }
355
356 void sk_getaddr(SockAddr addr, char *buf, int buflen)
357 {
358 #ifdef IPV6
359     if (addr->family == AF_INET) {
360 #endif
361         struct in_addr a;
362         a.s_addr = htonl(addr->address);
363         strncpy(buf, inet_ntoa(a), buflen);
364 #ifdef IPV6
365     } else {
366         FIXME; /* I don't know how to get a text form of an IPv6 address. */
367     }
368 #endif
369 }
370
371 void sk_addr_free(SockAddr addr)
372 {
373     sfree(addr);
374 }
375
376 static Plug sk_tcp_plug(Socket sock, Plug p)
377 {
378     Actual_Socket s = (Actual_Socket) sock;
379     Plug ret = s->plug;
380     if (p)
381         s->plug = p;
382     return ret;
383 }
384
385 static void sk_tcp_flush(Socket s)
386 {
387     /*
388      * We send data to the socket as soon as we can anyway,
389      * so we don't need to do anything here.  :-)
390      */
391 }
392
393 static void sk_tcp_close(Socket s);
394 static int sk_tcp_write(Socket s, char *data, int len);
395 static int sk_tcp_write_oob(Socket s, char *data, int len);
396 static char *sk_tcp_socket_error(Socket s);
397
398 extern char *do_select(SOCKET skt, int startup);
399
400 Socket sk_register(void *sock, Plug plug)
401 {
402     static struct socket_function_table fn_table = {
403         sk_tcp_plug,
404         sk_tcp_close,
405         sk_tcp_write,
406         sk_tcp_write_oob,
407         sk_tcp_flush,
408         sk_tcp_socket_error
409     };
410
411     DWORD err;
412     char *errstr;
413     Actual_Socket ret;
414
415     /*
416      * Create Socket structure.
417      */
418     ret = smalloc(sizeof(struct Socket_tag));
419     ret->fn = &fn_table;
420     ret->error = NULL;
421     ret->plug = plug;
422     bufchain_init(&ret->output_data);
423     ret->writable = 1;                 /* to start with */
424     ret->sending_oob = 0;
425     ret->frozen = 1;
426     ret->frozen_readable = 0;
427     ret->localhost_only = 0;           /* unused, but best init anyway */
428     ret->pending_error = 0;
429
430     ret->s = (SOCKET)sock;
431
432     if (ret->s == INVALID_SOCKET) {
433         err = WSAGetLastError();
434         ret->error = winsock_error_string(err);
435         return (Socket) ret;
436     }
437
438     ret->oobinline = 0;
439
440     /* Set up a select mechanism. This could be an AsyncSelect on a
441      * window, or an EventSelect on an event object. */
442     errstr = do_select(ret->s, 1);
443     if (errstr) {
444         ret->error = errstr;
445         return (Socket) ret;
446     }
447
448     add234(sktree, ret);
449
450     return (Socket) ret;
451 }
452
453 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
454               int nodelay, Plug plug)
455 {
456     static struct socket_function_table fn_table = {
457         sk_tcp_plug,
458         sk_tcp_close,
459         sk_tcp_write,
460         sk_tcp_write_oob,
461         sk_tcp_flush,
462         sk_tcp_socket_error
463     };
464
465     SOCKET s;
466 #ifdef IPV6
467     SOCKADDR_IN6 a6;
468 #endif
469     SOCKADDR_IN a;
470     DWORD err;
471     char *errstr;
472     Actual_Socket ret;
473     short localport;
474
475     /*
476      * Create Socket structure.
477      */
478     ret = smalloc(sizeof(struct Socket_tag));
479     ret->fn = &fn_table;
480     ret->error = NULL;
481     ret->plug = plug;
482     bufchain_init(&ret->output_data);
483     ret->connected = 0;                /* to start with */
484     ret->writable = 0;                 /* to start with */
485     ret->sending_oob = 0;
486     ret->frozen = 0;
487     ret->frozen_readable = 0;
488     ret->localhost_only = 0;           /* unused, but best init anyway */
489     ret->pending_error = 0;
490
491     /*
492      * Open socket.
493      */
494     s = socket(addr->family, SOCK_STREAM, 0);
495     ret->s = s;
496
497     if (s == INVALID_SOCKET) {
498         err = WSAGetLastError();
499         ret->error = winsock_error_string(err);
500         return (Socket) ret;
501     }
502
503     ret->oobinline = oobinline;
504     if (oobinline) {
505         BOOL b = TRUE;
506         setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
507     }
508
509     if (nodelay) {
510         BOOL b = TRUE;
511         setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
512     }
513
514     /*
515      * Bind to local address.
516      */
517     if (privport)
518         localport = 1023;              /* count from 1023 downwards */
519     else
520         localport = 0;                 /* just use port 0 (ie winsock picks) */
521
522     /* Loop round trying to bind */
523     while (1) {
524         int retcode;
525
526 #ifdef IPV6
527         if (addr->family == AF_INET6) {
528             memset(&a6, 0, sizeof(a6));
529             a6.sin6_family = AF_INET6;
530 /*a6.sin6_addr      = in6addr_any; *//* == 0 */
531             a6.sin6_port = htons(localport);
532         } else
533 #endif
534         {
535             a.sin_family = AF_INET;
536             a.sin_addr.s_addr = htonl(INADDR_ANY);
537             a.sin_port = htons(localport);
538         }
539 #ifdef IPV6
540         retcode = bind(s, (addr->family == AF_INET6 ?
541                            (struct sockaddr *) &a6 :
542                            (struct sockaddr *) &a),
543                        (addr->family ==
544                         AF_INET6 ? sizeof(a6) : sizeof(a)));
545 #else
546         retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
547 #endif
548         if (retcode != SOCKET_ERROR) {
549             err = 0;
550             break;                     /* done */
551         } else {
552             err = WSAGetLastError();
553             if (err != WSAEADDRINUSE)  /* failed, for a bad reason */
554                 break;
555         }
556
557         if (localport == 0)
558             break;                     /* we're only looping once */
559         localport--;
560         if (localport == 0)
561             break;                     /* we might have got to the end */
562     }
563
564     if (err) {
565         ret->error = winsock_error_string(err);
566         return (Socket) ret;
567     }
568
569     /*
570      * Connect to remote address.
571      */
572 #ifdef IPV6
573     if (addr->family == AF_INET6) {
574         memset(&a, 0, sizeof(a));
575         a6.sin6_family = AF_INET6;
576         a6.sin6_port = htons((short) port);
577         a6.sin6_addr =
578             ((struct sockaddr_in6 *) addr->ai->ai_addr)->sin6_addr;
579     } else
580 #endif
581     {
582         a.sin_family = AF_INET;
583         a.sin_addr.s_addr = htonl(addr->address);
584         a.sin_port = htons((short) port);
585     }
586
587     /* Set up a select mechanism. This could be an AsyncSelect on a
588      * window, or an EventSelect on an event object. */
589     errstr = do_select(s, 1);
590     if (errstr) {
591         ret->error = errstr;
592         return (Socket) ret;
593     }
594
595     if ((
596 #ifdef IPV6
597             connect(s, ((addr->family == AF_INET6) ?
598                         (struct sockaddr *) &a6 : (struct sockaddr *) &a),
599                     (addr->family == AF_INET6) ? sizeof(a6) : sizeof(a))
600 #else
601             connect(s, (struct sockaddr *) &a, sizeof(a))
602 #endif
603         ) == SOCKET_ERROR) {
604         err = WSAGetLastError();
605         /*
606          * We expect a potential EWOULDBLOCK here, because the
607          * chances are the front end has done a select for
608          * FD_CONNECT, so that connect() will complete
609          * asynchronously.
610          */
611         if ( err != WSAEWOULDBLOCK ) {
612             ret->error = winsock_error_string(err);
613             return (Socket) ret;
614         }
615     } else {
616         /*
617          * If we _don't_ get EWOULDBLOCK, the connect has completed
618          * and we should set the socket as writable.
619          */
620         ret->writable = 1;
621     }
622
623     add234(sktree, ret);
624
625     return (Socket) ret;
626 }
627
628 Socket sk_newlistener(int port, Plug plug, int local_host_only)
629 {
630     static struct socket_function_table fn_table = {
631         sk_tcp_plug,
632         sk_tcp_close,
633         sk_tcp_write,
634         sk_tcp_write_oob,
635         sk_tcp_flush,
636         sk_tcp_socket_error
637     };
638
639     SOCKET s;
640 #ifdef IPV6
641     SOCKADDR_IN6 a6;
642 #endif
643     SOCKADDR_IN a;
644     DWORD err;
645     char *errstr;
646     Actual_Socket ret;
647     int retcode;
648     int on = 1;
649
650     /*
651      * Create Socket structure.
652      */
653     ret = smalloc(sizeof(struct Socket_tag));
654     ret->fn = &fn_table;
655     ret->error = NULL;
656     ret->plug = plug;
657     bufchain_init(&ret->output_data);
658     ret->writable = 0;                 /* to start with */
659     ret->sending_oob = 0;
660     ret->frozen = 0;
661     ret->frozen_readable = 0;
662     ret->localhost_only = local_host_only;
663     ret->pending_error = 0;
664
665     /*
666      * Open socket.
667      */
668     s = socket(AF_INET, SOCK_STREAM, 0);
669     ret->s = s;
670
671     if (s == INVALID_SOCKET) {
672         err = WSAGetLastError();
673         ret->error = winsock_error_string(err);
674         return (Socket) ret;
675     }
676
677     ret->oobinline = 0;
678
679
680     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
681
682
683 #ifdef IPV6
684         if (addr->family == AF_INET6) {
685             memset(&a6, 0, sizeof(a6));
686             a6.sin6_family = AF_INET6;
687             if (local_host_only)
688                 a6.sin6_addr = in6addr_loopback;
689             else
690                 a6.sin6_addr = in6addr_any;
691             a6.sin6_port = htons(port);
692         } else
693 #endif
694         {
695             a.sin_family = AF_INET;
696             if (local_host_only)
697                 a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
698             else
699                 a.sin_addr.s_addr = htonl(INADDR_ANY);
700             a.sin_port = htons((short)port);
701         }
702 #ifdef IPV6
703         retcode = bind(s, (addr->family == AF_INET6 ?
704                            (struct sockaddr *) &a6 :
705                            (struct sockaddr *) &a),
706                        (addr->family ==
707                         AF_INET6 ? sizeof(a6) : sizeof(a)));
708 #else
709         retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
710 #endif
711         if (retcode != SOCKET_ERROR) {
712             err = 0;
713         } else {
714             err = WSAGetLastError();
715         }
716
717     if (err) {
718         ret->error = winsock_error_string(err);
719         return (Socket) ret;
720     }
721
722
723     if (listen(s, SOMAXCONN) == SOCKET_ERROR) {
724         closesocket(s);
725         ret->error = winsock_error_string(err);
726         return (Socket) ret;
727     }
728
729     /* Set up a select mechanism. This could be an AsyncSelect on a
730      * window, or an EventSelect on an event object. */
731     errstr = do_select(s, 1);
732     if (errstr) {
733         ret->error = errstr;
734         return (Socket) ret;
735     }
736
737     add234(sktree, ret);
738
739     return (Socket) ret;
740 }
741
742 static void sk_tcp_close(Socket sock)
743 {
744     extern char *do_select(SOCKET skt, int startup);
745     Actual_Socket s = (Actual_Socket) sock;
746
747     del234(sktree, s);
748     do_select(s->s, 0);
749     closesocket(s->s);
750     sfree(s);
751 }
752
753 /*
754  * The function which tries to send on a socket once it's deemed
755  * writable.
756  */
757 void try_send(Actual_Socket s)
758 {
759     while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
760         int nsent;
761         DWORD err;
762         void *data;
763         int len, urgentflag;
764
765         if (s->sending_oob) {
766             urgentflag = MSG_OOB;
767             len = s->sending_oob;
768             data = &s->oobdata;
769         } else {
770             urgentflag = 0;
771             bufchain_prefix(&s->output_data, &data, &len);
772         }
773         nsent = send(s->s, data, len, urgentflag);
774         noise_ultralight(nsent);
775         if (nsent <= 0) {
776             err = (nsent < 0 ? WSAGetLastError() : 0);
777             if ((err < WSABASEERR && nsent < 0) || err == WSAEWOULDBLOCK) {
778                 /*
779                  * Perfectly normal: we've sent all we can for the moment.
780                  * 
781                  * (Some WinSock send() implementations can return
782                  * <0 but leave no sensible error indication -
783                  * WSAGetLastError() is called but returns zero or
784                  * a small number - so we check that case and treat
785                  * it just like WSAEWOULDBLOCK.)
786                  */
787                 s->writable = FALSE;
788                 return;
789             } else if (nsent == 0 ||
790                        err == WSAECONNABORTED || err == WSAECONNRESET) {
791                 /*
792                  * If send() returns CONNABORTED or CONNRESET, we
793                  * unfortunately can't just call plug_closing(),
794                  * because it's quite likely that we're currently
795                  * _in_ a call from the code we'd be calling back
796                  * to, so we'd have to make half the SSH code
797                  * reentrant. Instead we flag a pending error on
798                  * the socket, to be dealt with (by calling
799                  * plug_closing()) at some suitable future moment.
800                  */
801                 s->pending_error = err;
802                 return;
803             } else {
804                 fatalbox(winsock_error_string(err));
805             }
806         } else {
807             if (s->sending_oob) {
808                 if (nsent < len) {
809                     memmove(s->oobdata, s->oobdata+nsent, len-nsent);
810                     s->sending_oob = len - nsent;
811                 } else {
812                     s->sending_oob = 0;
813                 }
814             } else {
815                 bufchain_consume(&s->output_data, nsent);
816             }
817         }
818     }
819 }
820
821 static int sk_tcp_write(Socket sock, char *buf, int len)
822 {
823     Actual_Socket s = (Actual_Socket) sock;
824
825     /*
826      * Add the data to the buffer list on the socket.
827      */
828     bufchain_add(&s->output_data, buf, len);
829
830     /*
831      * Now try sending from the start of the buffer list.
832      */
833     if (s->writable)
834         try_send(s);
835
836     return bufchain_size(&s->output_data);
837 }
838
839 static int sk_tcp_write_oob(Socket sock, char *buf, int len)
840 {
841     Actual_Socket s = (Actual_Socket) sock;
842
843     /*
844      * Replace the buffer list on the socket with the data.
845      */
846     bufchain_clear(&s->output_data);
847     assert(len <= sizeof(s->oobdata));
848     memcpy(s->oobdata, buf, len);
849     s->sending_oob = len;
850
851     /*
852      * Now try sending from the start of the buffer list.
853      */
854     if (s->writable)
855         try_send(s);
856
857     return s->sending_oob;
858 }
859
860 int select_result(WPARAM wParam, LPARAM lParam)
861 {
862     int ret, open;
863     DWORD err;
864     char buf[20480];                   /* nice big buffer for plenty of speed */
865     Actual_Socket s;
866     u_long atmark;
867
868     /* wParam is the socket itself */
869     s = find234(sktree, (void *) wParam, cmpforsearch);
870     if (!s)
871         return 1;                      /* boggle */
872
873     if ((err = WSAGETSELECTERROR(lParam)) != 0) {
874         /*
875          * An error has occurred on this socket. Pass it to the
876          * plug.
877          */
878         return plug_closing(s->plug, winsock_error_string(err), err, 0);
879     }
880
881     noise_ultralight(lParam);
882
883     switch (WSAGETSELECTEVENT(lParam)) {
884       case FD_CONNECT:
885         s->connected = s->writable = 1;
886         break;
887       case FD_READ:
888         /* In the case the socket is still frozen, we don't even bother */
889         if (s->frozen) {
890             s->frozen_readable = 1;
891             break;
892         }
893
894         /*
895          * We have received data on the socket. For an oobinline
896          * socket, this might be data _before_ an urgent pointer,
897          * in which case we send it to the back end with type==1
898          * (data prior to urgent).
899          */
900         if (s->oobinline) {
901             atmark = 1;
902             ioctlsocket(s->s, SIOCATMARK, &atmark);
903             /*
904              * Avoid checking the return value from ioctlsocket(),
905              * on the grounds that some WinSock wrappers don't
906              * support it. If it does nothing, we get atmark==1,
907              * which is equivalent to `no OOB pending', so the
908              * effect will be to non-OOB-ify any OOB data.
909              */
910         } else
911             atmark = 1;
912
913         ret = recv(s->s, buf, sizeof(buf), 0);
914         noise_ultralight(ret);
915         if (ret < 0) {
916             err = WSAGetLastError();
917             if (err == WSAEWOULDBLOCK) {
918                 break;
919             }
920         }
921         if (ret < 0) {
922             return plug_closing(s->plug, winsock_error_string(err), err,
923                                 0);
924         } else if (0 == ret) {
925             return plug_closing(s->plug, NULL, 0, 0);
926         } else {
927             return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
928         }
929         break;
930       case FD_OOB:
931         /*
932          * This will only happen on a non-oobinline socket. It
933          * indicates that we can immediately perform an OOB read
934          * and get back OOB data, which we will send to the back
935          * end with type==2 (urgent data).
936          */
937         ret = recv(s->s, buf, sizeof(buf), MSG_OOB);
938         noise_ultralight(ret);
939         if (ret <= 0) {
940             fatalbox(ret == 0 ? "Internal networking trouble" :
941                      winsock_error_string(WSAGetLastError()));
942         } else {
943             return plug_receive(s->plug, 2, buf, ret);
944         }
945         break;
946       case FD_WRITE:
947         {
948             int bufsize_before, bufsize_after;
949             s->writable = 1;
950             bufsize_before = s->sending_oob + bufchain_size(&s->output_data);
951             try_send(s);
952             bufsize_after = s->sending_oob + bufchain_size(&s->output_data);
953             if (bufsize_after < bufsize_before)
954                 plug_sent(s->plug, bufsize_after);
955         }
956         break;
957       case FD_CLOSE:
958         /* Signal a close on the socket. First read any outstanding data. */
959         open = 1;
960         do {
961             ret = recv(s->s, buf, sizeof(buf), 0);
962             if (ret < 0) {
963                 err = WSAGetLastError();
964                 if (err == WSAEWOULDBLOCK)
965                     break;
966                 return plug_closing(s->plug, winsock_error_string(err),
967                                     err, 0);
968             } else {
969                 if (ret)
970                     open &= plug_receive(s->plug, 0, buf, ret);
971                 else
972                     open &= plug_closing(s->plug, NULL, 0, 0);
973             }
974         } while (ret > 0);
975         return open;
976        case FD_ACCEPT:
977         {
978             struct sockaddr_in isa;
979             int addrlen = sizeof(struct sockaddr_in);
980             SOCKET t;  /* socket of connection */
981
982             memset(&isa, 0, sizeof(struct sockaddr_in));
983             err = 0;
984             t = accept(s->s,(struct sockaddr *)&isa,&addrlen);
985             if (t == INVALID_SOCKET)
986             {
987                 err = WSAGetLastError();
988                 if (err == WSATRY_AGAIN)
989                     break;
990             }
991
992             if (s->localhost_only &&
993                 ntohl(isa.sin_addr.s_addr) != INADDR_LOOPBACK) {
994                 closesocket(t);        /* dodgy WinSock let nonlocal through */
995             } else if (plug_accepting(s->plug, (void*)t)) {
996                 closesocket(t);        /* denied or error */
997             }
998         }
999     }
1000
1001     return 1;
1002 }
1003
1004 /*
1005  * Deal with socket errors detected in try_send().
1006  */
1007 void net_pending_errors(void)
1008 {
1009     int i;
1010     Actual_Socket s;
1011
1012     /*
1013      * This might be a fiddly business, because it's just possible
1014      * that handling a pending error on one socket might cause
1015      * others to be closed. (I can't think of any reason this might
1016      * happen in current SSH implementation, but to maintain
1017      * generality of this network layer I'll assume the worst.)
1018      * 
1019      * So what we'll do is search the socket list for _one_ socket
1020      * with a pending error, and then handle it, and then search
1021      * the list again _from the beginning_. Repeat until we make a
1022      * pass with no socket errors present. That way we are
1023      * protected against the socket list changing under our feet.
1024      */
1025
1026     do {
1027         for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
1028             if (s->pending_error) {
1029                 /*
1030                  * An error has occurred on this socket. Pass it to the
1031                  * plug.
1032                  */
1033                 plug_closing(s->plug,
1034                              winsock_error_string(s->pending_error),
1035                              s->pending_error, 0);
1036                 break;
1037             }
1038         }
1039     } while (s);
1040 }
1041
1042 /*
1043  * Each socket abstraction contains a `void *' private field in
1044  * which the client can keep state.
1045  */
1046 void sk_set_private_ptr(Socket sock, void *ptr)
1047 {
1048     Actual_Socket s = (Actual_Socket) sock;
1049     s->private_ptr = ptr;
1050 }
1051
1052 void *sk_get_private_ptr(Socket sock)
1053 {
1054     Actual_Socket s = (Actual_Socket) sock;
1055     return s->private_ptr;
1056 }
1057
1058 /*
1059  * Special error values are returned from sk_namelookup and sk_new
1060  * if there's a problem. These functions extract an error message,
1061  * or return NULL if there's no problem.
1062  */
1063 char *sk_addr_error(SockAddr addr)
1064 {
1065     return addr->error;
1066 }
1067 static char *sk_tcp_socket_error(Socket sock)
1068 {
1069     Actual_Socket s = (Actual_Socket) sock;
1070     return s->error;
1071 }
1072
1073 void sk_set_frozen(Socket sock, int is_frozen)
1074 {
1075     Actual_Socket s = (Actual_Socket) sock;
1076     if (s->frozen == is_frozen)
1077         return;
1078     s->frozen = is_frozen;
1079     if (!is_frozen && s->frozen_readable) {
1080         char c;
1081         recv(s->s, &c, 1, MSG_PEEK);
1082     }
1083     s->frozen_readable = 0;
1084 }
1085
1086 /*
1087  * For Plink: enumerate all sockets currently active.
1088  */
1089 SOCKET first_socket(int *state)
1090 {
1091     Actual_Socket s;
1092     *state = 0;
1093     s = index234(sktree, (*state)++);
1094     return s ? s->s : INVALID_SOCKET;
1095 }
1096
1097 SOCKET next_socket(int *state)
1098 {
1099     Actual_Socket s = index234(sktree, (*state)++);
1100     return s ? s->s : INVALID_SOCKET;
1101 }