]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - winnet.c
Move MODULE files out of individual project directories into a
[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 int sk_addrtype(SockAddr addr)
372 {
373     return addr->family;
374 }
375
376 void sk_addrcopy(SockAddr addr, char *buf)
377 {
378 #ifdef IPV6
379     if (addr->family == AF_INET) {
380 #endif
381         struct in_addr a;
382         a.s_addr = htonl(addr->address);
383         memcpy(buf, (char*) &a.s_addr, 4);
384 #ifdef IPV6
385     } else {
386         memcpy(buf, (char*) addr->ai, 16);
387     }
388 #endif
389 }
390
391 void sk_addr_free(SockAddr addr)
392 {
393     sfree(addr);
394 }
395
396 static Plug sk_tcp_plug(Socket sock, Plug p)
397 {
398     Actual_Socket s = (Actual_Socket) sock;
399     Plug ret = s->plug;
400     if (p)
401         s->plug = p;
402     return ret;
403 }
404
405 static void sk_tcp_flush(Socket s)
406 {
407     /*
408      * We send data to the socket as soon as we can anyway,
409      * so we don't need to do anything here.  :-)
410      */
411 }
412
413 static void sk_tcp_close(Socket s);
414 static int sk_tcp_write(Socket s, char *data, int len);
415 static int sk_tcp_write_oob(Socket s, char *data, int len);
416 static void sk_tcp_set_private_ptr(Socket s, void *ptr);
417 static void *sk_tcp_get_private_ptr(Socket s);
418 static void sk_tcp_set_frozen(Socket s, int is_frozen);
419 static char *sk_tcp_socket_error(Socket s);
420
421 extern char *do_select(SOCKET skt, int startup);
422
423 Socket sk_register(void *sock, Plug plug)
424 {
425     static struct socket_function_table fn_table = {
426         sk_tcp_plug,
427         sk_tcp_close,
428         sk_tcp_write,
429         sk_tcp_write_oob,
430         sk_tcp_flush,
431         sk_tcp_set_private_ptr,
432         sk_tcp_get_private_ptr,
433         sk_tcp_set_frozen,
434         sk_tcp_socket_error
435     };
436
437     DWORD err;
438     char *errstr;
439     Actual_Socket ret;
440
441     /*
442      * Create Socket structure.
443      */
444     ret = smalloc(sizeof(struct Socket_tag));
445     ret->fn = &fn_table;
446     ret->error = NULL;
447     ret->plug = plug;
448     bufchain_init(&ret->output_data);
449     ret->writable = 1;                 /* to start with */
450     ret->sending_oob = 0;
451     ret->frozen = 1;
452     ret->frozen_readable = 0;
453     ret->localhost_only = 0;           /* unused, but best init anyway */
454     ret->pending_error = 0;
455
456     ret->s = (SOCKET)sock;
457
458     if (ret->s == INVALID_SOCKET) {
459         err = WSAGetLastError();
460         ret->error = winsock_error_string(err);
461         return (Socket) ret;
462     }
463
464     ret->oobinline = 0;
465
466     /* Set up a select mechanism. This could be an AsyncSelect on a
467      * window, or an EventSelect on an event object. */
468     errstr = do_select(ret->s, 1);
469     if (errstr) {
470         ret->error = errstr;
471         return (Socket) ret;
472     }
473
474     add234(sktree, ret);
475
476     return (Socket) ret;
477 }
478
479 Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
480               int nodelay, Plug plug)
481 {
482     static struct socket_function_table fn_table = {
483         sk_tcp_plug,
484         sk_tcp_close,
485         sk_tcp_write,
486         sk_tcp_write_oob,
487         sk_tcp_flush,
488         sk_tcp_set_private_ptr,
489         sk_tcp_get_private_ptr,
490         sk_tcp_set_frozen,
491         sk_tcp_socket_error
492     };
493
494     SOCKET s;
495 #ifdef IPV6
496     SOCKADDR_IN6 a6;
497 #endif
498     SOCKADDR_IN a;
499     DWORD err;
500     char *errstr;
501     Actual_Socket ret;
502     short localport;
503
504     /*
505      * Create Socket structure.
506      */
507     ret = smalloc(sizeof(struct Socket_tag));
508     ret->fn = &fn_table;
509     ret->error = NULL;
510     ret->plug = plug;
511     bufchain_init(&ret->output_data);
512     ret->connected = 0;                /* to start with */
513     ret->writable = 0;                 /* to start with */
514     ret->sending_oob = 0;
515     ret->frozen = 0;
516     ret->frozen_readable = 0;
517     ret->localhost_only = 0;           /* unused, but best init anyway */
518     ret->pending_error = 0;
519
520     /*
521      * Open socket.
522      */
523     s = socket(addr->family, SOCK_STREAM, 0);
524     ret->s = s;
525
526     if (s == INVALID_SOCKET) {
527         err = WSAGetLastError();
528         ret->error = winsock_error_string(err);
529         return (Socket) ret;
530     }
531
532     ret->oobinline = oobinline;
533     if (oobinline) {
534         BOOL b = TRUE;
535         setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
536     }
537
538     if (nodelay) {
539         BOOL b = TRUE;
540         setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
541     }
542
543     /*
544      * Bind to local address.
545      */
546     if (privport)
547         localport = 1023;              /* count from 1023 downwards */
548     else
549         localport = 0;                 /* just use port 0 (ie winsock picks) */
550
551     /* Loop round trying to bind */
552     while (1) {
553         int retcode;
554
555 #ifdef IPV6
556         if (addr->family == AF_INET6) {
557             memset(&a6, 0, sizeof(a6));
558             a6.sin6_family = AF_INET6;
559 /*a6.sin6_addr      = in6addr_any; *//* == 0 */
560             a6.sin6_port = htons(localport);
561         } else
562 #endif
563         {
564             a.sin_family = AF_INET;
565             a.sin_addr.s_addr = htonl(INADDR_ANY);
566             a.sin_port = htons(localport);
567         }
568 #ifdef IPV6
569         retcode = bind(s, (addr->family == AF_INET6 ?
570                            (struct sockaddr *) &a6 :
571                            (struct sockaddr *) &a),
572                        (addr->family ==
573                         AF_INET6 ? sizeof(a6) : sizeof(a)));
574 #else
575         retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
576 #endif
577         if (retcode != SOCKET_ERROR) {
578             err = 0;
579             break;                     /* done */
580         } else {
581             err = WSAGetLastError();
582             if (err != WSAEADDRINUSE)  /* failed, for a bad reason */
583                 break;
584         }
585
586         if (localport == 0)
587             break;                     /* we're only looping once */
588         localport--;
589         if (localport == 0)
590             break;                     /* we might have got to the end */
591     }
592
593     if (err) {
594         ret->error = winsock_error_string(err);
595         return (Socket) ret;
596     }
597
598     /*
599      * Connect to remote address.
600      */
601 #ifdef IPV6
602     if (addr->family == AF_INET6) {
603         memset(&a, 0, sizeof(a));
604         a6.sin6_family = AF_INET6;
605         a6.sin6_port = htons((short) port);
606         a6.sin6_addr =
607             ((struct sockaddr_in6 *) addr->ai->ai_addr)->sin6_addr;
608     } else
609 #endif
610     {
611         a.sin_family = AF_INET;
612         a.sin_addr.s_addr = htonl(addr->address);
613         a.sin_port = htons((short) port);
614     }
615
616     /* Set up a select mechanism. This could be an AsyncSelect on a
617      * window, or an EventSelect on an event object. */
618     errstr = do_select(s, 1);
619     if (errstr) {
620         ret->error = errstr;
621         return (Socket) ret;
622     }
623
624     if ((
625 #ifdef IPV6
626             connect(s, ((addr->family == AF_INET6) ?
627                         (struct sockaddr *) &a6 : (struct sockaddr *) &a),
628                     (addr->family == AF_INET6) ? sizeof(a6) : sizeof(a))
629 #else
630             connect(s, (struct sockaddr *) &a, sizeof(a))
631 #endif
632         ) == SOCKET_ERROR) {
633         err = WSAGetLastError();
634         /*
635          * We expect a potential EWOULDBLOCK here, because the
636          * chances are the front end has done a select for
637          * FD_CONNECT, so that connect() will complete
638          * asynchronously.
639          */
640         if ( err != WSAEWOULDBLOCK ) {
641             ret->error = winsock_error_string(err);
642             return (Socket) ret;
643         }
644     } else {
645         /*
646          * If we _don't_ get EWOULDBLOCK, the connect has completed
647          * and we should set the socket as writable.
648          */
649         ret->writable = 1;
650     }
651
652     add234(sktree, ret);
653
654     return (Socket) ret;
655 }
656
657 Socket sk_newlistener(int port, Plug plug, int local_host_only)
658 {
659     static struct socket_function_table fn_table = {
660         sk_tcp_plug,
661         sk_tcp_close,
662         sk_tcp_write,
663         sk_tcp_write_oob,
664         sk_tcp_flush,
665         sk_tcp_set_private_ptr,
666         sk_tcp_get_private_ptr,
667         sk_tcp_set_frozen,
668         sk_tcp_socket_error
669     };
670
671     SOCKET s;
672 #ifdef IPV6
673     SOCKADDR_IN6 a6;
674 #endif
675     SOCKADDR_IN a;
676     DWORD err;
677     char *errstr;
678     Actual_Socket ret;
679     int retcode;
680     int on = 1;
681
682     /*
683      * Create Socket structure.
684      */
685     ret = smalloc(sizeof(struct Socket_tag));
686     ret->fn = &fn_table;
687     ret->error = NULL;
688     ret->plug = plug;
689     bufchain_init(&ret->output_data);
690     ret->writable = 0;                 /* to start with */
691     ret->sending_oob = 0;
692     ret->frozen = 0;
693     ret->frozen_readable = 0;
694     ret->localhost_only = local_host_only;
695     ret->pending_error = 0;
696
697     /*
698      * Open socket.
699      */
700     s = socket(AF_INET, SOCK_STREAM, 0);
701     ret->s = s;
702
703     if (s == INVALID_SOCKET) {
704         err = WSAGetLastError();
705         ret->error = winsock_error_string(err);
706         return (Socket) ret;
707     }
708
709     ret->oobinline = 0;
710
711
712     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
713
714
715 #ifdef IPV6
716         if (addr->family == AF_INET6) {
717             memset(&a6, 0, sizeof(a6));
718             a6.sin6_family = AF_INET6;
719             if (local_host_only)
720                 a6.sin6_addr = in6addr_loopback;
721             else
722                 a6.sin6_addr = in6addr_any;
723             a6.sin6_port = htons(port);
724         } else
725 #endif
726         {
727             a.sin_family = AF_INET;
728             if (local_host_only)
729                 a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
730             else
731                 a.sin_addr.s_addr = htonl(INADDR_ANY);
732             a.sin_port = htons((short)port);
733         }
734 #ifdef IPV6
735         retcode = bind(s, (addr->family == AF_INET6 ?
736                            (struct sockaddr *) &a6 :
737                            (struct sockaddr *) &a),
738                        (addr->family ==
739                         AF_INET6 ? sizeof(a6) : sizeof(a)));
740 #else
741         retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
742 #endif
743         if (retcode != SOCKET_ERROR) {
744             err = 0;
745         } else {
746             err = WSAGetLastError();
747         }
748
749     if (err) {
750         ret->error = winsock_error_string(err);
751         return (Socket) ret;
752     }
753
754
755     if (listen(s, SOMAXCONN) == SOCKET_ERROR) {
756         closesocket(s);
757         ret->error = winsock_error_string(err);
758         return (Socket) ret;
759     }
760
761     /* Set up a select mechanism. This could be an AsyncSelect on a
762      * window, or an EventSelect on an event object. */
763     errstr = do_select(s, 1);
764     if (errstr) {
765         ret->error = errstr;
766         return (Socket) ret;
767     }
768
769     add234(sktree, ret);
770
771     return (Socket) ret;
772 }
773
774 static void sk_tcp_close(Socket sock)
775 {
776     extern char *do_select(SOCKET skt, int startup);
777     Actual_Socket s = (Actual_Socket) sock;
778
779     del234(sktree, s);
780     do_select(s->s, 0);
781     closesocket(s->s);
782     sfree(s);
783 }
784
785 /*
786  * The function which tries to send on a socket once it's deemed
787  * writable.
788  */
789 void try_send(Actual_Socket s)
790 {
791     while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
792         int nsent;
793         DWORD err;
794         void *data;
795         int len, urgentflag;
796
797         if (s->sending_oob) {
798             urgentflag = MSG_OOB;
799             len = s->sending_oob;
800             data = &s->oobdata;
801         } else {
802             urgentflag = 0;
803             bufchain_prefix(&s->output_data, &data, &len);
804         }
805         nsent = send(s->s, data, len, urgentflag);
806         noise_ultralight(nsent);
807         if (nsent <= 0) {
808             err = (nsent < 0 ? WSAGetLastError() : 0);
809             if ((err < WSABASEERR && nsent < 0) || err == WSAEWOULDBLOCK) {
810                 /*
811                  * Perfectly normal: we've sent all we can for the moment.
812                  * 
813                  * (Some WinSock send() implementations can return
814                  * <0 but leave no sensible error indication -
815                  * WSAGetLastError() is called but returns zero or
816                  * a small number - so we check that case and treat
817                  * it just like WSAEWOULDBLOCK.)
818                  */
819                 s->writable = FALSE;
820                 return;
821             } else if (nsent == 0 ||
822                        err == WSAECONNABORTED || err == WSAECONNRESET) {
823                 /*
824                  * If send() returns CONNABORTED or CONNRESET, we
825                  * unfortunately can't just call plug_closing(),
826                  * because it's quite likely that we're currently
827                  * _in_ a call from the code we'd be calling back
828                  * to, so we'd have to make half the SSH code
829                  * reentrant. Instead we flag a pending error on
830                  * the socket, to be dealt with (by calling
831                  * plug_closing()) at some suitable future moment.
832                  */
833                 s->pending_error = err;
834                 return;
835             } else {
836                 logevent(winsock_error_string(err));
837                 fatalbox("%s", winsock_error_string(err));
838             }
839         } else {
840             if (s->sending_oob) {
841                 if (nsent < len) {
842                     memmove(s->oobdata, s->oobdata+nsent, len-nsent);
843                     s->sending_oob = len - nsent;
844                 } else {
845                     s->sending_oob = 0;
846                 }
847             } else {
848                 bufchain_consume(&s->output_data, nsent);
849             }
850         }
851     }
852 }
853
854 static int sk_tcp_write(Socket sock, char *buf, int len)
855 {
856     Actual_Socket s = (Actual_Socket) sock;
857
858     /*
859      * Add the data to the buffer list on the socket.
860      */
861     bufchain_add(&s->output_data, buf, len);
862
863     /*
864      * Now try sending from the start of the buffer list.
865      */
866     if (s->writable)
867         try_send(s);
868
869     return bufchain_size(&s->output_data);
870 }
871
872 static int sk_tcp_write_oob(Socket sock, char *buf, int len)
873 {
874     Actual_Socket s = (Actual_Socket) sock;
875
876     /*
877      * Replace the buffer list on the socket with the data.
878      */
879     bufchain_clear(&s->output_data);
880     assert(len <= sizeof(s->oobdata));
881     memcpy(s->oobdata, buf, len);
882     s->sending_oob = len;
883
884     /*
885      * Now try sending from the start of the buffer list.
886      */
887     if (s->writable)
888         try_send(s);
889
890     return s->sending_oob;
891 }
892
893 int select_result(WPARAM wParam, LPARAM lParam)
894 {
895     int ret, open;
896     DWORD err;
897     char buf[20480];                   /* nice big buffer for plenty of speed */
898     Actual_Socket s;
899     u_long atmark;
900
901     /* wParam is the socket itself */
902     s = find234(sktree, (void *) wParam, cmpforsearch);
903     if (!s)
904         return 1;                      /* boggle */
905
906     if ((err = WSAGETSELECTERROR(lParam)) != 0) {
907         /*
908          * An error has occurred on this socket. Pass it to the
909          * plug.
910          */
911         return plug_closing(s->plug, winsock_error_string(err), err, 0);
912     }
913
914     noise_ultralight(lParam);
915
916     switch (WSAGETSELECTEVENT(lParam)) {
917       case FD_CONNECT:
918         s->connected = s->writable = 1;
919         break;
920       case FD_READ:
921         /* In the case the socket is still frozen, we don't even bother */
922         if (s->frozen) {
923             s->frozen_readable = 1;
924             break;
925         }
926
927         /*
928          * We have received data on the socket. For an oobinline
929          * socket, this might be data _before_ an urgent pointer,
930          * in which case we send it to the back end with type==1
931          * (data prior to urgent).
932          */
933         if (s->oobinline) {
934             atmark = 1;
935             ioctlsocket(s->s, SIOCATMARK, &atmark);
936             /*
937              * Avoid checking the return value from ioctlsocket(),
938              * on the grounds that some WinSock wrappers don't
939              * support it. If it does nothing, we get atmark==1,
940              * which is equivalent to `no OOB pending', so the
941              * effect will be to non-OOB-ify any OOB data.
942              */
943         } else
944             atmark = 1;
945
946         ret = recv(s->s, buf, sizeof(buf), 0);
947         noise_ultralight(ret);
948         if (ret < 0) {
949             err = WSAGetLastError();
950             if (err == WSAEWOULDBLOCK) {
951                 break;
952             }
953         }
954         if (ret < 0) {
955             return plug_closing(s->plug, winsock_error_string(err), err,
956                                 0);
957         } else if (0 == ret) {
958             return plug_closing(s->plug, NULL, 0, 0);
959         } else {
960             return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
961         }
962         break;
963       case FD_OOB:
964         /*
965          * This will only happen on a non-oobinline socket. It
966          * indicates that we can immediately perform an OOB read
967          * and get back OOB data, which we will send to the back
968          * end with type==2 (urgent data).
969          */
970         ret = recv(s->s, buf, sizeof(buf), MSG_OOB);
971         noise_ultralight(ret);
972         if (ret <= 0) {
973             char *str = (ret == 0 ? "Internal networking trouble" :
974                          winsock_error_string(WSAGetLastError()));
975             logevent(str);
976             fatalbox("%s", str);
977         } else {
978             return plug_receive(s->plug, 2, buf, ret);
979         }
980         break;
981       case FD_WRITE:
982         {
983             int bufsize_before, bufsize_after;
984             s->writable = 1;
985             bufsize_before = s->sending_oob + bufchain_size(&s->output_data);
986             try_send(s);
987             bufsize_after = s->sending_oob + bufchain_size(&s->output_data);
988             if (bufsize_after < bufsize_before)
989                 plug_sent(s->plug, bufsize_after);
990         }
991         break;
992       case FD_CLOSE:
993         /* Signal a close on the socket. First read any outstanding data. */
994         open = 1;
995         do {
996             ret = recv(s->s, buf, sizeof(buf), 0);
997             if (ret < 0) {
998                 err = WSAGetLastError();
999                 if (err == WSAEWOULDBLOCK)
1000                     break;
1001                 return plug_closing(s->plug, winsock_error_string(err),
1002                                     err, 0);
1003             } else {
1004                 if (ret)
1005                     open &= plug_receive(s->plug, 0, buf, ret);
1006                 else
1007                     open &= plug_closing(s->plug, NULL, 0, 0);
1008             }
1009         } while (ret > 0);
1010         return open;
1011        case FD_ACCEPT:
1012         {
1013             struct sockaddr_in isa;
1014             int addrlen = sizeof(struct sockaddr_in);
1015             SOCKET t;  /* socket of connection */
1016
1017             memset(&isa, 0, sizeof(struct sockaddr_in));
1018             err = 0;
1019             t = accept(s->s,(struct sockaddr *)&isa,&addrlen);
1020             if (t == INVALID_SOCKET)
1021             {
1022                 err = WSAGetLastError();
1023                 if (err == WSATRY_AGAIN)
1024                     break;
1025             }
1026
1027             if (s->localhost_only &&
1028                 ntohl(isa.sin_addr.s_addr) != INADDR_LOOPBACK) {
1029                 closesocket(t);        /* dodgy WinSock let nonlocal through */
1030             } else if (plug_accepting(s->plug, (void*)t)) {
1031                 closesocket(t);        /* denied or error */
1032             }
1033         }
1034     }
1035
1036     return 1;
1037 }
1038
1039 /*
1040  * Deal with socket errors detected in try_send().
1041  */
1042 void net_pending_errors(void)
1043 {
1044     int i;
1045     Actual_Socket s;
1046
1047     /*
1048      * This might be a fiddly business, because it's just possible
1049      * that handling a pending error on one socket might cause
1050      * others to be closed. (I can't think of any reason this might
1051      * happen in current SSH implementation, but to maintain
1052      * generality of this network layer I'll assume the worst.)
1053      * 
1054      * So what we'll do is search the socket list for _one_ socket
1055      * with a pending error, and then handle it, and then search
1056      * the list again _from the beginning_. Repeat until we make a
1057      * pass with no socket errors present. That way we are
1058      * protected against the socket list changing under our feet.
1059      */
1060
1061     do {
1062         for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
1063             if (s->pending_error) {
1064                 /*
1065                  * An error has occurred on this socket. Pass it to the
1066                  * plug.
1067                  */
1068                 plug_closing(s->plug,
1069                              winsock_error_string(s->pending_error),
1070                              s->pending_error, 0);
1071                 break;
1072             }
1073         }
1074     } while (s);
1075 }
1076
1077 /*
1078  * Each socket abstraction contains a `void *' private field in
1079  * which the client can keep state.
1080  */
1081 static void sk_tcp_set_private_ptr(Socket sock, void *ptr)
1082 {
1083     Actual_Socket s = (Actual_Socket) sock;
1084     s->private_ptr = ptr;
1085 }
1086
1087 static void *sk_tcp_get_private_ptr(Socket sock)
1088 {
1089     Actual_Socket s = (Actual_Socket) sock;
1090     return s->private_ptr;
1091 }
1092
1093 /*
1094  * Special error values are returned from sk_namelookup and sk_new
1095  * if there's a problem. These functions extract an error message,
1096  * or return NULL if there's no problem.
1097  */
1098 char *sk_addr_error(SockAddr addr)
1099 {
1100     return addr->error;
1101 }
1102 static char *sk_tcp_socket_error(Socket sock)
1103 {
1104     Actual_Socket s = (Actual_Socket) sock;
1105     return s->error;
1106 }
1107
1108 static void sk_tcp_set_frozen(Socket sock, int is_frozen)
1109 {
1110     Actual_Socket s = (Actual_Socket) sock;
1111     if (s->frozen == is_frozen)
1112         return;
1113     s->frozen = is_frozen;
1114     if (!is_frozen && s->frozen_readable) {
1115         char c;
1116         recv(s->s, &c, 1, MSG_PEEK);
1117     }
1118     s->frozen_readable = 0;
1119 }
1120
1121 /*
1122  * For Plink: enumerate all sockets currently active.
1123  */
1124 SOCKET first_socket(int *state)
1125 {
1126     Actual_Socket s;
1127     *state = 0;
1128     s = index234(sktree, (*state)++);
1129     return s ? s->s : INVALID_SOCKET;
1130 }
1131
1132 SOCKET next_socket(int *state)
1133 {
1134     Actual_Socket s = index234(sktree, (*state)++);
1135     return s ? s->s : INVALID_SOCKET;
1136 }