Patch from Iain Patterson: fix crash on Windows when GSSAPI auth is attempted
[sgt/putty] / unix / uxnet.c
CommitLineData
c5e438ec 1/*
2 * Unix networking abstraction.
3 */
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <assert.h>
8#include <errno.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <sys/types.h>
12#include <sys/socket.h>
13#include <sys/ioctl.h>
14#include <arpa/inet.h>
15#include <netinet/in.h>
16#include <netinet/tcp.h>
17#include <netdb.h>
fc0f17db 18#include <sys/un.h>
c5e438ec 19
20#define DEFINE_PLUG_METHOD_MACROS
21#include "putty.h"
22#include "network.h"
23#include "tree234.h"
24
dbf58cfa 25/* Solaris needs <sys/sockio.h> for SIOCATMARK. */
5f86b177 26#ifndef SIOCATMARK
dbf58cfa 27#include <sys/sockio.h>
28#endif
29
fc0f17db 30#ifndef X11_UNIX_PATH
31# define X11_UNIX_PATH "/tmp/.X11-unix/X"
32#endif
33
4efd5997 34/*
35 * We used to typedef struct Socket_tag *Socket.
36 *
37 * Since we have made the networking abstraction slightly more
38 * abstract, Socket no longer means a tcp socket (it could mean
39 * an ssl socket). So now we must use Actual_Socket when we know
40 * we are talking about a tcp socket.
41 */
42typedef struct Socket_tag *Actual_Socket;
43
c5e438ec 44struct Socket_tag {
45 struct socket_function_table *fn;
46 /* the above variable absolutely *must* be the first in this structure */
cbe2d68f 47 const char *error;
c5e438ec 48 int s;
49 Plug plug;
50 void *private_ptr;
51 bufchain output_data;
1cfc764f 52 int connected; /* irrelevant for listening sockets */
c5e438ec 53 int writable;
54 int frozen; /* this causes readability notifications to be ignored */
55 int frozen_readable; /* this means we missed at least one readability
56 * notification while we were frozen */
57 int localhost_only; /* for listening sockets */
58 char oobdata[1];
59 int sending_oob;
60 int oobpending; /* is there OOB data available to read? */
61 int oobinline;
62 int pending_error; /* in case send() returns error */
63 int listener;
7555d6a5 64 int nodelay, keepalive; /* for connect()-type sockets */
65 int privport, port; /* and again */
66 SockAddr addr;
4efd5997 67 /*
68 * We sometimes need pairs of Socket structures to be linked:
69 * if we are listening on the same IPv6 and v4 port, for
70 * example. So here we define `parent' and `child' pointers to
71 * track this link.
72 */
73 Actual_Socket parent, child;
c5e438ec 74};
75
c5e438ec 76struct SockAddr_tag {
cbe2d68f 77 const char *error;
b7a189f3 78 /*
79 * Which address family this address belongs to. AF_INET for
80 * IPv4; AF_INET6 for IPv6; AF_UNSPEC indicates that name
81 * resolution has not been done and a simple host name is held
82 * in this SockAddr structure.
83 */
c5e438ec 84 int family;
05581745 85#ifndef NO_IPV6
7555d6a5 86 struct addrinfo *ais; /* Addresses IPv6 style. */
87 struct addrinfo *ai; /* steps along the linked list */
792c5eb5 88#else
7555d6a5 89 unsigned long *addresses; /* Addresses IPv4 style. */
90 int naddresses, curraddr;
c5e438ec 91#endif
b7a189f3 92 char hostname[512]; /* Store an unresolved host name. */
c5e438ec 93};
94
95static tree234 *sktree;
96
0ff9ea38 97static void uxsel_tell(Actual_Socket s);
98
c5e438ec 99static int cmpfortree(void *av, void *bv)
100{
101 Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
102 int as = a->s, bs = b->s;
103 if (as < bs)
104 return -1;
105 if (as > bs)
106 return +1;
fef4049e 107 if (a < b)
108 return -1;
109 if (a > b)
110 return +1;
c5e438ec 111 return 0;
112}
113
114static int cmpforsearch(void *av, void *bv)
115{
116 Actual_Socket b = (Actual_Socket) bv;
f7f9fb5c 117 int as = *(int *)av, bs = b->s;
c5e438ec 118 if (as < bs)
119 return -1;
120 if (as > bs)
121 return +1;
122 return 0;
123}
124
125void sk_init(void)
126{
127 sktree = newtree234(cmpfortree);
128}
129
130void sk_cleanup(void)
131{
132 Actual_Socket s;
133 int i;
134
135 if (sktree) {
136 for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
137 close(s->s);
138 }
139 }
140}
141
05581745 142SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family)
c5e438ec 143{
3d88e64d 144 SockAddr ret = snew(struct SockAddr_tag);
05581745 145#ifndef NO_IPV6
792c5eb5 146 struct addrinfo hints;
147 int err;
148#else
c5e438ec 149 unsigned long a;
150 struct hostent *h = NULL;
7555d6a5 151 int n;
792c5eb5 152#endif
c5e438ec 153 char realhost[8192];
154
155 /* Clear the structure and default to IPv4. */
156 memset(ret, 0, sizeof(struct SockAddr_tag));
157 ret->family = 0; /* We set this one when we have resolved the host. */
158 *realhost = '\0';
159 ret->error = NULL;
160
05581745 161#ifndef NO_IPV6
792c5eb5 162 hints.ai_flags = AI_CANONNAME;
81b34354 163 hints.ai_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
164 address_family == ADDRTYPE_IPV6 ? AF_INET6 :
165 AF_UNSPEC);
166 hints.ai_socktype = SOCK_STREAM;
792c5eb5 167 hints.ai_protocol = 0;
168 hints.ai_addrlen = 0;
169 hints.ai_addr = NULL;
170 hints.ai_canonname = NULL;
171 hints.ai_next = NULL;
7555d6a5 172 err = getaddrinfo(host, NULL, &hints, &ret->ais);
173 ret->ai = ret->ais;
792c5eb5 174 if (err != 0) {
175 ret->error = gai_strerror(err);
176 return ret;
177 }
178 ret->family = ret->ai->ai_family;
179 *realhost = '\0';
180 if (ret->ai->ai_canonname != NULL)
181 strncat(realhost, ret->ai->ai_canonname, sizeof(realhost) - 1);
182 else
183 strncat(realhost, host, sizeof(realhost) - 1);
184#else
72e22079 185 if ((a = inet_addr(host)) == (unsigned long)(in_addr_t)(-1)) {
792c5eb5 186 /*
187 * Otherwise use the IPv4-only gethostbyname... (NOTE:
188 * we don't use gethostbyname as a fallback!)
189 */
190 if (ret->family == 0) {
7555d6a5 191 /*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */
192 if ( (h = gethostbyname(host)) )
193 ret->family = AF_INET;
792c5eb5 194 }
195 if (ret->family == 0) {
7555d6a5 196 ret->error = (h_errno == HOST_NOT_FOUND ||
197 h_errno == NO_DATA ||
198 h_errno == NO_ADDRESS ? "Host does not exist" :
199 h_errno == TRY_AGAIN ?
200 "Temporary name service failure" :
201 "gethostbyname: unknown error");
202 return ret;
c5e438ec 203 }
792c5eb5 204 /* This way we are always sure the h->h_name is valid :) */
205 strncpy(realhost, h->h_name, sizeof(realhost));
7555d6a5 206 for (n = 0; h->h_addr_list[n]; n++);
207 ret->addresses = snewn(n, unsigned long);
208 ret->naddresses = n;
209 for (n = 0; n < ret->naddresses; n++) {
210 memcpy(&a, h->h_addr_list[n], sizeof(a));
211 ret->addresses[n] = ntohl(a);
212 }
c5e438ec 213 } else {
214 /*
215 * This must be a numeric IPv4 address because it caused a
216 * success return from inet_addr.
217 */
218 ret->family = AF_INET;
219 strncpy(realhost, host, sizeof(realhost));
7555d6a5 220 ret->addresses = snew(unsigned long);
221 ret->naddresses = 1;
222 ret->addresses[0] = ntohl(a);
223 ret->curraddr = 0;
c5e438ec 224 }
792c5eb5 225#endif
c5e438ec 226 realhost[lenof(realhost)-1] = '\0';
3d88e64d 227 *canonicalname = snewn(1+strlen(realhost), char);
c5e438ec 228 strcpy(*canonicalname, realhost);
229 return ret;
230}
231
e8fa8f62 232SockAddr sk_nonamelookup(const char *host)
b7a189f3 233{
3d88e64d 234 SockAddr ret = snew(struct SockAddr_tag);
ab0873ab 235 ret->error = NULL;
b7a189f3 236 ret->family = AF_UNSPEC;
237 strncpy(ret->hostname, host, lenof(ret->hostname));
238 ret->hostname[lenof(ret->hostname)-1] = '\0';
e14d27a1 239#ifndef NO_IPV6
7555d6a5 240 ret->ais = NULL;
241#else
242 ret->addresses = NULL;
e14d27a1 243#endif
b7a189f3 244 return ret;
245}
246
7555d6a5 247static int sk_nextaddr(SockAddr addr)
248{
249#ifndef NO_IPV6
c24e27c6 250 if (addr->ai && addr->ai->ai_next) {
7555d6a5 251 addr->ai = addr->ai->ai_next;
252 addr->family = addr->ai->ai_family;
253 return TRUE;
254 } else
255 return FALSE;
256#else
257 if (addr->curraddr+1 < addr->naddresses) {
258 addr->curraddr++;
259 return TRUE;
260 } else {
261 return FALSE;
262 }
263#endif
264}
265
c5e438ec 266void sk_getaddr(SockAddr addr, char *buf, int buflen)
267{
792c5eb5 268
269 if (addr->family == AF_UNSPEC) {
270 strncpy(buf, addr->hostname, buflen);
271 buf[buflen-1] = '\0';
272 } else {
05581745 273#ifndef NO_IPV6
792c5eb5 274 if (getnameinfo(addr->ai->ai_addr, addr->ai->ai_addrlen, buf, buflen,
275 NULL, 0, NI_NUMERICHOST) != 0) {
276 buf[0] = '\0';
277 strncat(buf, "<unknown>", buflen - 1);
278 }
279#else
c5e438ec 280 struct in_addr a;
792c5eb5 281 assert(addr->family == AF_INET);
7555d6a5 282 a.s_addr = htonl(addr->addresses[addr->curraddr]);
c5e438ec 283 strncpy(buf, inet_ntoa(a), buflen);
b7a189f3 284 buf[buflen-1] = '\0';
792c5eb5 285#endif
c5e438ec 286 }
c5e438ec 287}
288
b804e1e5 289int sk_hostname_is_local(char *name)
290{
291 return !strcmp(name, "localhost");
292}
293
147d3370 294#define ipv4_is_loopback(addr) \
295 (((addr).s_addr & htonl(0xff000000)) == htonl(0x7f000000))
296
297static int sockaddr_is_loopback(struct sockaddr *sa)
298{
299 struct sockaddr_in *sin;
300#ifndef NO_IPV6
301 struct sockaddr_in6 *sin6;
302#endif
303
304 switch (sa->sa_family) {
305 case AF_INET:
306 sin = (struct sockaddr_in *)sa;
307 return ipv4_is_loopback(sin->sin_addr);
308#ifndef NO_IPV6
309 case AF_INET6:
310 sin6 = (struct sockaddr_in6 *)sa;
311 return IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr);
312#endif
ff677091 313 case AF_UNIX:
147d3370 314 return TRUE;
315 default:
316 return FALSE;
317 }
318}
319
b804e1e5 320int sk_address_is_local(SockAddr addr)
321{
792c5eb5 322
323 if (addr->family == AF_UNSPEC)
324 return 0; /* we don't know; assume not */
325 else {
05581745 326#ifndef NO_IPV6
147d3370 327 return sockaddr_is_loopback(addr->ai->ai_addr);
792c5eb5 328#else
b804e1e5 329 struct in_addr a;
792c5eb5 330 assert(addr->family == AF_INET);
7555d6a5 331 a.s_addr = htonl(addr->addresses[addr->curraddr]);
b804e1e5 332 return ipv4_is_loopback(a);
792c5eb5 333#endif
b804e1e5 334 }
b804e1e5 335}
336
c5e438ec 337int sk_addrtype(SockAddr addr)
338{
b7a189f3 339 return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
05581745 340#ifndef NO_IPV6
b7a189f3 341 addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
342#endif
343 ADDRTYPE_NAME);
c5e438ec 344}
345
346void sk_addrcopy(SockAddr addr, char *buf)
347{
792c5eb5 348
05581745 349#ifndef NO_IPV6
792c5eb5 350 if (addr->family == AF_INET)
351 memcpy(buf, &((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr,
352 sizeof(struct in_addr));
353 else if (addr->family == AF_INET6)
354 memcpy(buf, &((struct sockaddr_in6 *)addr->ai->ai_addr)->sin6_addr,
355 sizeof(struct in6_addr));
356 else
357 assert(FALSE);
358#else
359 struct in_addr a;
360
361 assert(addr->family == AF_INET);
7555d6a5 362 a.s_addr = htonl(addr->addresses[addr->curraddr]);
792c5eb5 363 memcpy(buf, (char*) &a.s_addr, 4);
c5e438ec 364#endif
c5e438ec 365}
366
367void sk_addr_free(SockAddr addr)
368{
792c5eb5 369
05581745 370#ifndef NO_IPV6
7555d6a5 371 if (addr->ais != NULL)
372 freeaddrinfo(addr->ais);
373#else
374 sfree(addr->addresses);
792c5eb5 375#endif
c5e438ec 376 sfree(addr);
377}
378
379static Plug sk_tcp_plug(Socket sock, Plug p)
380{
381 Actual_Socket s = (Actual_Socket) sock;
382 Plug ret = s->plug;
383 if (p)
384 s->plug = p;
385 return ret;
386}
387
388static void sk_tcp_flush(Socket s)
389{
390 /*
391 * We send data to the socket as soon as we can anyway,
392 * so we don't need to do anything here. :-)
393 */
394}
395
396static void sk_tcp_close(Socket s);
e0e7dff8 397static int sk_tcp_write(Socket s, const char *data, int len);
398static int sk_tcp_write_oob(Socket s, const char *data, int len);
c5e438ec 399static void sk_tcp_set_private_ptr(Socket s, void *ptr);
400static void *sk_tcp_get_private_ptr(Socket s);
401static void sk_tcp_set_frozen(Socket s, int is_frozen);
cbe2d68f 402static const char *sk_tcp_socket_error(Socket s);
c5e438ec 403
2f92b717 404static struct socket_function_table tcp_fn_table = {
405 sk_tcp_plug,
406 sk_tcp_close,
407 sk_tcp_write,
408 sk_tcp_write_oob,
409 sk_tcp_flush,
410 sk_tcp_set_private_ptr,
411 sk_tcp_get_private_ptr,
412 sk_tcp_set_frozen,
413 sk_tcp_socket_error
414};
415
f7f9fb5c 416Socket sk_register(OSSocket sockfd, Plug plug)
c5e438ec 417{
c5e438ec 418 Actual_Socket ret;
419
420 /*
421 * Create Socket structure.
422 */
3d88e64d 423 ret = snew(struct Socket_tag);
2f92b717 424 ret->fn = &tcp_fn_table;
c5e438ec 425 ret->error = NULL;
426 ret->plug = plug;
427 bufchain_init(&ret->output_data);
428 ret->writable = 1; /* to start with */
429 ret->sending_oob = 0;
430 ret->frozen = 1;
431 ret->frozen_readable = 0;
432 ret->localhost_only = 0; /* unused, but best init anyway */
433 ret->pending_error = 0;
434 ret->oobpending = FALSE;
435 ret->listener = 0;
4efd5997 436 ret->parent = ret->child = NULL;
7555d6a5 437 ret->addr = NULL;
a8cb2b6e 438 ret->connected = 1;
c5e438ec 439
f7f9fb5c 440 ret->s = sockfd;
c5e438ec 441
442 if (ret->s < 0) {
7555d6a5 443 ret->error = strerror(errno);
c5e438ec 444 return (Socket) ret;
445 }
446
447 ret->oobinline = 0;
448
0ff9ea38 449 uxsel_tell(ret);
c5e438ec 450 add234(sktree, ret);
451
452 return (Socket) ret;
453}
454
7555d6a5 455static int try_connect(Actual_Socket sock)
c5e438ec 456{
c5e438ec 457 int s;
05581745 458#ifndef NO_IPV6
c5e438ec 459 struct sockaddr_in6 a6;
460#endif
461 struct sockaddr_in a;
fc0f17db 462 struct sockaddr_un au;
463 const struct sockaddr *sa;
7555d6a5 464 int err = 0;
c5e438ec 465 short localport;
fc0f17db 466 int fl, salen;
c5e438ec 467
fef4049e 468 /*
469 * Remove the socket from the tree before we overwrite its
470 * internal socket id, because that forms part of the tree's
471 * sorting criterion. We'll add it back before exiting this
472 * function, whether we changed anything or not.
473 */
474 del234(sktree, sock);
475
7555d6a5 476 if (sock->s >= 0)
477 close(sock->s);
478
479 plug_log(sock->plug, 0, sock->addr, sock->port, NULL, 0);
c5e438ec 480
481 /*
482 * Open socket.
483 */
7555d6a5 484 assert(sock->addr->family != AF_UNSPEC);
485 s = socket(sock->addr->family, SOCK_STREAM, 0);
486 sock->s = s;
c5e438ec 487
488 if (s < 0) {
7555d6a5 489 err = errno;
490 goto ret;
c5e438ec 491 }
492
db9b7dce 493 cloexec(s);
89e97516 494
7555d6a5 495 if (sock->oobinline) {
c5e438ec 496 int b = TRUE;
497 setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
498 }
499
7555d6a5 500 if (sock->nodelay) {
c5e438ec 501 int b = TRUE;
502 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b));
503 }
504
7555d6a5 505 if (sock->keepalive) {
79bf227b 506 int b = TRUE;
507 setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b));
508 }
509
c5e438ec 510 /*
511 * Bind to local address.
512 */
7555d6a5 513 if (sock->privport)
c5e438ec 514 localport = 1023; /* count from 1023 downwards */
515 else
516 localport = 0; /* just use port 0 (ie kernel picks) */
517
d2c29274 518 /* BSD IP stacks need sockaddr_in zeroed before filling in */
519 memset(&a,'\0',sizeof(struct sockaddr_in));
05581745 520#ifndef NO_IPV6
d2c29274 521 memset(&a6,'\0',sizeof(struct sockaddr_in6));
522#endif
fc0f17db 523
524 /* We don't try to bind to a local address for UNIX domain sockets. (Why
525 * do we bother doing the bind when localport == 0 anyway?) */
7555d6a5 526 if(sock->addr->family != AF_UNIX) {
fc0f17db 527 /* Loop round trying to bind */
528 while (1) {
529 int retcode;
c5e438ec 530
05581745 531#ifndef NO_IPV6
7555d6a5 532 if (sock->addr->family == AF_INET6) {
fc0f17db 533 /* XXX use getaddrinfo to get a local address? */
534 a6.sin6_family = AF_INET6;
535 a6.sin6_addr = in6addr_any;
536 a6.sin6_port = htons(localport);
537 retcode = bind(s, (struct sockaddr *) &a6, sizeof(a6));
538 } else
c5e438ec 539#endif
fc0f17db 540 {
7555d6a5 541 assert(sock->addr->family == AF_INET);
fc0f17db 542 a.sin_family = AF_INET;
543 a.sin_addr.s_addr = htonl(INADDR_ANY);
544 a.sin_port = htons(localport);
545 retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
546 }
547 if (retcode >= 0) {
548 err = 0;
549 break; /* done */
550 } else {
551 err = errno;
552 if (err != EADDRINUSE) /* failed, for a bad reason */
553 break;
554 }
555
556 if (localport == 0)
557 break; /* we're only looping once */
558 localport--;
559 if (localport == 0)
560 break; /* we might have got to the end */
c5e438ec 561 }
fc0f17db 562
7555d6a5 563 if (err)
564 goto ret;
c5e438ec 565 }
566
567 /*
568 * Connect to remote address.
569 */
7555d6a5 570 switch(sock->addr->family) {
05581745 571#ifndef NO_IPV6
fc0f17db 572 case AF_INET:
573 /* XXX would be better to have got getaddrinfo() to fill in the port. */
7555d6a5 574 ((struct sockaddr_in *)sock->addr->ai->ai_addr)->sin_port =
575 htons(sock->port);
576 sa = (const struct sockaddr *)sock->addr->ai->ai_addr;
577 salen = sock->addr->ai->ai_addrlen;
fc0f17db 578 break;
579 case AF_INET6:
7555d6a5 580 ((struct sockaddr_in *)sock->addr->ai->ai_addr)->sin_port =
581 htons(sock->port);
582 sa = (const struct sockaddr *)sock->addr->ai->ai_addr;
583 salen = sock->addr->ai->ai_addrlen;
fc0f17db 584 break;
792c5eb5 585#else
fc0f17db 586 case AF_INET:
587 a.sin_family = AF_INET;
7555d6a5 588 a.sin_addr.s_addr = htonl(sock->addr->addresses[sock->addr->curraddr]);
589 a.sin_port = htons((short) sock->port);
fc0f17db 590 sa = (const struct sockaddr *)&a;
591 salen = sizeof a;
592 break;
792c5eb5 593#endif
fc0f17db 594 case AF_UNIX:
7555d6a5 595 assert(sock->port == 0); /* to catch confused people */
596 assert(strlen(sock->addr->hostname) < sizeof au.sun_path);
fc0f17db 597 memset(&au, 0, sizeof au);
598 au.sun_family = AF_UNIX;
7555d6a5 599 strcpy(au.sun_path, sock->addr->hostname);
fc0f17db 600 sa = (const struct sockaddr *)&au;
601 salen = sizeof au;
602 break;
603
604 default:
605 assert(0 && "unknown address family");
8815b68b 606 exit(1); /* XXX: GCC doesn't understand assert() on some systems. */
fc0f17db 607 }
4b70e70e 608
609 fl = fcntl(s, F_GETFL);
610 if (fl != -1)
611 fcntl(s, F_SETFL, fl | O_NONBLOCK);
051dd789 612
fc0f17db 613 if ((connect(s, sa, salen)) < 0) {
051dd789 614 if ( errno != EINPROGRESS ) {
7555d6a5 615 err = errno;
616 goto ret;
c5e438ec 617 }
618 } else {
619 /*
620 * If we _don't_ get EWOULDBLOCK, the connect has completed
621 * and we should set the socket as connected and writable.
622 */
7555d6a5 623 sock->connected = 1;
624 sock->writable = 1;
c5e438ec 625 }
626
7555d6a5 627 uxsel_tell(sock);
7555d6a5 628
629 ret:
fef4049e 630
631 /*
632 * No matter what happened, put the socket back in the tree.
633 */
634 add234(sktree, sock);
635
7555d6a5 636 if (err)
637 plug_log(sock->plug, 1, sock->addr, sock->port, strerror(err), err);
638 return err;
639}
640
641Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
642 int nodelay, int keepalive, Plug plug)
643{
644 Actual_Socket ret;
645 int err;
646
647 /*
648 * Create Socket structure.
649 */
650 ret = snew(struct Socket_tag);
651 ret->fn = &tcp_fn_table;
652 ret->error = NULL;
653 ret->plug = plug;
654 bufchain_init(&ret->output_data);
655 ret->connected = 0; /* to start with */
656 ret->writable = 0; /* to start with */
657 ret->sending_oob = 0;
658 ret->frozen = 0;
659 ret->frozen_readable = 0;
660 ret->localhost_only = 0; /* unused, but best init anyway */
661 ret->pending_error = 0;
4efd5997 662 ret->parent = ret->child = NULL;
7555d6a5 663 ret->oobpending = FALSE;
664 ret->listener = 0;
665 ret->addr = addr;
666 ret->s = -1;
667 ret->oobinline = oobinline;
668 ret->nodelay = nodelay;
669 ret->keepalive = keepalive;
670 ret->privport = privport;
671 ret->port = port;
672
673 err = 0;
674 do {
675 err = try_connect(ret);
676 } while (err && sk_nextaddr(ret->addr));
c5e438ec 677
7555d6a5 678 if (err)
679 ret->error = strerror(err);
f85e6f6e 680
c5e438ec 681 return (Socket) ret;
682}
683
4efd5997 684Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int orig_address_family)
c5e438ec 685{
c5e438ec 686 int s;
05581745 687#ifndef NO_IPV6
792c5eb5 688 struct addrinfo hints, *ai;
689 char portstr[6];
adb18b94 690 struct sockaddr_in6 a6;
792c5eb5 691#endif
adb18b94 692 struct sockaddr *addr;
693 int addrlen;
c5e438ec 694 struct sockaddr_in a;
c5e438ec 695 Actual_Socket ret;
696 int retcode;
4efd5997 697 int address_family;
c5e438ec 698 int on = 1;
699
700 /*
701 * Create Socket structure.
702 */
3d88e64d 703 ret = snew(struct Socket_tag);
2f92b717 704 ret->fn = &tcp_fn_table;
c5e438ec 705 ret->error = NULL;
706 ret->plug = plug;
707 bufchain_init(&ret->output_data);
708 ret->writable = 0; /* to start with */
709 ret->sending_oob = 0;
710 ret->frozen = 0;
711 ret->frozen_readable = 0;
712 ret->localhost_only = local_host_only;
713 ret->pending_error = 0;
4efd5997 714 ret->parent = ret->child = NULL;
c5e438ec 715 ret->oobpending = FALSE;
716 ret->listener = 1;
7555d6a5 717 ret->addr = NULL;
c5e438ec 718
719 /*
05581745 720 * Translate address_family from platform-independent constants
721 * into local reality.
722 */
4efd5997 723 address_family = (orig_address_family == ADDRTYPE_IPV4 ? AF_INET :
40040af1 724#ifndef NO_IPV6
4efd5997 725 orig_address_family == ADDRTYPE_IPV6 ? AF_INET6 :
40040af1 726#endif
727 AF_UNSPEC);
05581745 728
729#ifndef NO_IPV6
730 /* Let's default to IPv6.
731 * If the stack doesn't support IPv6, we will fall back to IPv4. */
732 if (address_family == AF_UNSPEC) address_family = AF_INET6;
733#else
734 /* No other choice, default to IPv4 */
735 if (address_family == AF_UNSPEC) address_family = AF_INET;
736#endif
737
738 /*
c5e438ec 739 * Open socket.
740 */
05581745 741 s = socket(address_family, SOCK_STREAM, 0);
742
40040af1 743#ifndef NO_IPV6
05581745 744 /* If the host doesn't support IPv6 try fallback to IPv4. */
745 if (s < 0 && address_family == AF_INET6) {
746 address_family = AF_INET;
747 s = socket(address_family, SOCK_STREAM, 0);
748 }
40040af1 749#endif
c5e438ec 750
751 if (s < 0) {
7555d6a5 752 ret->error = strerror(errno);
c5e438ec 753 return (Socket) ret;
754 }
755
db9b7dce 756 cloexec(s);
89e97516 757
c5e438ec 758 ret->oobinline = 0;
759
760 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
761
adb18b94 762 retcode = -1;
763 addr = NULL; addrlen = -1; /* placate optimiser */
764
765 if (srcaddr != NULL) {
05581745 766#ifndef NO_IPV6
adb18b94 767 hints.ai_flags = AI_NUMERICHOST;
768 hints.ai_family = address_family;
d5474756 769 hints.ai_socktype = SOCK_STREAM;
adb18b94 770 hints.ai_protocol = 0;
771 hints.ai_addrlen = 0;
772 hints.ai_addr = NULL;
773 hints.ai_canonname = NULL;
774 hints.ai_next = NULL;
062af27b 775 assert(port >= 0 && port <= 99999);
adb18b94 776 sprintf(portstr, "%d", port);
777 retcode = getaddrinfo(srcaddr, portstr, &hints, &ai);
7f8c817c 778 if (retcode == 0) {
ca9892ae 779 addr = ai->ai_addr;
780 addrlen = ai->ai_addrlen;
781 }
adb18b94 782#else
783 memset(&a,'\0',sizeof(struct sockaddr_in));
784 a.sin_family = AF_INET;
785 a.sin_port = htons(port);
786 a.sin_addr.s_addr = inet_addr(srcaddr);
787 if (a.sin_addr.s_addr != (in_addr_t)(-1)) {
788 /* Override localhost_only with specified listen addr. */
789 ret->localhost_only = ipv4_is_loopback(a.sin_addr);
adb18b94 790 }
dffa03fd 791 addr = (struct sockaddr *)&a;
adb18b94 792 addrlen = sizeof(a);
793 retcode = 0;
792c5eb5 794#endif
adb18b94 795 }
6ee9b735 796
adb18b94 797 if (retcode != 0) {
798#ifndef NO_IPV6
799 if (address_family == AF_INET6) {
800 memset(&a6,'\0',sizeof(struct sockaddr_in6));
801 a6.sin6_family = AF_INET6;
802 a6.sin6_port = htons(port);
803 if (local_host_only)
804 a6.sin6_addr = in6addr_loopback;
805 else
806 a6.sin6_addr = in6addr_any;
807 addr = (struct sockaddr *)&a6;
808 addrlen = sizeof(a6);
809 } else
810#endif
811 {
812 memset(&a,'\0',sizeof(struct sockaddr_in));
813 a.sin_family = AF_INET;
814 a.sin_port = htons(port);
6ee9b735 815 if (local_host_only)
816 a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
817 else
818 a.sin_addr.s_addr = htonl(INADDR_ANY);
adb18b94 819 addr = (struct sockaddr *)&a;
820 addrlen = sizeof(a);
821 }
c5e438ec 822 }
823
adb18b94 824 retcode = bind(s, addr, addrlen);
825 if (retcode < 0) {
826 close(s);
7555d6a5 827 ret->error = strerror(errno);
c5e438ec 828 return (Socket) ret;
829 }
830
c5e438ec 831 if (listen(s, SOMAXCONN) < 0) {
832 close(s);
7555d6a5 833 ret->error = strerror(errno);
c5e438ec 834 return (Socket) ret;
835 }
836
4efd5997 837#ifndef NO_IPV6
838 /*
839 * If we were given ADDRTYPE_UNSPEC, we must also create an
840 * IPv4 listening socket and link it to this one.
841 */
842 if (address_family == AF_INET6 && orig_address_family == ADDRTYPE_UNSPEC) {
843 Actual_Socket other;
844
845 other = (Actual_Socket) sk_newlistener(srcaddr, port, plug,
846 local_host_only, ADDRTYPE_IPV4);
847
848 if (other) {
849 if (!other->error) {
850 other->parent = ret;
851 ret->child = other;
852 } else {
853 /* If we couldn't create a listening socket on IPv4 as well
854 * as IPv6, we must return an error overall. */
855 close(s);
856 sfree(ret);
857 return (Socket) other;
858 }
859 }
860 }
861#endif
862
adb18b94 863 ret->s = s;
864
0ff9ea38 865 uxsel_tell(ret);
c5e438ec 866 add234(sktree, ret);
867
868 return (Socket) ret;
869}
870
871static void sk_tcp_close(Socket sock)
872{
873 Actual_Socket s = (Actual_Socket) sock;
874
4efd5997 875 if (s->child)
876 sk_tcp_close((Socket)s->child);
877
0ff9ea38 878 uxsel_del(s->s);
c5e438ec 879 del234(sktree, s);
880 close(s->s);
7555d6a5 881 if (s->addr)
882 sk_addr_free(s->addr);
c5e438ec 883 sfree(s);
884}
885
0a4022a1 886void *sk_getxdmdata(void *sock, int *lenp)
2f92b717 887{
888 Actual_Socket s = (Actual_Socket) sock;
0a4022a1 889#ifdef NO_IPV6
2f92b717 890 struct sockaddr_in addr;
0a4022a1 891#else
892 struct sockaddr_storage addr;
893 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
894#endif
895 struct sockaddr *sa = (struct sockaddr *)&addr;
896 struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
2f92b717 897 socklen_t addrlen;
0a4022a1 898 char *buf;
899 static unsigned int unix_addr = 0xFFFFFFFF;
2f92b717 900
901 /*
902 * We must check that this socket really _is_ an Actual_Socket.
903 */
904 if (s->fn != &tcp_fn_table)
0a4022a1 905 return NULL; /* failure */
2f92b717 906
2f92b717 907 addrlen = sizeof(addr);
0a4022a1 908 if (getsockname(s->s, sa, &addrlen) < 0)
909 return NULL;
910 switch(sa->sa_family) {
fc0f17db 911 case AF_INET:
0a4022a1 912 *lenp = 6;
913 buf = snewn(*lenp, char);
914 PUT_32BIT_MSB_FIRST(buf, ntohl(sin->sin_addr.s_addr));
915 PUT_16BIT_MSB_FIRST(buf+4, ntohs(sin->sin_port));
fc0f17db 916 break;
0a4022a1 917#ifndef NO_IPV6
918 case AF_INET6:
919 *lenp = 6;
920 buf = snewn(*lenp, char);
921 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
922 memcpy(buf, sin6->sin6_addr.s6_addr + 12, 4);
923 PUT_16BIT_MSB_FIRST(buf+4, ntohs(sin6->sin6_port));
924 } else
925 /* This is stupid, but it's what XLib does. */
926 memset(buf, 0, 6);
927 break;
928#endif
fc0f17db 929 case AF_UNIX:
0a4022a1 930 *lenp = 6;
931 buf = snewn(*lenp, char);
932 PUT_32BIT_MSB_FIRST(buf, unix_addr--);
933 PUT_16BIT_MSB_FIRST(buf+4, getpid());
fc0f17db 934 break;
2f92b717 935
fc0f17db 936 /* XXX IPV6 */
937
938 default:
0a4022a1 939 return NULL;
fc0f17db 940 }
2f92b717 941
0a4022a1 942 return buf;
2f92b717 943}
944
c5e438ec 945/*
946 * The function which tries to send on a socket once it's deemed
947 * writable.
948 */
949void try_send(Actual_Socket s)
950{
951 while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
952 int nsent;
953 int err;
954 void *data;
955 int len, urgentflag;
956
957 if (s->sending_oob) {
958 urgentflag = MSG_OOB;
959 len = s->sending_oob;
960 data = &s->oobdata;
961 } else {
962 urgentflag = 0;
963 bufchain_prefix(&s->output_data, &data, &len);
964 }
965 nsent = send(s->s, data, len, urgentflag);
966 noise_ultralight(nsent);
967 if (nsent <= 0) {
968 err = (nsent < 0 ? errno : 0);
969 if (err == EWOULDBLOCK) {
970 /*
971 * Perfectly normal: we've sent all we can for the moment.
972 */
973 s->writable = FALSE;
974 return;
f3e0acda 975 } else {
c5e438ec 976 /*
f3e0acda 977 * We unfortunately can't just call plug_closing(),
c5e438ec 978 * because it's quite likely that we're currently
979 * _in_ a call from the code we'd be calling back
980 * to, so we'd have to make half the SSH code
981 * reentrant. Instead we flag a pending error on
982 * the socket, to be dealt with (by calling
983 * plug_closing()) at some suitable future moment.
984 */
985 s->pending_error = err;
986 return;
c5e438ec 987 }
988 } else {
989 if (s->sending_oob) {
990 if (nsent < len) {
991 memmove(s->oobdata, s->oobdata+nsent, len-nsent);
992 s->sending_oob = len - nsent;
993 } else {
994 s->sending_oob = 0;
995 }
996 } else {
997 bufchain_consume(&s->output_data, nsent);
998 }
999 }
1000 }
0ff9ea38 1001 uxsel_tell(s);
c5e438ec 1002}
1003
e0e7dff8 1004static int sk_tcp_write(Socket sock, const char *buf, int len)
c5e438ec 1005{
1006 Actual_Socket s = (Actual_Socket) sock;
1007
1008 /*
1009 * Add the data to the buffer list on the socket.
1010 */
1011 bufchain_add(&s->output_data, buf, len);
1012
1013 /*
1014 * Now try sending from the start of the buffer list.
1015 */
1016 if (s->writable)
1017 try_send(s);
1018
c2a71b0d 1019 /*
1020 * Update the select() status to correctly reflect whether or
1021 * not we should be selecting for write.
1022 */
1023 uxsel_tell(s);
1024
c5e438ec 1025 return bufchain_size(&s->output_data);
1026}
1027
e0e7dff8 1028static int sk_tcp_write_oob(Socket sock, const char *buf, int len)
c5e438ec 1029{
1030 Actual_Socket s = (Actual_Socket) sock;
1031
1032 /*
1033 * Replace the buffer list on the socket with the data.
1034 */
1035 bufchain_clear(&s->output_data);
1036 assert(len <= sizeof(s->oobdata));
1037 memcpy(s->oobdata, buf, len);
1038 s->sending_oob = len;
1039
1040 /*
1041 * Now try sending from the start of the buffer list.
1042 */
1043 if (s->writable)
1044 try_send(s);
1045
c2a71b0d 1046 /*
1047 * Update the select() status to correctly reflect whether or
1048 * not we should be selecting for write.
1049 */
1050 uxsel_tell(s);
1051
c5e438ec 1052 return s->sending_oob;
1053}
1054
0ff9ea38 1055static int net_select_result(int fd, int event)
c5e438ec 1056{
1057 int ret;
c5e438ec 1058 char buf[20480]; /* nice big buffer for plenty of speed */
1059 Actual_Socket s;
1060 u_long atmark;
1061
1062 /* Find the Socket structure */
f7f9fb5c 1063 s = find234(sktree, &fd, cmpforsearch);
c5e438ec 1064 if (!s)
1065 return 1; /* boggle */
1066
1067 noise_ultralight(event);
1068
1069 switch (event) {
c5e438ec 1070 case 4: /* exceptional */
1071 if (!s->oobinline) {
1072 /*
1073 * On a non-oobinline socket, this indicates that we
1074 * can immediately perform an OOB read and get back OOB
1075 * data, which we will send to the back end with
1076 * type==2 (urgent data).
1077 */
1078 ret = recv(s->s, buf, sizeof(buf), MSG_OOB);
1079 noise_ultralight(ret);
1080 if (ret <= 0) {
f3e0acda 1081 return plug_closing(s->plug,
1082 ret == 0 ? "Internal networking trouble" :
1083 strerror(errno), errno, 0);
c5e438ec 1084 } else {
7555d6a5 1085 /*
1086 * Receiving actual data on a socket means we can
1087 * stop falling back through the candidate
1088 * addresses to connect to.
1089 */
1090 if (s->addr) {
1091 sk_addr_free(s->addr);
1092 s->addr = NULL;
1093 }
c5e438ec 1094 return plug_receive(s->plug, 2, buf, ret);
1095 }
1096 break;
1097 }
1098
1099 /*
1100 * If we reach here, this is an oobinline socket, which
56e5b2db 1101 * means we should set s->oobpending and then deal with it
1102 * when we get called for the readability event (which
1103 * should also occur).
c5e438ec 1104 */
1105 s->oobpending = TRUE;
56e5b2db 1106 break;
c5e438ec 1107 case 1: /* readable; also acceptance */
1108 if (s->listener) {
1109 /*
1110 * On a listening socket, the readability event means a
1111 * connection is ready to be accepted.
1112 */
19a4130c 1113#ifdef NO_IPV6
1114 struct sockaddr_in ss;
1115#else
1116 struct sockaddr_storage ss;
1117#endif
1118 socklen_t addrlen = sizeof(ss);
c5e438ec 1119 int t; /* socket of connection */
068ba98c 1120 int fl;
c5e438ec 1121
19a4130c 1122 memset(&ss, 0, addrlen);
1123 t = accept(s->s, (struct sockaddr *)&ss, &addrlen);
c5e438ec 1124 if (t < 0) {
1125 break;
1126 }
1127
068ba98c 1128 fl = fcntl(t, F_GETFL);
1129 if (fl != -1)
1130 fcntl(t, F_SETFL, fl | O_NONBLOCK);
1131
19a4130c 1132 if (s->localhost_only &&
1133 !sockaddr_is_loopback((struct sockaddr *)&ss)) {
c5e438ec 1134 close(t); /* someone let nonlocal through?! */
f7f9fb5c 1135 } else if (plug_accepting(s->plug, t)) {
c5e438ec 1136 close(t); /* denied or error */
1137 }
1138 break;
1139 }
1140
1141 /*
1142 * If we reach here, this is not a listening socket, so
1143 * readability really means readability.
1144 */
1145
1146 /* In the case the socket is still frozen, we don't even bother */
1147 if (s->frozen) {
1148 s->frozen_readable = 1;
1149 break;
1150 }
1151
1152 /*
1153 * We have received data on the socket. For an oobinline
1154 * socket, this might be data _before_ an urgent pointer,
1155 * in which case we send it to the back end with type==1
1156 * (data prior to urgent).
1157 */
1158 if (s->oobinline && s->oobpending) {
1159 atmark = 1;
1160 if (ioctl(s->s, SIOCATMARK, &atmark) == 0 && atmark)
1161 s->oobpending = FALSE; /* clear this indicator */
1162 } else
1163 atmark = 1;
1164
56e5b2db 1165 ret = recv(s->s, buf, s->oobpending ? 1 : sizeof(buf), 0);
c5e438ec 1166 noise_ultralight(ret);
1167 if (ret < 0) {
1168 if (errno == EWOULDBLOCK) {
1169 break;
1170 }
1171 }
1172 if (ret < 0) {
7555d6a5 1173 /*
1174 * An error at this point _might_ be an error reported
1175 * by a non-blocking connect(). So before we return a
1176 * panic status to the user, let's just see whether
1177 * that's the case.
1178 */
1179 int err = errno;
1180 if (s->addr) {
1181 plug_log(s->plug, 1, s->addr, s->port, strerror(err), err);
1182 while (s->addr && sk_nextaddr(s->addr)) {
1183 err = try_connect(s);
1184 }
1185 }
1186 if (err != 0)
1187 return plug_closing(s->plug, strerror(err), err, 0);
c5e438ec 1188 } else if (0 == ret) {
1189 return plug_closing(s->plug, NULL, 0, 0);
1190 } else {
7555d6a5 1191 /*
1192 * Receiving actual data on a socket means we can
1193 * stop falling back through the candidate
1194 * addresses to connect to.
1195 */
1196 if (s->addr) {
1197 sk_addr_free(s->addr);
1198 s->addr = NULL;
1199 }
c5e438ec 1200 return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
1201 }
1202 break;
1203 case 2: /* writable */
051dd789 1204 if (!s->connected) {
1205 /*
1206 * select() reports a socket as _writable_ when an
1207 * asynchronous connection is completed.
1208 */
1209 s->connected = s->writable = 1;
0ff9ea38 1210 uxsel_tell(s);
051dd789 1211 break;
1212 } else {
c5e438ec 1213 int bufsize_before, bufsize_after;
1214 s->writable = 1;
1215 bufsize_before = s->sending_oob + bufchain_size(&s->output_data);
1216 try_send(s);
1217 bufsize_after = s->sending_oob + bufchain_size(&s->output_data);
1218 if (bufsize_after < bufsize_before)
1219 plug_sent(s->plug, bufsize_after);
1220 }
1221 break;
1222 }
1223
1224 return 1;
1225}
1226
1227/*
1228 * Deal with socket errors detected in try_send().
1229 */
1230void net_pending_errors(void)
1231{
1232 int i;
1233 Actual_Socket s;
1234
1235 /*
1236 * This might be a fiddly business, because it's just possible
1237 * that handling a pending error on one socket might cause
1238 * others to be closed. (I can't think of any reason this might
1239 * happen in current SSH implementation, but to maintain
1240 * generality of this network layer I'll assume the worst.)
1241 *
1242 * So what we'll do is search the socket list for _one_ socket
1243 * with a pending error, and then handle it, and then search
1244 * the list again _from the beginning_. Repeat until we make a
1245 * pass with no socket errors present. That way we are
1246 * protected against the socket list changing under our feet.
1247 */
1248
1249 do {
1250 for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
1251 if (s->pending_error) {
1252 /*
1253 * An error has occurred on this socket. Pass it to the
1254 * plug.
1255 */
7555d6a5 1256 plug_closing(s->plug, strerror(s->pending_error),
c5e438ec 1257 s->pending_error, 0);
1258 break;
1259 }
1260 }
1261 } while (s);
1262}
1263
1264/*
1265 * Each socket abstraction contains a `void *' private field in
1266 * which the client can keep state.
1267 */
1268static void sk_tcp_set_private_ptr(Socket sock, void *ptr)
1269{
1270 Actual_Socket s = (Actual_Socket) sock;
1271 s->private_ptr = ptr;
1272}
1273
1274static void *sk_tcp_get_private_ptr(Socket sock)
1275{
1276 Actual_Socket s = (Actual_Socket) sock;
1277 return s->private_ptr;
1278}
1279
1280/*
1281 * Special error values are returned from sk_namelookup and sk_new
1282 * if there's a problem. These functions extract an error message,
1283 * or return NULL if there's no problem.
1284 */
cbe2d68f 1285const char *sk_addr_error(SockAddr addr)
c5e438ec 1286{
1287 return addr->error;
1288}
cbe2d68f 1289static const char *sk_tcp_socket_error(Socket sock)
c5e438ec 1290{
1291 Actual_Socket s = (Actual_Socket) sock;
1292 return s->error;
1293}
1294
1295static void sk_tcp_set_frozen(Socket sock, int is_frozen)
1296{
1297 Actual_Socket s = (Actual_Socket) sock;
1298 if (s->frozen == is_frozen)
1299 return;
1300 s->frozen = is_frozen;
1301 if (!is_frozen && s->frozen_readable) {
1302 char c;
1303 recv(s->s, &c, 1, MSG_PEEK);
1304 }
1305 s->frozen_readable = 0;
0ff9ea38 1306 uxsel_tell(s);
c5e438ec 1307}
1308
0ff9ea38 1309static void uxsel_tell(Actual_Socket s)
c5e438ec 1310{
0ff9ea38 1311 int rwx = 0;
1cfc764f 1312 if (s->listener) {
1313 rwx |= 1; /* read == accept */
1314 } else {
1315 if (!s->connected)
1316 rwx |= 2; /* write == connect */
1317 if (s->connected && !s->frozen)
1318 rwx |= 1 | 4; /* read, except */
1319 if (bufchain_size(&s->output_data))
1320 rwx |= 2; /* write */
1321 }
0ff9ea38 1322 uxsel_set(s->s, rwx, net_select_result);
c5e438ec 1323}
1324
1325int net_service_lookup(char *service)
1326{
1327 struct servent *se;
1328 se = getservbyname(service, NULL);
1329 if (se != NULL)
1330 return ntohs(se->s_port);
1331 else
1332 return 0;
1333}
fc0f17db 1334
48806a46 1335SockAddr platform_get_x11_unix_address(const char *display, int displaynum,
1336 char **canonicalname)
fc0f17db 1337{
1338 SockAddr ret = snew(struct SockAddr_tag);
1339 int n;
1340
1341 memset(ret, 0, sizeof *ret);
1342 ret->family = AF_UNIX;
48806a46 1343 /*
1344 * Mac OS X Leopard uses an innovative X display naming
1345 * convention in which the entire display name is the path to
1346 * the Unix socket, including the trailing :0 which only
1347 * _looks_ like a display number. Heuristically, I think
1348 * detecting this by means of a leading slash ought to be
1349 * adequate.
1350 */
1351 if (display[0] == '/') {
1352 n = snprintf(ret->hostname, sizeof ret->hostname,
1353 "%s", display);
1354 } else {
1355 n = snprintf(ret->hostname, sizeof ret->hostname,
1356 "%s%d", X11_UNIX_PATH, displaynum);
1357 }
fc0f17db 1358 if(n < 0)
1359 ret->error = "snprintf failed";
1360 else if(n >= sizeof ret->hostname)
1361 ret->error = "X11 UNIX name too long";
1362 else
1363 *canonicalname = dupstr(ret->hostname);
7555d6a5 1364#ifndef NO_IPV6
c24e27c6 1365 ret->ai = ret->ais = NULL;
7555d6a5 1366#else
1367 ret->addresses = NULL;
c24e27c6 1368 ret->curraddr = ret->naddresses = 0;
7555d6a5 1369#endif
fc0f17db 1370 return ret;
1371}