Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright (c) 2002, 2025, Oracle and/or its affiliates.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 /*
     24 
     25 Copyright 1993, 1994, 1998  The Open Group
     26 
     27 Permission to use, copy, modify, distribute, and sell this software and its
     28 documentation for any purpose is hereby granted without fee, provided that
     29 the above copyright notice appear in all copies and that both that
     30 copyright notice and this permission notice appear in supporting
     31 documentation.
     32 
     33 The above copyright notice and this permission notice shall be included
     34 in all copies or substantial portions of the Software.
     35 
     36 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     37 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     38 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     39 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     40 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     41 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     42 OTHER DEALINGS IN THE SOFTWARE.
     43 
     44 Except as contained in this notice, the name of the copyright holders shall
     45 not be used in advertising or otherwise to promote the sale, use or
     46 other dealings in this Software without prior written authorization
     47 from the copyright holders.
     48 
     49  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
     50  *
     51  * All Rights Reserved
     52  *
     53  * Permission to use, copy, modify, and distribute this software and its
     54  * documentation for any purpose and without fee is hereby granted, provided
     55  * that the above copyright notice appear in all copies and that both that
     56  * copyright notice and this permission notice appear in supporting
     57  * documentation, and that the name NCR not be used in advertising
     58  * or publicity pertaining to distribution of the software without specific,
     59  * written prior permission.  NCR makes no representations about the
     60  * suitability of this software for any purpose.  It is provided "as is"
     61  * without express or implied warranty.
     62  *
     63  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     64  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
     65  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     66  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     67  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     68  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     69  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     70  */
     71 
     72 #include <ctype.h>
     73 #ifdef XTHREADS
     74 #include <X11/Xthreads.h>
     75 #endif
     76 
     77 #ifndef WIN32
     78 
     79 #if defined(TCPCONN) || defined(UNIXCONN)
     80 #include <sys/socket.h>
     81 #include <netinet/in.h>
     82 #include <arpa/inet.h>
     83 #endif
     84 
     85 #if defined(TCPCONN) || defined(UNIXCONN)
     86 #define X_INCLUDE_NETDB_H
     87 #define XOS_USE_NO_LOCKING
     88 #include <X11/Xos_r.h>
     89 #endif
     90 
     91 #ifdef UNIXCONN
     92 #ifndef X_NO_SYS_UN
     93 #include <sys/un.h>
     94 #endif
     95 #include <sys/stat.h>
     96 #endif
     97 
     98 
     99 #ifndef NO_TCP_H
    100 #if defined(linux) || defined(__GLIBC__)
    101 #include <sys/param.h>
    102 #endif /* osf */
    103 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
    104 #include <sys/param.h>
    105 #include <machine/endian.h>
    106 #endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
    107 #include <netinet/tcp.h>
    108 #endif /* !NO_TCP_H */
    109 
    110 #include <sys/ioctl.h>
    111 #if defined(SVR4) || defined(__SVR4)
    112 #include <sys/filio.h>
    113 #endif
    114 
    115 #include <unistd.h>
    116 
    117 #else /* !WIN32 */
    118 
    119 #include <X11/Xwinsock.h>
    120 #include <X11/Xwindows.h>
    121 #include <X11/Xw32defs.h>
    122 #undef close
    123 #define close closesocket
    124 #define ECONNREFUSED WSAECONNREFUSED
    125 #define EADDRINUSE WSAEADDRINUSE
    126 #define EPROTOTYPE WSAEPROTOTYPE
    127 #undef EWOULDBLOCK
    128 #define EWOULDBLOCK WSAEWOULDBLOCK
    129 #define EINPROGRESS WSAEINPROGRESS
    130 #undef EINTR
    131 #define EINTR WSAEINTR
    132 #define X_INCLUDE_NETDB_H
    133 #define XOS_USE_MTSAFE_NETDBAPI
    134 #include <X11/Xos_r.h>
    135 #endif /* WIN32 */
    136 
    137 #if defined(SO_DONTLINGER) && defined(SO_LINGER)
    138 #undef SO_DONTLINGER
    139 #endif
    140 
    141 /* others don't need this */
    142 #define SocketInitOnce() /**/
    143 
    144 #ifdef __linux__
    145 #define HAVE_ABSTRACT_SOCKETS
    146 #endif
    147 
    148 #define MIN_BACKLOG 128
    149 #ifdef SOMAXCONN
    150 #if SOMAXCONN > MIN_BACKLOG
    151 #define BACKLOG SOMAXCONN
    152 #endif
    153 #endif
    154 #ifndef BACKLOG
    155 #define BACKLOG MIN_BACKLOG
    156 #endif
    157 
    158 #if defined(IPv6) && !defined(AF_INET6)
    159 #error "Cannot build IPv6 support without AF_INET6"
    160 #endif
    161 
    162 /* Temporary workaround for consumers whose configure scripts were
    163    generated with pre-1.6 versions of xtrans.m4 */
    164 #if defined(IPv6) && !defined(HAVE_GETADDRINFO)
    165 #define HAVE_GETADDRINFO
    166 #endif
    167 
    168 /*
    169  * This is the Socket implementation of the X Transport service layer
    170  *
    171  * This file contains the implementation for both the UNIX and INET domains,
    172  * and can be built for either one, or both.
    173  *
    174  */
    175 
    176 typedef struct _Sockettrans2dev {
    177     const char	*transname;
    178     int		family;
    179     int		devcotsname;
    180     int		devcltsname;
    181     int		protocol;
    182 } Sockettrans2dev;
    183 
    184 /* As documented in the X(7) man page:
    185  *  tcp     TCP over IPv4 or IPv6
    186  *  inet    TCP over IPv4 only
    187  *  inet6   TCP over IPv6 only
    188  *  unix    UNIX Domain Sockets (same host only)
    189  *  local   Platform preferred local connection method
    190  */
    191 static Sockettrans2dev Sockettrans2devtab[] = {
    192 #ifdef TCPCONN
    193     {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
    194 #ifndef IPv6
    195     {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
    196 #else /* IPv6 */
    197     {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
    198     {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
    199     {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
    200 #endif
    201 #endif /* TCPCONN */
    202 #ifdef UNIXCONN
    203     {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
    204 #if !defined(LOCALCONN)
    205     {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
    206 #endif /* !LOCALCONN */
    207 #endif /* UNIXCONN */
    208 };
    209 
    210 #define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
    211 
    212 #ifdef TCPCONN
    213 static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
    214 #endif
    215 
    216 #if (defined(TCPCONN) && \
    217      (defined(TRANS_SERVER) || defined(X11_t) || !defined(HAVE_GETADDRINFO))) \
    218     || defined(TRANS_REOPEN)
    219 static int
    220 is_numeric (const char *str)
    221 {
    222     int i;
    223 
    224     for (i = 0; i < (int) strlen (str); i++)
    225 	if (!isdigit (str[i]))
    226 	    return (0);
    227 
    228     return (1);
    229 }
    230 #endif
    231 
    232 #ifdef UNIXCONN
    233 
    234 
    235 #if defined(X11_t)
    236 #define UNIX_PATH "/tmp/.X11-unix/X"
    237 #define UNIX_DIR "/tmp/.X11-unix"
    238 #endif /* X11_t */
    239 #if defined(XIM_t)
    240 #define UNIX_PATH "/tmp/.XIM-unix/XIM"
    241 #define UNIX_DIR "/tmp/.XIM-unix"
    242 #endif /* XIM_t */
    243 #if defined(FS_t) || defined(FONT_t)
    244 #define UNIX_PATH "/tmp/.font-unix/fs"
    245 #define UNIX_DIR "/tmp/.font-unix"
    246 #endif /* FS_t || FONT_t */
    247 #if defined(ICE_t)
    248 #define UNIX_PATH "/tmp/.ICE-unix/"
    249 #define UNIX_DIR "/tmp/.ICE-unix"
    250 #endif /* ICE_t */
    251 
    252 
    253 #endif /* UNIXCONN */
    254 
    255 #define PORTBUFSIZE	32
    256 
    257 #ifndef MAXHOSTNAMELEN
    258 #define MAXHOSTNAMELEN 255
    259 #endif
    260 
    261 #if defined(HAVE_SOCKLEN_T) || defined(IPv6)
    262 # define SOCKLEN_T socklen_t
    263 #elif defined(SVR4) || defined(__SVR4)
    264 # define SOCKLEN_T size_t
    265 #else
    266 # define SOCKLEN_T int
    267 #endif
    268 
    269 /*
    270  * These are some utility function used by the real interface function below.
    271  */
    272 
    273 static int
    274 TRANS(SocketSelectFamily) (int first, const char *family)
    275 
    276 {
    277     int     i;
    278 
    279     prmsg (3,"SocketSelectFamily(%s)\n", family);
    280 
    281     for (i = first + 1; i < (int)NUMSOCKETFAMILIES; i++)
    282     {
    283         if (!strcmp (family, Sockettrans2devtab[i].transname))
    284 	    return i;
    285     }
    286 
    287     return (first == -1 ? -2 : -1);
    288 }
    289 
    290 
    291 /*
    292  * This function gets the local address of the socket and stores it in the
    293  * XtransConnInfo structure for the connection.
    294  */
    295 
    296 static int
    297 TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
    298 
    299 {
    300 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
    301     struct sockaddr_storage sockname;
    302 #else
    303     struct sockaddr_in sockname;
    304 #endif
    305     void *socknamePtr = &sockname;
    306     SOCKLEN_T namelen = sizeof(sockname);
    307 
    308     prmsg (3,"SocketINETGetAddr(%p)\n", (void *) ciptr);
    309 
    310     bzero(socknamePtr, namelen);
    311 
    312     if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
    313 		     (void *)&namelen) < 0)
    314     {
    315 #ifdef WIN32
    316 	errno = WSAGetLastError();
    317 #endif
    318 	prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n",
    319 	    EGET());
    320 	return -1;
    321     }
    322 
    323     /*
    324      * Everything looks good: fill in the XtransConnInfo structure.
    325      */
    326 
    327     if ((ciptr->addr = malloc (namelen)) == NULL)
    328     {
    329         prmsg (1,
    330 	    "SocketINETGetAddr: Can't allocate space for the addr\n");
    331         return -1;
    332     }
    333 
    334     ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
    335     ciptr->addrlen = namelen;
    336     memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
    337 
    338     return 0;
    339 }
    340 
    341 
    342 /*
    343  * This function gets the remote address of the socket and stores it in the
    344  * XtransConnInfo structure for the connection.
    345  */
    346 
    347 static int
    348 TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
    349 
    350 {
    351 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
    352     struct sockaddr_storage sockname;
    353 #else
    354     struct sockaddr_in 	sockname;
    355 #endif
    356     void *socknamePtr = &sockname;
    357     SOCKLEN_T namelen = sizeof(sockname);
    358 
    359     bzero(socknamePtr, namelen);
    360 
    361     prmsg (3,"SocketINETGetPeerAddr(%p)\n", (void *) ciptr);
    362 
    363     if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
    364 		     (void *)&namelen) < 0)
    365     {
    366 #ifdef WIN32
    367 	errno = WSAGetLastError();
    368 #endif
    369 	prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
    370 	    EGET());
    371 	return -1;
    372     }
    373 
    374     /*
    375      * Everything looks good: fill in the XtransConnInfo structure.
    376      */
    377 
    378     if ((ciptr->peeraddr = malloc (namelen)) == NULL)
    379     {
    380         prmsg (1,
    381 	   "SocketINETGetPeerAddr: Can't allocate space for the addr\n");
    382         return -1;
    383     }
    384 
    385     ciptr->peeraddrlen = namelen;
    386     memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
    387 
    388     return 0;
    389 }
    390 
    391 
    392 static XtransConnInfo
    393 TRANS(SocketOpen) (int i, int type)
    394 
    395 {
    396     XtransConnInfo	ciptr;
    397 
    398     prmsg (3,"SocketOpen(%d,%d)\n", i, type);
    399 
    400     if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
    401     {
    402 	prmsg (1, "SocketOpen: malloc failed\n");
    403 	return NULL;
    404     }
    405 
    406     ciptr->fd = socket(Sockettrans2devtab[i].family, type,
    407                        Sockettrans2devtab[i].protocol);
    408 
    409 #ifndef WIN32
    410 #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
    411     if (ciptr->fd >= sysconf(_SC_OPEN_MAX))
    412     {
    413 	prmsg (2, "SocketOpen: socket() returned out of range fd %d\n",
    414 	       ciptr->fd);
    415 	close (ciptr->fd);
    416 	ciptr->fd = -1;
    417     }
    418 #endif
    419 #endif
    420 
    421     if (ciptr->fd < 0) {
    422 #ifdef WIN32
    423 	errno = WSAGetLastError();
    424 #endif
    425 	prmsg (2, "SocketOpen: socket() failed for %s\n",
    426 	    Sockettrans2devtab[i].transname);
    427 
    428 	free (ciptr);
    429 	return NULL;
    430     }
    431 
    432 #ifdef TCP_NODELAY
    433     if (Sockettrans2devtab[i].family == AF_INET
    434 #ifdef IPv6
    435       || Sockettrans2devtab[i].family == AF_INET6
    436 #endif
    437     )
    438     {
    439 	/*
    440 	 * turn off TCP coalescence for INET sockets
    441 	 */
    442 
    443 	int tmp = 1;
    444 	setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
    445 	    (char *) &tmp, sizeof (int));
    446     }
    447 #endif
    448 
    449     /*
    450      * Some systems provide a really small default buffer size for
    451      * UNIX sockets.  Bump it up a bit such that large transfers don't
    452      * proceed at glacial speed.
    453      */
    454 #ifdef SO_SNDBUF
    455     if (Sockettrans2devtab[i].family == AF_UNIX)
    456     {
    457 	SOCKLEN_T len = sizeof (int);
    458 	int val;
    459 
    460 	if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF,
    461 	    (char *) &val, &len) == 0 && val < 64 * 1024)
    462 	{
    463 	    val = 64 * 1024;
    464 	    setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF,
    465 	        (char *) &val, sizeof (int));
    466 	}
    467     }
    468 #endif
    469 
    470     return ciptr;
    471 }
    472 
    473 
    474 #ifdef TRANS_REOPEN
    475 
    476 static XtransConnInfo
    477 TRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port)
    478 
    479 {
    480     XtransConnInfo	ciptr;
    481     int portlen;
    482     struct sockaddr *addr;
    483     size_t addrlen;
    484 
    485     prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
    486 
    487     if (port == NULL) {
    488       prmsg (1, "SocketReopen: port was null!\n");
    489       return NULL;
    490     }
    491 
    492     portlen = strlen(port) + 1; // include space for trailing null
    493 #ifdef SOCK_MAXADDRLEN
    494     if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
    495       prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
    496       return NULL;
    497     }
    498     if (portlen < 14) portlen = 14;
    499 #else
    500     if (portlen < 0 || portlen > 14) {
    501       prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
    502       return NULL;
    503     }
    504 #endif /*SOCK_MAXADDRLEN*/
    505 
    506     if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
    507     {
    508 	prmsg (1, "SocketReopen: malloc(ciptr) failed\n");
    509 	return NULL;
    510     }
    511 
    512     ciptr->fd = fd;
    513 
    514     addrlen = portlen + offsetof(struct sockaddr, sa_data);
    515     if ((addr = calloc (1, addrlen)) == NULL) {
    516 	prmsg (1, "SocketReopen: malloc(addr) failed\n");
    517 	free (ciptr);
    518 	return NULL;
    519     }
    520     ciptr->addr = (char *) addr;
    521     ciptr->addrlen = addrlen;
    522 
    523     if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) {
    524 	prmsg (1, "SocketReopen: malloc(portaddr) failed\n");
    525 	free (addr);
    526 	free (ciptr);
    527 	return NULL;
    528     }
    529     ciptr->peeraddrlen = addrlen;
    530 
    531     /* Initialize ciptr structure as if it were a normally-opened unix socket */
    532     ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
    533 #ifdef BSD44SOCKETS
    534     addr->sa_len = addrlen;
    535 #endif
    536     addr->sa_family = AF_UNIX;
    537 #if defined(HAVE_STRLCPY) || defined(HAS_STRLCPY)
    538     strlcpy(addr->sa_data, port, portlen);
    539 #else
    540     strncpy(addr->sa_data, port, portlen);
    541 #endif
    542     ciptr->family = AF_UNIX;
    543     memcpy(ciptr->peeraddr, ciptr->addr, addrlen);
    544     ciptr->port = rindex(addr->sa_data, ':');
    545     if (ciptr->port == NULL) {
    546 	if (is_numeric(addr->sa_data)) {
    547 	    ciptr->port = addr->sa_data;
    548 	}
    549     } else if (ciptr->port[0] == ':') {
    550 	ciptr->port++;
    551     }
    552     /* port should now point to portnum or NULL */
    553     return ciptr;
    554 }
    555 
    556 #endif /* TRANS_REOPEN */
    557 
    558 
    559 /*
    560  * These functions are the interface supplied in the Xtransport structure
    561  */
    562 
    563 #ifdef TRANS_CLIENT
    564 
    565 static XtransConnInfo
    566 TRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol,
    567 			   const char *host, const char *port, int previndex)
    568 {
    569     XtransConnInfo	ciptr = NULL;
    570     int			i = previndex;
    571 
    572     prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
    573 	protocol, host, port);
    574 
    575     SocketInitOnce();
    576 
    577     while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
    578 	if ((ciptr = TRANS(SocketOpen) (
    579 		i, Sockettrans2devtab[i].devcotsname)) != NULL) {
    580 	    /* Save the index for later use */
    581 
    582 	    ciptr->index = i;
    583 	    break;
    584 	}
    585     }
    586     if (i < 0) {
    587 	if (i == -1)
    588 	    prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
    589 		   transname);
    590 	else
    591 	    prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
    592 		   transname);
    593 	return NULL;
    594     }
    595 
    596     return ciptr;
    597 }
    598 
    599 static XtransConnInfo
    600 TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol,
    601 			     const char *host, const char *port)
    602 {
    603     return TRANS(SocketOpenCOTSClientBase)(
    604 			thistrans->TransName, protocol, host, port, -1);
    605 }
    606 
    607 
    608 #endif /* TRANS_CLIENT */
    609 
    610 
    611 #ifdef TRANS_SERVER
    612 
    613 static XtransConnInfo
    614 TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol,
    615 			     const char *host, const char *port)
    616 
    617 {
    618     XtransConnInfo	ciptr = NULL;
    619     int	i = -1;
    620 
    621     prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
    622 
    623     SocketInitOnce();
    624 
    625     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
    626 	if ((ciptr = TRANS(SocketOpen) (
    627 		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
    628 	    break;
    629     }
    630     if (i < 0) {
    631 	if (i == -1) {
    632 		if (errno == EAFNOSUPPORT) {
    633 			thistrans->flags |= TRANS_NOLISTEN;
    634 			prmsg (1,"SocketOpenCOTSServer: Socket for %s unsupported on this system.\n",
    635 			       thistrans->TransName);
    636 		} else {
    637 			prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
    638 			       thistrans->TransName);
    639 		}
    640 	} else {
    641 	    prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
    642 		   thistrans->TransName);
    643 	}
    644 	return NULL;
    645     }
    646 
    647     /*
    648      * Using this prevents the bind() check for an existing server listening
    649      * on the same port, but it is required for other reasons.
    650      */
    651 #ifdef SO_REUSEADDR
    652 
    653     /*
    654      * SO_REUSEADDR only applied to AF_INET && AF_INET6
    655      */
    656 
    657     if (Sockettrans2devtab[i].family == AF_INET
    658 #ifdef IPv6
    659       || Sockettrans2devtab[i].family == AF_INET6
    660 #endif
    661     )
    662     {
    663 	int one = 1;
    664 	setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
    665 		    (char *) &one, sizeof (int));
    666     }
    667 #endif
    668 #ifdef IPV6_V6ONLY
    669     if (Sockettrans2devtab[i].family == AF_INET6)
    670     {
    671 	int one = 1;
    672 	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
    673     }
    674 #endif
    675     /* Save the index for later use */
    676 
    677     ciptr->index = i;
    678 
    679     return ciptr;
    680 }
    681 
    682 #endif /* TRANS_SERVER */
    683 
    684 
    685 #ifdef TRANS_REOPEN
    686 
    687 static XtransConnInfo
    688 TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port)
    689 
    690 {
    691     XtransConnInfo	ciptr;
    692     int			i = -1;
    693 
    694     prmsg (2,
    695 	"SocketReopenCOTSServer(%d, %s)\n", fd, port);
    696 
    697     SocketInitOnce();
    698 
    699     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
    700 	if ((ciptr = TRANS(SocketReopen) (
    701 		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
    702 	    break;
    703     }
    704     if (i < 0) {
    705 	if (i == -1)
    706 	    prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
    707 		   thistrans->TransName);
    708 	else
    709 	    prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
    710 		   thistrans->TransName);
    711 	return NULL;
    712     }
    713 
    714     /* Save the index for later use */
    715 
    716     ciptr->index = i;
    717 
    718     return ciptr;
    719 }
    720 
    721 #endif /* TRANS_REOPEN */
    722 
    723 
    724 static int
    725 TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
    726 
    727 {
    728     prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
    729 
    730     return -1;
    731 }
    732 
    733 #ifdef UNIXCONN
    734 static int
    735 set_sun_path(const char *port, const char *upath, char *path, int abstract)
    736 {
    737     struct sockaddr_un s;
    738     ssize_t maxlen = sizeof(s.sun_path) - 1;
    739     const char *at = "";
    740 
    741     if (!port || !*port || !path)
    742 	return -1;
    743 
    744 #ifdef HAVE_ABSTRACT_SOCKETS
    745     if (port[0] == '@')
    746 	upath = "";
    747     else if (abstract)
    748 	at = "@";
    749 #endif
    750 
    751     if (*port == '/') /* a full pathname */
    752 	upath = "";
    753 
    754     if ((ssize_t)(strlen(at) + strlen(upath) + strlen(port)) > maxlen)
    755 	return -1;
    756     snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port);
    757     return 0;
    758 }
    759 #endif
    760 
    761 #ifdef TRANS_SERVER
    762 
    763 static int
    764 TRANS(SocketCreateListener) (XtransConnInfo ciptr,
    765 			     struct sockaddr *sockname,
    766 			     int socknamelen, unsigned int flags)
    767 
    768 {
    769     SOCKLEN_T namelen = socknamelen;
    770     int	fd = ciptr->fd;
    771     int	retry;
    772 
    773     prmsg (3, "SocketCreateListener(%p,%d)\n", (void *) ciptr, fd);
    774 
    775     if (Sockettrans2devtab[ciptr->index].family == AF_INET
    776 #ifdef IPv6
    777       || Sockettrans2devtab[ciptr->index].family == AF_INET6
    778 #endif
    779 	)
    780 	retry = 20;
    781     else
    782 	retry = 0;
    783 
    784     while (bind (fd, sockname, namelen) < 0)
    785     {
    786 	if (errno == EADDRINUSE) {
    787 	    if (flags & ADDR_IN_USE_ALLOWED)
    788 		break;
    789 	    else
    790 		return TRANS_ADDR_IN_USE;
    791 	}
    792 
    793 	if (retry-- == 0) {
    794 	    prmsg (1, "SocketCreateListener: failed to bind listener\n");
    795 	    close (fd);
    796 	    return TRANS_CREATE_LISTENER_FAILED;
    797 	}
    798 #ifdef SO_REUSEADDR
    799 	sleep (1);
    800 #else
    801 	sleep (10);
    802 #endif /* SO_REUSEDADDR */
    803     }
    804 
    805     if (Sockettrans2devtab[ciptr->index].family == AF_INET
    806 #ifdef IPv6
    807       || Sockettrans2devtab[ciptr->index].family == AF_INET6
    808 #endif
    809 	) {
    810 #ifdef SO_DONTLINGER
    811 	setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
    812 #else
    813 #ifdef SO_LINGER
    814     {
    815 	static int linger[2] = { 0, 0 };
    816 	setsockopt (fd, SOL_SOCKET, SO_LINGER,
    817 		(char *) linger, sizeof (linger));
    818     }
    819 #endif
    820 #endif
    821 }
    822 
    823     if (listen (fd, BACKLOG) < 0)
    824     {
    825 	prmsg (1, "SocketCreateListener: listen() failed\n");
    826 	close (fd);
    827 	return TRANS_CREATE_LISTENER_FAILED;
    828     }
    829 
    830     /* Set a flag to indicate that this connection is a listener */
    831 
    832     ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
    833 
    834     return 0;
    835 }
    836 
    837 #ifdef TCPCONN
    838 static int
    839 TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port,
    840                                  unsigned int flags)
    841 
    842 {
    843 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
    844     struct sockaddr_storage sockname;
    845 #else
    846     struct sockaddr_in	    sockname;
    847 #endif
    848     unsigned short	    sport;
    849     SOCKLEN_T	namelen = sizeof(sockname);
    850     int		status;
    851     long	tmpport;
    852 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
    853     _Xgetservbynameparams sparams;
    854 #endif
    855     struct servent *servp;
    856 
    857 #ifdef X11_t
    858     char	portbuf[PORTBUFSIZE];
    859 #endif
    860 
    861     prmsg (2, "SocketINETCreateListener(%s)\n", port);
    862 
    863 #ifdef X11_t
    864     /*
    865      * X has a well known port, that is transport dependent. It is easier
    866      * to handle it here, than try and come up with a transport independent
    867      * representation that can be passed in and resolved the usual way.
    868      *
    869      * The port that is passed here is really a string containing the idisplay
    870      * from ConnectDisplay().
    871      */
    872 
    873     if (is_numeric (port))
    874     {
    875 	/* fixup the server port address */
    876 	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
    877 	snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
    878 	port = portbuf;
    879     }
    880 #endif
    881 
    882     if (port && *port)
    883     {
    884 	/* Check to see if the port string is just a number (handles X11) */
    885 
    886 	if (!is_numeric (port))
    887 	{
    888 	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
    889 	    {
    890 		prmsg (1,
    891 	     "SocketINETCreateListener: Unable to get service for %s\n",
    892 		      port);
    893 		return TRANS_CREATE_LISTENER_FAILED;
    894 	    }
    895 	    /* we trust getservbyname to return a valid number */
    896 	    sport = servp->s_port;
    897 	}
    898 	else
    899 	{
    900 	    tmpport = strtol (port, (char**)NULL, 10);
    901 	    /*
    902 	     * check that somehow the port address isn't negative or in
    903 	     * the range of reserved port addresses. This can happen and
    904 	     * be very bad if the server is suid-root and the user does
    905 	     * something (dumb) like `X :60049`.
    906 	     */
    907 	    if (tmpport < 1024 || tmpport > USHRT_MAX)
    908 		return TRANS_CREATE_LISTENER_FAILED;
    909 
    910 	    sport = (unsigned short) tmpport;
    911 	}
    912     }
    913     else
    914 	sport = 0;
    915 
    916     bzero(&sockname, sizeof(sockname));
    917     if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
    918 	namelen = sizeof (struct sockaddr_in);
    919 #ifdef BSD44SOCKETS
    920 	((struct sockaddr_in *)&sockname)->sin_len = namelen;
    921 #endif
    922 	((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
    923 	((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
    924 	((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
    925     } else {
    926 #ifdef IPv6
    927 	namelen = sizeof (struct sockaddr_in6);
    928 #ifdef SIN6_LEN
    929 	((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
    930 #endif
    931 	((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
    932 	((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
    933 	((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
    934 #else
    935         prmsg (1,
    936                "SocketINETCreateListener: unsupported address family %d\n",
    937                Sockettrans2devtab[ciptr->index].family);
    938         return TRANS_CREATE_LISTENER_FAILED;
    939 #endif
    940     }
    941 
    942     if ((status = TRANS(SocketCreateListener) (ciptr,
    943 	(struct sockaddr *) &sockname, namelen, flags)) < 0)
    944     {
    945 	prmsg (1,
    946     "SocketINETCreateListener: ...SocketCreateListener() failed\n");
    947 	return status;
    948     }
    949 
    950     if (TRANS(SocketINETGetAddr) (ciptr) < 0)
    951     {
    952 	prmsg (1,
    953        "SocketINETCreateListener: ...SocketINETGetAddr() failed\n");
    954 	return TRANS_CREATE_LISTENER_FAILED;
    955     }
    956 
    957     return 0;
    958 }
    959 
    960 #endif /* TCPCONN */
    961 
    962 
    963 #ifdef UNIXCONN
    964 
    965 static int
    966 TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port,
    967 				 unsigned int flags)
    968 
    969 {
    970     struct sockaddr_un	sockname;
    971     int			namelen;
    972     int			oldUmask;
    973     int			status;
    974     unsigned int	mode;
    975     char		tmpport[108];
    976 
    977     int			abstract = 0;
    978 #ifdef HAVE_ABSTRACT_SOCKETS
    979     abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
    980 #endif
    981 
    982     prmsg (2, "SocketUNIXCreateListener(%s)\n",
    983 	port ? port : "NULL");
    984 
    985     /* Make sure the directory is created */
    986 
    987     oldUmask = umask (0);
    988 
    989 #ifdef UNIX_DIR
    990 #ifdef HAS_STICKY_DIR_BIT
    991     mode = 01777;
    992 #else
    993     mode = 0777;
    994 #endif
    995     if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
    996 	prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
    997 	       UNIX_DIR, errno);
    998 	(void) umask (oldUmask);
    999 	return TRANS_CREATE_LISTENER_FAILED;
   1000     }
   1001 #endif
   1002 
   1003     memset(&sockname, 0, sizeof(sockname));
   1004     sockname.sun_family = AF_UNIX;
   1005 
   1006     if (!(port && *port)) {
   1007 	snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
   1008 	port = tmpport;
   1009     }
   1010     if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
   1011 	prmsg (1, "SocketUNIXCreateListener: path too long\n");
   1012 	return TRANS_CREATE_LISTENER_FAILED;
   1013     }
   1014 
   1015 #if defined(BSD44SOCKETS)
   1016     sockname.sun_len = strlen(sockname.sun_path);
   1017 #endif
   1018 
   1019 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
   1020     namelen = SUN_LEN(&sockname);
   1021 #else
   1022     namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
   1023 #endif
   1024 
   1025     if (abstract) {
   1026 	sockname.sun_path[0] = '\0';
   1027 	namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
   1028     }
   1029     else
   1030 	unlink (sockname.sun_path);
   1031 
   1032     if ((status = TRANS(SocketCreateListener) (ciptr,
   1033 	(struct sockaddr *) &sockname, namelen, flags)) < 0)
   1034     {
   1035 	prmsg (1,
   1036     "SocketUNIXCreateListener: ...SocketCreateListener() failed\n");
   1037 	(void) umask (oldUmask);
   1038 	return status;
   1039     }
   1040 
   1041     /*
   1042      * Now that the listener is esablished, create the addr info for
   1043      * this connection. getpeername() doesn't work for UNIX Domain Sockets
   1044      * on some systems (hpux at least), so we will just do it manually, instead
   1045      * of calling something like TRANS(SocketUNIXGetAddr).
   1046      */
   1047 
   1048     namelen = sizeof (sockname); /* this will always make it the same size */
   1049 
   1050     if ((ciptr->addr = malloc (namelen)) == NULL)
   1051     {
   1052         prmsg (1,
   1053         "SocketUNIXCreateListener: Can't allocate space for the addr\n");
   1054 	(void) umask (oldUmask);
   1055         return TRANS_CREATE_LISTENER_FAILED;
   1056     }
   1057 
   1058     if (abstract)
   1059 	sockname.sun_path[0] = '@';
   1060 
   1061     ciptr->family = sockname.sun_family;
   1062     ciptr->addrlen = namelen;
   1063     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
   1064 
   1065     (void) umask (oldUmask);
   1066 
   1067     return 0;
   1068 }
   1069 
   1070 
   1071 static int
   1072 TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
   1073 
   1074 {
   1075     /*
   1076      * See if the unix domain socket has disappeared.  If it has, recreate it.
   1077      */
   1078 
   1079     struct sockaddr_un 	*unsock = (struct sockaddr_un *) ciptr->addr;
   1080     struct stat		statb;
   1081     int 		status = TRANS_RESET_NOOP;
   1082     unsigned int	mode;
   1083     int abstract = 0;
   1084 #ifdef HAVE_ABSTRACT_SOCKETS
   1085     abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
   1086 #endif
   1087 
   1088     prmsg (3, "SocketUNIXResetListener(%p,%d)\n", (void *) ciptr, ciptr->fd);
   1089 
   1090     if (!abstract && (
   1091 	stat (unsock->sun_path, &statb) == -1 ||
   1092         ((statb.st_mode & S_IFMT) !=
   1093 #if !defined(S_IFSOCK)
   1094 	  		S_IFIFO
   1095 #else
   1096 			S_IFSOCK
   1097 #endif
   1098 				)))
   1099     {
   1100 	int oldUmask = umask (0);
   1101 
   1102 #ifdef UNIX_DIR
   1103 #ifdef HAS_STICKY_DIR_BIT
   1104 	mode = 01777;
   1105 #else
   1106 	mode = 0777;
   1107 #endif
   1108         if (trans_mkdir(UNIX_DIR, mode) == -1) {
   1109             prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
   1110 	    UNIX_DIR, errno);
   1111 	    (void) umask (oldUmask);
   1112 	    return TRANS_RESET_FAILURE;
   1113         }
   1114 #endif
   1115 
   1116 	close (ciptr->fd);
   1117 	unlink (unsock->sun_path);
   1118 
   1119 	if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
   1120 	{
   1121 	    TRANS(FreeConnInfo) (ciptr);
   1122 	    (void) umask (oldUmask);
   1123 	    return TRANS_RESET_FAILURE;
   1124 	}
   1125 
   1126 	if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
   1127 	{
   1128 	    close (ciptr->fd);
   1129 	    TRANS(FreeConnInfo) (ciptr);
   1130 	    return TRANS_RESET_FAILURE;
   1131 	}
   1132 
   1133 	if (listen (ciptr->fd, BACKLOG) < 0)
   1134 	{
   1135 	    close (ciptr->fd);
   1136 	    TRANS(FreeConnInfo) (ciptr);
   1137 	    (void) umask (oldUmask);
   1138 	    return TRANS_RESET_FAILURE;
   1139 	}
   1140 
   1141 	umask (oldUmask);
   1142 
   1143 	status = TRANS_RESET_NEW_FD;
   1144     }
   1145 
   1146     return status;
   1147 }
   1148 
   1149 #endif /* UNIXCONN */
   1150 
   1151 
   1152 #ifdef TCPCONN
   1153 
   1154 static XtransConnInfo
   1155 TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
   1156 
   1157 {
   1158     XtransConnInfo	newciptr;
   1159     struct sockaddr_in	sockname;
   1160     SOCKLEN_T		namelen = sizeof(sockname);
   1161 
   1162     prmsg (2, "SocketINETAccept(%p,%d)\n", (void *) ciptr, ciptr->fd);
   1163 
   1164     if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
   1165     {
   1166 	prmsg (1, "SocketINETAccept: malloc failed\n");
   1167 	*status = TRANS_ACCEPT_BAD_MALLOC;
   1168 	return NULL;
   1169     }
   1170 
   1171     if ((newciptr->fd = accept (ciptr->fd,
   1172 	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
   1173     {
   1174 #ifdef WIN32
   1175 	errno = WSAGetLastError();
   1176 #endif
   1177 	prmsg (1, "SocketINETAccept: accept() failed\n");
   1178 	free (newciptr);
   1179 	*status = TRANS_ACCEPT_FAILED;
   1180 	return NULL;
   1181     }
   1182 
   1183 #ifdef TCP_NODELAY
   1184     {
   1185 	/*
   1186 	 * turn off TCP coalescence for INET sockets
   1187 	 */
   1188 
   1189 	int tmp = 1;
   1190 	setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
   1191 	    (char *) &tmp, sizeof (int));
   1192     }
   1193 #endif
   1194 
   1195     /*
   1196      * Get this address again because the transport may give a more
   1197      * specific address now that a connection is established.
   1198      */
   1199 
   1200     if (TRANS(SocketINETGetAddr) (newciptr) < 0)
   1201     {
   1202 	prmsg (1,
   1203 	    "SocketINETAccept: ...SocketINETGetAddr() failed:\n");
   1204 	close (newciptr->fd);
   1205 	free (newciptr);
   1206 	*status = TRANS_ACCEPT_MISC_ERROR;
   1207         return NULL;
   1208     }
   1209 
   1210     if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
   1211     {
   1212 	prmsg (1,
   1213 	  "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n");
   1214 	close (newciptr->fd);
   1215 	if (newciptr->addr) free (newciptr->addr);
   1216 	free (newciptr);
   1217 	*status = TRANS_ACCEPT_MISC_ERROR;
   1218         return NULL;
   1219     }
   1220 
   1221     *status = 0;
   1222 
   1223     return newciptr;
   1224 }
   1225 
   1226 #endif /* TCPCONN */
   1227 
   1228 
   1229 #ifdef UNIXCONN
   1230 static XtransConnInfo
   1231 TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
   1232 
   1233 {
   1234     XtransConnInfo	newciptr;
   1235     struct sockaddr_un	sockname;
   1236     SOCKLEN_T 		namelen = sizeof sockname;
   1237 
   1238     prmsg (2, "SocketUNIXAccept(%p,%d)\n", (void *) ciptr, ciptr->fd);
   1239 
   1240     if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
   1241     {
   1242 	prmsg (1, "SocketUNIXAccept: malloc() failed\n");
   1243 	*status = TRANS_ACCEPT_BAD_MALLOC;
   1244 	return NULL;
   1245     }
   1246 
   1247     if ((newciptr->fd = accept (ciptr->fd,
   1248 	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
   1249     {
   1250 	prmsg (1, "SocketUNIXAccept: accept() failed\n");
   1251 	free (newciptr);
   1252 	*status = TRANS_ACCEPT_FAILED;
   1253 	return NULL;
   1254     }
   1255 
   1256 	ciptr->addrlen = namelen;
   1257     /*
   1258      * Get the socket name and the peer name from the listener socket,
   1259      * since this is unix domain.
   1260      */
   1261 
   1262     if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL)
   1263     {
   1264         prmsg (1,
   1265         "SocketUNIXAccept: Can't allocate space for the addr\n");
   1266 	close (newciptr->fd);
   1267 	free (newciptr);
   1268 	*status = TRANS_ACCEPT_BAD_MALLOC;
   1269         return NULL;
   1270     }
   1271 
   1272     /*
   1273      * if the socket is abstract, we already modified the address to have a
   1274      * @ instead of the initial NUL, so no need to do that again here.
   1275      */
   1276 
   1277     newciptr->addrlen = ciptr->addrlen;
   1278     memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
   1279 
   1280     if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL)
   1281     {
   1282         prmsg (1,
   1283 	      "SocketUNIXAccept: Can't allocate space for the addr\n");
   1284 	close (newciptr->fd);
   1285 	if (newciptr->addr) free (newciptr->addr);
   1286 	free (newciptr);
   1287 	*status = TRANS_ACCEPT_BAD_MALLOC;
   1288         return NULL;
   1289     }
   1290 
   1291     newciptr->peeraddrlen = ciptr->addrlen;
   1292     memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
   1293 
   1294     newciptr->family = AF_UNIX;
   1295 
   1296     *status = 0;
   1297 
   1298     return newciptr;
   1299 }
   1300 
   1301 #endif /* UNIXCONN */
   1302 
   1303 #endif /* TRANS_SERVER */
   1304 
   1305 
   1306 #ifdef TRANS_CLIENT
   1307 
   1308 #ifdef TCPCONN
   1309 
   1310 #ifdef HAVE_GETADDRINFO
   1311 struct addrlist {
   1312     struct addrinfo *	addr;
   1313     struct addrinfo *	firstaddr;
   1314     char 		port[PORTBUFSIZE];
   1315     char 		host[MAXHOSTNAMELEN];
   1316 };
   1317 static struct addrlist  *addrlist = NULL;
   1318 #endif
   1319 
   1320 
   1321 static int
   1322 TRANS(SocketINETConnect) (XtransConnInfo ciptr,
   1323                           const char *host, const char *port)
   1324 
   1325 {
   1326     struct sockaddr *	socketaddr = NULL;
   1327     int			socketaddrlen = 0;
   1328     int			res;
   1329 #ifdef HAVE_GETADDRINFO
   1330     struct addrinfo 	hints;
   1331     char		ntopbuf[INET6_ADDRSTRLEN];
   1332     int			resetonce = 0;
   1333 #else
   1334     struct sockaddr_in	sockname;
   1335     struct hostent	*hostp;
   1336     struct servent	*servp;
   1337     unsigned long 	tmpaddr;
   1338 #endif
   1339 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
   1340     _Xgethostbynameparams hparams;
   1341     _Xgetservbynameparams sparams;
   1342 #endif
   1343 #ifdef X11_t
   1344     char	portbuf[PORTBUFSIZE];
   1345 #endif
   1346 
   1347     char 		hostnamebuf[256];		/* tmp space */
   1348 
   1349     prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
   1350 
   1351     if (!host)
   1352     {
   1353 	hostnamebuf[0] = '\0';
   1354 	(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
   1355 	host = hostnamebuf;
   1356     }
   1357 
   1358 #ifdef X11_t
   1359     /*
   1360      * X has a well known port, that is transport dependent. It is easier
   1361      * to handle it here, than try and come up with a transport independent
   1362      * representation that can be passed in and resolved the usual way.
   1363      *
   1364      * The port that is passed here is really a string containing the idisplay
   1365      * from ConnectDisplay().
   1366      */
   1367 
   1368     if (is_numeric (port))
   1369     {
   1370 	long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
   1371 	snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
   1372 	port = portbuf;
   1373     }
   1374 #endif
   1375 
   1376 #ifdef HAVE_GETADDRINFO
   1377     {
   1378 	if (addrlist != NULL) {
   1379 	    if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
   1380 		if (addrlist->firstaddr)
   1381 		    freeaddrinfo(addrlist->firstaddr);
   1382 		addrlist->firstaddr = NULL;
   1383 	    }
   1384 	} else {
   1385 	    addrlist = malloc(sizeof(struct addrlist));
   1386 	    if (addrlist == NULL) {
   1387 		prmsg (1, "SocketINETConnect() can't allocate memory "
   1388 			"for addrlist: %s\n", strerror(errno));
   1389 		return TRANS_CONNECT_FAILED;
   1390 	    }
   1391 	    addrlist->firstaddr = NULL;
   1392 	}
   1393 
   1394 	if (addrlist->firstaddr == NULL) {
   1395 	    strncpy(addrlist->port, port, sizeof(addrlist->port));
   1396 	    addrlist->port[sizeof(addrlist->port) - 1] = '\0';
   1397 	    strncpy(addrlist->host, host, sizeof(addrlist->host));
   1398 	    addrlist->host[sizeof(addrlist->host) - 1] = '\0';
   1399 
   1400 	    bzero(&hints,sizeof(hints));
   1401 #ifdef IPv6
   1402 	    if (strcmp(Sockettrans2devtab[ciptr->index].transname, "tcp") == 0)
   1403 		hints.ai_family = AF_UNSPEC;
   1404 	    else
   1405 #endif
   1406 		hints.ai_family = Sockettrans2devtab[ciptr->index].family;
   1407 	    hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
   1408 
   1409 	    res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
   1410 	    if (res != 0) {
   1411 		prmsg (1, "SocketINETConnect() can't get address "
   1412 			"for %s:%s: %s\n", host, port, gai_strerror(res));
   1413 		ESET(EINVAL);
   1414 		return TRANS_CONNECT_FAILED;
   1415 	    }
   1416 	    for (res = 0, addrlist->addr = addrlist->firstaddr;
   1417 		 addrlist->addr ; res++) {
   1418 		addrlist->addr = addrlist->addr->ai_next;
   1419 	    }
   1420 	    prmsg(4,"Got New Address list with %d addresses\n", res);
   1421 	    res = 0;
   1422 	    addrlist->addr = NULL;
   1423 	}
   1424 
   1425 	while (socketaddr == NULL) {
   1426 	    if (addrlist->addr == NULL) {
   1427 		if (resetonce) {
   1428 		    /* Already checked entire list - no usable addresses */
   1429 		    prmsg (1, "SocketINETConnect() no usable address "
   1430 			   "for %s:%s\n", host, port);
   1431 		    return TRANS_CONNECT_FAILED;
   1432 		} else {
   1433 		    /* Go back to beginning of list */
   1434 		    resetonce = 1;
   1435 		    addrlist->addr = addrlist->firstaddr;
   1436 		}
   1437 	    }
   1438 
   1439 	    socketaddr = addrlist->addr->ai_addr;
   1440 	    socketaddrlen = addrlist->addr->ai_addrlen;
   1441 
   1442 	    if (addrlist->addr->ai_family == AF_INET) {
   1443 		struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
   1444 
   1445 		prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n",
   1446 			inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
   1447 			ntopbuf,sizeof(ntopbuf)));
   1448 
   1449 		prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n",
   1450 			ntohs(sin->sin_port));
   1451 
   1452 #ifdef IPv6
   1453 		if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
   1454 		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
   1455 				"tcp") == 0) {
   1456 			XtransConnInfo newciptr;
   1457 
   1458 			/*
   1459 			 * Our socket is an IPv6 socket, but the address is
   1460 			 * IPv4.  Close it and get an IPv4 socket.  This is
   1461 			 * needed for IPv4 connections to work on platforms
   1462 			 * that don't allow IPv4 over IPv6 sockets.
   1463 			 */
   1464 			TRANS(SocketINETClose)(ciptr);
   1465 			newciptr = TRANS(SocketOpenCOTSClientBase)(
   1466 					"tcp", "tcp", host, port, ciptr->index);
   1467 			if (newciptr)
   1468 			    ciptr->fd = newciptr->fd;
   1469 			if (!newciptr ||
   1470 			    Sockettrans2devtab[newciptr->index].family !=
   1471 				AF_INET) {
   1472 			    socketaddr = NULL;
   1473 			    prmsg (4,"SocketINETConnect() Cannot get IPv4 "
   1474 					" socketfor IPv4 address\n");
   1475 			}
   1476 			if (newciptr)
   1477 			    free(newciptr);
   1478 		    } else {
   1479 			socketaddr = NULL;
   1480 			prmsg (4,"SocketINETConnect Skipping IPv4 address\n");
   1481 		    }
   1482 		}
   1483 	    } else if (addrlist->addr->ai_family == AF_INET6) {
   1484 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
   1485 
   1486 		prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
   1487 			inet_ntop(addrlist->addr->ai_family,
   1488 				  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)));
   1489 		prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n",
   1490 			ntohs(sin6->sin6_port));
   1491 
   1492 		if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
   1493 		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
   1494 				"tcp") == 0) {
   1495 			XtransConnInfo newciptr;
   1496 
   1497 			/*
   1498 			 * Close the IPv4 socket and try to open an IPv6 socket.
   1499 			 */
   1500 			TRANS(SocketINETClose)(ciptr);
   1501 			newciptr = TRANS(SocketOpenCOTSClientBase)(
   1502 					"tcp", "tcp", host, port, -1);
   1503 			if (newciptr)
   1504 			    ciptr->fd = newciptr->fd;
   1505 			if (!newciptr ||
   1506 			    Sockettrans2devtab[newciptr->index].family !=
   1507 					AF_INET6) {
   1508 			    socketaddr = NULL;
   1509 			    prmsg (4,"SocketINETConnect() Cannot get IPv6 "
   1510 				   "socket for IPv6 address\n");
   1511 			}
   1512 			if (newciptr)
   1513 			    free(newciptr);
   1514 		    }
   1515 		    else
   1516 		    {
   1517 			socketaddr = NULL;
   1518 			prmsg (4,"SocketINETConnect() Skipping IPv6 address\n");
   1519 		    }
   1520 		}
   1521 #endif /* IPv6 */
   1522 	    } else {
   1523 		socketaddr = NULL; /* Unsupported address type */
   1524 	    }
   1525 	    if (socketaddr == NULL) {
   1526 		addrlist->addr = addrlist->addr->ai_next;
   1527 	    }
   1528 	}
   1529     }
   1530 #else /* !HAVE_GETADDRINFO */
   1531     {
   1532 	/*
   1533 	 * Build the socket name.
   1534 	 */
   1535 
   1536 #ifdef BSD44SOCKETS
   1537 	sockname.sin_len = sizeof (struct sockaddr_in);
   1538 #endif
   1539 	sockname.sin_family = AF_INET;
   1540 
   1541 	/*
   1542 	 * fill in sin_addr
   1543 	 */
   1544 
   1545 #ifndef INADDR_NONE
   1546 #define INADDR_NONE ((in_addr_t) 0xffffffff)
   1547 #endif
   1548 
   1549 	/* check for ww.xx.yy.zz host string */
   1550 
   1551 	if (isascii (host[0]) && isdigit (host[0])) {
   1552 	    tmpaddr = inet_addr (host); /* returns network byte order */
   1553 	} else {
   1554 	    tmpaddr = INADDR_NONE;
   1555 	}
   1556 
   1557 	prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr);
   1558 
   1559 	if (tmpaddr == INADDR_NONE) {
   1560 	    if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
   1561 		prmsg (1,"SocketINETConnect: Can't get address for %s\n",
   1562 			host);
   1563 		ESET(EINVAL);
   1564 		return TRANS_CONNECT_FAILED;
   1565 	    }
   1566 	    if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
   1567 		prmsg (1,"SocketINETConnect: not INET host%s\n", host);
   1568 		ESET(EPROTOTYPE);
   1569 		return TRANS_CONNECT_FAILED;
   1570 	    }
   1571 
   1572 	    memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
   1573 		    sizeof (sockname.sin_addr));
   1574 
   1575 	} else {
   1576 	    sockname.sin_addr.s_addr = tmpaddr;
   1577         }
   1578 
   1579 	/*
   1580 	 * fill in sin_port
   1581 	 */
   1582 
   1583 	/* Check for number in the port string */
   1584 
   1585 	if (!is_numeric (port)) {
   1586 	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
   1587 		prmsg (1,"SocketINETConnect: can't get service for %s\n",
   1588 			port);
   1589 		return TRANS_CONNECT_FAILED;
   1590 	    }
   1591 	    sockname.sin_port = htons (servp->s_port);
   1592 	} else {
   1593 	    long tmpport = strtol (port, (char**)NULL, 10);
   1594 	    if (tmpport < 1024 || tmpport > USHRT_MAX)
   1595 		return TRANS_CONNECT_FAILED;
   1596 	    sockname.sin_port = htons (((unsigned short) tmpport));
   1597 	}
   1598 
   1599 	prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n",
   1600 		ntohs(sockname.sin_port));
   1601 	socketaddr = (struct sockaddr *) &sockname;
   1602 	socketaddrlen = sizeof(sockname);
   1603     }
   1604 #endif
   1605 
   1606     /*
   1607      * Turn on socket keepalive so the client process will eventually
   1608      * be notified with a SIGPIPE signal if the display server fails
   1609      * to respond to a periodic transmission of messages
   1610      * on the connected socket.
   1611      * This is useful to avoid hung application processes when the
   1612      * processes are not spawned from the xdm session and
   1613      * the display server terminates abnormally.
   1614      * (Someone turned off the power switch.)
   1615      */
   1616 
   1617     {
   1618 	int tmp = 1;
   1619 	setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
   1620 		(char *) &tmp, sizeof (int));
   1621     }
   1622 
   1623     /*
   1624      * Do the connect()
   1625      */
   1626 
   1627     if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
   1628     {
   1629 #ifdef WIN32
   1630 	int olderrno = WSAGetLastError();
   1631 #else
   1632 	int olderrno = errno;
   1633 #endif
   1634 
   1635 	/*
   1636 	 * If the error was ECONNREFUSED, the server may be overloaded
   1637 	 * and we should try again.
   1638 	 *
   1639 	 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
   1640 	 * was non-blocking and we should poll using select
   1641 	 *
   1642 	 * If the error was EINTR, the connect was interrupted and we
   1643 	 * should try again.
   1644 	 *
   1645 	 * If multiple addresses are found for a host then we should
   1646 	 * try to connect again with a different address for a larger
   1647 	 * number of errors that made us quit before, since those
   1648 	 * could be caused by trying to use an IPv6 address to contact
   1649 	 * a machine with an IPv4-only server or other reasons that
   1650 	 * only affect one of a set of addresses.
   1651 	 */
   1652 
   1653 	if (olderrno == ECONNREFUSED || olderrno == EINTR
   1654 #ifdef HAVE_GETADDRINFO
   1655 	  || (((addrlist->addr->ai_next != NULL) ||
   1656 	        (addrlist->addr != addrlist->firstaddr)) &&
   1657                (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
   1658 		 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
   1659 #if defined(EHOSTDOWN)
   1660 		   || olderrno == EHOSTDOWN
   1661 #endif
   1662 	       ))
   1663 #endif
   1664 	    )
   1665 	    res = TRANS_TRY_CONNECT_AGAIN;
   1666 	else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
   1667 	    res = TRANS_IN_PROGRESS;
   1668 	else
   1669 	{
   1670 	    prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n",
   1671 		   olderrno);
   1672 
   1673 	    res = TRANS_CONNECT_FAILED;
   1674 	}
   1675     } else {
   1676 	res = 0;
   1677 
   1678 
   1679 	/*
   1680 	 * Sync up the address fields of ciptr.
   1681 	 */
   1682 
   1683 	if (TRANS(SocketINETGetAddr) (ciptr) < 0)
   1684 	{
   1685 	    prmsg (1,
   1686 	     "SocketINETConnect: ...SocketINETGetAddr() failed:\n");
   1687 	    res = TRANS_CONNECT_FAILED;
   1688 	}
   1689 
   1690 	else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
   1691 	{
   1692 	    prmsg (1,
   1693 	      "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n");
   1694 	    res = TRANS_CONNECT_FAILED;
   1695 	}
   1696     }
   1697 
   1698 #ifdef HAVE_GETADDRINFO
   1699    if (res != 0) {
   1700 	addrlist->addr = addrlist->addr->ai_next;
   1701    }
   1702 #endif
   1703 
   1704     return res;
   1705 }
   1706 
   1707 #endif /* TCPCONN */
   1708 
   1709 
   1710 
   1711 #ifdef UNIXCONN
   1713 
   1714 /*
   1715  * Make sure 'host' is really local.
   1716  */
   1717 
   1718 static int
   1719 UnixHostReallyLocal (const char *host)
   1720 
   1721 {
   1722     char hostnamebuf[256];
   1723 
   1724     TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
   1725 
   1726     if (strcmp (hostnamebuf, host) == 0)
   1727     {
   1728 	return (1);
   1729     } else {
   1730 #ifdef HAVE_GETADDRINFO
   1731 	struct addrinfo *localhostaddr;
   1732 	struct addrinfo *otherhostaddr;
   1733 	struct addrinfo *i, *j;
   1734 	int equiv = 0;
   1735 
   1736 	if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
   1737 	    return 0;
   1738 	if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
   1739 	    freeaddrinfo(localhostaddr);
   1740 	    return 0;
   1741 	}
   1742 
   1743 	for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
   1744 	    for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
   1745 		if (i->ai_family == j->ai_family) {
   1746 		    if (i->ai_family == AF_INET) {
   1747 			struct sockaddr_in *sinA
   1748 			  = (struct sockaddr_in *) i->ai_addr;
   1749 			struct sockaddr_in *sinB
   1750 			  = (struct sockaddr_in *) j->ai_addr;
   1751 			struct in_addr *A = &sinA->sin_addr;
   1752 			struct in_addr *B = &sinB->sin_addr;
   1753 
   1754 			if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
   1755 			    equiv = 1;
   1756 			}
   1757 #ifdef IPv6
   1758 		    } else if (i->ai_family == AF_INET6) {
   1759 			struct sockaddr_in6 *sinA
   1760 			  = (struct sockaddr_in6 *) i->ai_addr;
   1761 			struct sockaddr_in6 *sinB
   1762 			  = (struct sockaddr_in6 *) j->ai_addr;
   1763 			struct in6_addr *A = &sinA->sin6_addr;
   1764 			struct in6_addr *B = &sinB->sin6_addr;
   1765 
   1766 			if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
   1767 			    equiv = 1;
   1768 			}
   1769 #endif /* IPv6 */
   1770 		    }
   1771 		}
   1772 	    }
   1773 	}
   1774 
   1775 	freeaddrinfo(localhostaddr);
   1776 	freeaddrinfo(otherhostaddr);
   1777 	return equiv;
   1778 #else /* !HAVE_GETADDRINFO */
   1779 	/*
   1780 	 * A host may have more than one network address.  If any of the
   1781 	 * network addresses of 'host' (specified to the connect call)
   1782 	 * match any of the network addresses of 'hostname' (determined
   1783 	 * by TRANS(GetHostname)), then the two hostnames are equivalent,
   1784 	 * and we know that 'host' is really a local host.
   1785 	 */
   1786 	char specified_local_addr_list[10][4];
   1787 	int scount, equiv, i, j;
   1788 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
   1789 	_Xgethostbynameparams hparams;
   1790 #endif
   1791 	struct hostent *hostp;
   1792 
   1793 	if ((hostp = _XGethostbyname (host,hparams)) == NULL)
   1794 	    return (0);
   1795 
   1796 	scount = 0;
   1797 	while (hostp->h_addr_list[scount] && scount <= 8)
   1798 	{
   1799 	    /*
   1800 	     * The 2nd call to gethostname() overrides the data
   1801 	     * from the 1st call, so we must save the address list.
   1802 	     */
   1803 
   1804 	    specified_local_addr_list[scount][0] =
   1805 				hostp->h_addr_list[scount][0];
   1806 	    specified_local_addr_list[scount][1] =
   1807 				hostp->h_addr_list[scount][1];
   1808 	    specified_local_addr_list[scount][2] =
   1809 				hostp->h_addr_list[scount][2];
   1810 	    specified_local_addr_list[scount][3] =
   1811 				hostp->h_addr_list[scount][3];
   1812 	    scount++;
   1813 	}
   1814 	if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
   1815 	    return (0);
   1816 
   1817 	equiv = 0;
   1818 	i = 0;
   1819 
   1820 	while (i < scount && !equiv)
   1821 	{
   1822 	    j = 0;
   1823 
   1824 	    while (hostp->h_addr_list[j])
   1825 	    {
   1826 		if ((specified_local_addr_list[i][0] ==
   1827 					hostp->h_addr_list[j][0]) &&
   1828 		    (specified_local_addr_list[i][1] ==
   1829 					hostp->h_addr_list[j][1]) &&
   1830 		    (specified_local_addr_list[i][2] ==
   1831 					hostp->h_addr_list[j][2]) &&
   1832 		    (specified_local_addr_list[i][3] ==
   1833 					hostp->h_addr_list[j][3]))
   1834 		{
   1835 		    /* They're equal, so we're done */
   1836 
   1837 		    equiv = 1;
   1838 		    break;
   1839 		}
   1840 
   1841 		j++;
   1842 	    }
   1843 
   1844 	    i++;
   1845 	}
   1846 	return (equiv);
   1847 #endif
   1848     }
   1849 }
   1850 
   1851 static int
   1852 TRANS(SocketUNIXConnect) (XtransConnInfo ciptr,
   1853                           const char *host, const char *port)
   1854 
   1855 {
   1856     struct sockaddr_un	sockname;
   1857     SOCKLEN_T		namelen;
   1858 
   1859     prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
   1860 
   1861     /*
   1862      * Make sure 'host' is really local.  If not, we return failure.
   1863      * The reason we make this check is because a process may advertise
   1864      * a "local" network ID for which it can accept connections, but if
   1865      * a process on a remote machine tries to connect to this network ID,
   1866      * we know for sure it will fail.
   1867      */
   1868 
   1869     if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
   1870     {
   1871 	prmsg (1,
   1872 	   "SocketUNIXConnect: Cannot connect to non-local host %s\n",
   1873 	       host);
   1874 	return TRANS_CONNECT_FAILED;
   1875     }
   1876 
   1877 
   1878     /*
   1879      * Check the port.
   1880      */
   1881 
   1882     if (!port || !*port)
   1883     {
   1884 	prmsg (1,"SocketUNIXConnect: Missing port specification\n");
   1885 	return TRANS_CONNECT_FAILED;
   1886     }
   1887 
   1888     /*
   1889      * Build the socket name.
   1890      */
   1891 
   1892     sockname.sun_family = AF_UNIX;
   1893 
   1894     if (set_sun_path(port, UNIX_PATH, sockname.sun_path, 0) != 0) {
   1895 	prmsg (1, "SocketUNIXConnect: path too long\n");
   1896 	return TRANS_CONNECT_FAILED;
   1897     }
   1898 
   1899 #if defined(BSD44SOCKETS)
   1900     sockname.sun_len = strlen (sockname.sun_path);
   1901 #endif
   1902 
   1903 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
   1904     namelen = SUN_LEN (&sockname);
   1905 #else
   1906     namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
   1907 #endif
   1908 
   1909 
   1910     /*
   1911      * Do the connect()
   1912      */
   1913 
   1914     if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
   1915     {
   1916 	int olderrno = errno;
   1917 	int connected = 0;
   1918 
   1919 	if (!connected)
   1920 	{
   1921 	    errno = olderrno;
   1922 
   1923 	    /*
   1924 	     * If the error was ENOENT, the server may be starting up; we used
   1925 	     * to suggest to try again in this case with
   1926 	     * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
   1927 	     * processes still referencing stale sockets in their environment.
   1928 	     * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
   1929 	     * is suggested that higher level stacks handle retries on their
   1930 	     * level when they face a slow starting server.
   1931 	     *
   1932 	     * If the error was EWOULDBLOCK or EINPROGRESS then the socket
   1933 	     * was non-blocking and we should poll using select
   1934 	     *
   1935 	     * If the error was EINTR, the connect was interrupted and we
   1936 	     * should try again.
   1937 	     */
   1938 
   1939 	    if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
   1940 		return TRANS_IN_PROGRESS;
   1941 	    else if (olderrno == EINTR)
   1942 		return TRANS_TRY_CONNECT_AGAIN;
   1943 	    else {
   1944 		prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
   1945 		       EGET());
   1946 
   1947 		return TRANS_CONNECT_FAILED;
   1948 	    }
   1949 	}
   1950     }
   1951 
   1952     /*
   1953      * Get the socket name and the peer name from the connect socket,
   1954      * since this is unix domain.
   1955      */
   1956 
   1957     if ((ciptr->addr = malloc(namelen)) == NULL ||
   1958        (ciptr->peeraddr = malloc(namelen)) == NULL)
   1959     {
   1960         prmsg (1,
   1961 	"SocketUNIXCreateListener: Can't allocate space for the addr\n");
   1962         return TRANS_CONNECT_FAILED;
   1963     }
   1964 
   1965     ciptr->family = AF_UNIX;
   1966     ciptr->addrlen = namelen;
   1967     ciptr->peeraddrlen = namelen;
   1968     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
   1969     memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
   1970 
   1971     return 0;
   1972 }
   1973 
   1974 #endif /* UNIXCONN */
   1975 
   1976 #endif /* TRANS_CLIENT */
   1977 
   1978 
   1979 static int
   1980 TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
   1981 
   1982 {
   1983     prmsg (2,"SocketBytesReadable(%p,%d,%p)\n",
   1984 	(void *) ciptr, ciptr->fd, (void *) pend);
   1985 #ifdef WIN32
   1986     {
   1987 	int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
   1988 	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
   1989 	return ret;
   1990     }
   1991 #else
   1992     return ioctl (ciptr->fd, FIONREAD, (char *) pend);
   1993 #endif /* WIN32 */
   1994 }
   1995 
   1996 #if XTRANS_SEND_FDS
   1997 
   1998 static void
   1999 appendFd(struct _XtransConnFd **prev, int fd, int do_close)
   2000 {
   2001     struct _XtransConnFd *cf, *new;
   2002 
   2003     new = malloc (sizeof (struct _XtransConnFd));
   2004     if (!new) {
   2005         /* XXX mark connection as broken */
   2006         close(fd);
   2007         return;
   2008     }
   2009     new->next = 0;
   2010     new->fd = fd;
   2011     new->do_close = do_close;
   2012     /* search to end of list */
   2013     for (; (cf = *prev); prev = &(cf->next));
   2014     *prev = new;
   2015 }
   2016 
   2017 static int
   2018 removeFd(struct _XtransConnFd **prev)
   2019 {
   2020     struct _XtransConnFd *cf;
   2021     int fd;
   2022 
   2023     if ((cf = *prev)) {
   2024         *prev = cf->next;
   2025         fd = cf->fd;
   2026         free(cf);
   2027     } else
   2028         fd = -1;
   2029     return fd;
   2030 }
   2031 
   2032 static void
   2033 discardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close)
   2034 {
   2035     struct _XtransConnFd *cf, *next;
   2036 
   2037     for (cf = *prev; cf != upto; cf = next) {
   2038         next = cf->next;
   2039         if (do_close || cf->do_close)
   2040             close(cf->fd);
   2041         free(cf);
   2042     }
   2043     *prev = upto;
   2044 }
   2045 
   2046 static void
   2047 cleanupFds(XtransConnInfo ciptr)
   2048 {
   2049     /* Clean up the send list but don't close the fds */
   2050     discardFd(&ciptr->send_fds, NULL, 0);
   2051     /* Clean up the recv list and *do* close the fds */
   2052     discardFd(&ciptr->recv_fds, NULL, 1);
   2053 }
   2054 
   2055 static int
   2056 nFd(struct _XtransConnFd **prev)
   2057 {
   2058     struct _XtransConnFd *cf;
   2059     int n = 0;
   2060 
   2061     for (cf = *prev; cf; cf = cf->next)
   2062         n++;
   2063     return n;
   2064 }
   2065 
   2066 static int
   2067 TRANS(SocketRecvFd) (XtransConnInfo ciptr)
   2068 {
   2069     prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd);
   2070     return removeFd(&ciptr->recv_fds);
   2071 }
   2072 
   2073 static int
   2074 TRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close)
   2075 {
   2076     appendFd(&ciptr->send_fds, fd, do_close);
   2077     return 0;
   2078 }
   2079 
   2080 static int
   2081 TRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr)
   2082 {
   2083     errno = EINVAL;
   2084     return -1;
   2085 }
   2086 
   2087 static int
   2088 TRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
   2089 {
   2090     errno = EINVAL;
   2091     return -1;
   2092 }
   2093 
   2094 #define MAX_FDS		128
   2095 
   2096 union fd_pass {
   2097 	struct cmsghdr	cmsghdr;
   2098 	char		buf[CMSG_SPACE(MAX_FDS * sizeof(int))];
   2099 };
   2100 
   2101 #endif /* XTRANS_SEND_FDS */
   2102 
   2103 static int
   2104 TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
   2105 
   2106 {
   2107     prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, (void *) buf, size);
   2108 
   2109 #if defined(WIN32)
   2110     {
   2111 	int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
   2112 #ifdef WIN32
   2113 	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
   2114 #endif
   2115 	return ret;
   2116     }
   2117 #else
   2118 #if XTRANS_SEND_FDS
   2119     {
   2120         struct iovec    iov = {
   2121             .iov_base = buf,
   2122             .iov_len = size
   2123         };
   2124         union fd_pass   cmsgbuf;
   2125         struct msghdr   msg = {
   2126             .msg_name = NULL,
   2127             .msg_namelen = 0,
   2128             .msg_iov = &iov,
   2129             .msg_iovlen = 1,
   2130             .msg_control = cmsgbuf.buf,
   2131             .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
   2132         };
   2133 
   2134         size = recvmsg(ciptr->fd, &msg, 0);
   2135         if (size >= 0) {
   2136             struct cmsghdr *hdr;
   2137 
   2138             for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
   2139                 if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
   2140                     int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
   2141                     int i;
   2142                     int *fd = (int *) CMSG_DATA(hdr);
   2143 
   2144                     for (i = 0; i < nfd; i++)
   2145                         appendFd(&ciptr->recv_fds, fd[i], 0);
   2146                 }
   2147             }
   2148         }
   2149         return size;
   2150     }
   2151 #else
   2152     return read(ciptr->fd, buf, size);
   2153 #endif /* XTRANS_SEND_FDS */
   2154 #endif /* WIN32 */
   2155 }
   2156 
   2157 static int
   2158 TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
   2159 
   2160 {
   2161     prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, (void *) buf, size);
   2162 
   2163 #if XTRANS_SEND_FDS
   2164     {
   2165         union fd_pass   cmsgbuf;
   2166         struct msghdr   msg = {
   2167             .msg_name = NULL,
   2168             .msg_namelen = 0,
   2169             .msg_iov = buf,
   2170             .msg_iovlen = size,
   2171             .msg_control = cmsgbuf.buf,
   2172             .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
   2173         };
   2174 
   2175         size = recvmsg(ciptr->fd, &msg, 0);
   2176         if (size >= 0) {
   2177             struct cmsghdr *hdr;
   2178 
   2179             for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
   2180                 if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
   2181                     int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
   2182                     int i;
   2183                     int *fd = (int *) CMSG_DATA(hdr);
   2184 
   2185                     for (i = 0; i < nfd; i++)
   2186                         appendFd(&ciptr->recv_fds, fd[i], 0);
   2187                 }
   2188             }
   2189         }
   2190         return size;
   2191     }
   2192 #else
   2193     return READV (ciptr, buf, size);
   2194 #endif
   2195 }
   2196 
   2197 
   2198 static int
   2199 TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
   2200 
   2201 {
   2202     prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, (void *) buf, size);
   2203 
   2204 #if XTRANS_SEND_FDS
   2205     if (ciptr->send_fds)
   2206     {
   2207         union fd_pass           cmsgbuf;
   2208         int                     nfd = nFd(&ciptr->send_fds);
   2209         struct _XtransConnFd    *cf = ciptr->send_fds;
   2210         struct msghdr           msg = {
   2211             .msg_name = NULL,
   2212             .msg_namelen = 0,
   2213             .msg_iov = buf,
   2214             .msg_iovlen = size,
   2215             .msg_control = cmsgbuf.buf,
   2216             .msg_controllen = CMSG_LEN(nfd * sizeof(int))
   2217         };
   2218         struct cmsghdr          *hdr = CMSG_FIRSTHDR(&msg);
   2219         int                     i;
   2220         int                     *fds;
   2221 
   2222         hdr->cmsg_len = msg.msg_controllen;
   2223         hdr->cmsg_level = SOL_SOCKET;
   2224         hdr->cmsg_type = SCM_RIGHTS;
   2225 
   2226         fds = (int *) CMSG_DATA(hdr);
   2227         /* Set up fds */
   2228         for (i = 0; i < nfd; i++) {
   2229             fds[i] = cf->fd;
   2230             cf = cf->next;
   2231         }
   2232 
   2233         i = sendmsg(ciptr->fd, &msg, 0);
   2234         if (i > 0)
   2235             discardFd(&ciptr->send_fds, cf, 0);
   2236         return i;
   2237     }
   2238 #endif
   2239     return WRITEV (ciptr, buf, size);
   2240 }
   2241 
   2242 
   2243 static int
   2244 TRANS(SocketWrite) (XtransConnInfo ciptr, const char *buf, int size)
   2245 
   2246 {
   2247     prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, (const void *) buf, size);
   2248 
   2249 #if defined(WIN32)
   2250     {
   2251 	int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
   2252 #ifdef WIN32
   2253 	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
   2254 #endif
   2255 	return ret;
   2256     }
   2257 #else
   2258 #if XTRANS_SEND_FDS
   2259     if (ciptr->send_fds)
   2260     {
   2261         struct iovec            iov;
   2262 
   2263         iov.iov_base = (void *) buf;
   2264         iov.iov_len = size;
   2265         return TRANS(SocketWritev)(ciptr, &iov, 1);
   2266     }
   2267 #endif /* XTRANS_SEND_FDS */
   2268     return write (ciptr->fd, buf, size);
   2269 #endif /* WIN32 */
   2270 }
   2271 
   2272 static int
   2273 TRANS(SocketDisconnect) (XtransConnInfo ciptr)
   2274 
   2275 {
   2276     prmsg (2,"SocketDisconnect(%p,%d)\n", (void *) ciptr, ciptr->fd);
   2277 
   2278 #ifdef WIN32
   2279     {
   2280 	int ret = shutdown (ciptr->fd, 2);
   2281 	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
   2282 	return ret;
   2283     }
   2284 #else
   2285     return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
   2286 #endif
   2287 }
   2288 
   2289 
   2290 #ifdef TCPCONN
   2291 static int
   2292 TRANS(SocketINETClose) (XtransConnInfo ciptr)
   2293 
   2294 {
   2295     prmsg (2,"SocketINETClose(%p,%d)\n", (void *) ciptr, ciptr->fd);
   2296 
   2297 #ifdef WIN32
   2298     {
   2299 	int ret = close (ciptr->fd);
   2300 	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
   2301 	return ret;
   2302     }
   2303 #else
   2304     return close (ciptr->fd);
   2305 #endif
   2306 }
   2307 
   2308 #endif /* TCPCONN */
   2309 
   2310 
   2311 #ifdef UNIXCONN
   2312 static int
   2313 TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
   2314 {
   2315     /*
   2316      * If this is the server side, then once the socket is closed,
   2317      * it must be unlinked to completely close it
   2318      */
   2319 
   2320     struct sockaddr_un	*sockname = (struct sockaddr_un *) ciptr->addr;
   2321     int ret;
   2322 
   2323     prmsg (2,"SocketUNIXClose(%p,%d)\n", (void *) ciptr, ciptr->fd);
   2324 
   2325 #if XTRANS_SEND_FDS
   2326     cleanupFds(ciptr);
   2327 #endif
   2328     ret = close(ciptr->fd);
   2329 
   2330     if (ciptr->flags
   2331        && sockname
   2332        && sockname->sun_family == AF_UNIX
   2333        && sockname->sun_path[0])
   2334     {
   2335 	if (!(ciptr->flags & TRANS_NOUNLINK
   2336 	    || ciptr->transptr->flags & TRANS_ABSTRACT))
   2337 		unlink (sockname->sun_path);
   2338     }
   2339 
   2340     return ret;
   2341 }
   2342 
   2343 static int
   2344 TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
   2345 
   2346 {
   2347     /*
   2348      * Don't unlink path.
   2349      */
   2350 
   2351     int ret;
   2352 
   2353     prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n",
   2354 	(void *) ciptr, ciptr->fd);
   2355 
   2356 #if XTRANS_SEND_FDS
   2357     cleanupFds(ciptr);
   2358 #endif
   2359     ret = close(ciptr->fd);
   2360 
   2361     return ret;
   2362 }
   2363 
   2364 #endif /* UNIXCONN */
   2365 
   2366 
   2367 #ifdef TCPCONN
   2368 # ifdef TRANS_SERVER
   2369 static const char* tcp_nolisten[] = {
   2370 	"inet",
   2371 #ifdef IPv6
   2372 	"inet6",
   2373 #endif
   2374 	NULL
   2375 };
   2376 # endif
   2377 
   2378 static Xtransport	TRANS(SocketTCPFuncs) = {
   2379 	/* Socket Interface */
   2380 	"tcp",
   2381         TRANS_ALIAS,
   2382 #ifdef TRANS_CLIENT
   2383 	TRANS(SocketOpenCOTSClient),
   2384 #endif /* TRANS_CLIENT */
   2385 #ifdef TRANS_SERVER
   2386 	tcp_nolisten,
   2387 	TRANS(SocketOpenCOTSServer),
   2388 #endif /* TRANS_SERVER */
   2389 #ifdef TRANS_REOPEN
   2390 	TRANS(SocketReopenCOTSServer),
   2391 #endif
   2392 	TRANS(SocketSetOption),
   2393 #ifdef TRANS_SERVER
   2394 	TRANS(SocketINETCreateListener),
   2395 	NULL,		       			/* ResetListener */
   2396 	TRANS(SocketINETAccept),
   2397 #endif /* TRANS_SERVER */
   2398 #ifdef TRANS_CLIENT
   2399 	TRANS(SocketINETConnect),
   2400 #endif /* TRANS_CLIENT */
   2401 	TRANS(SocketBytesReadable),
   2402 	TRANS(SocketRead),
   2403 	TRANS(SocketWrite),
   2404 	TRANS(SocketReadv),
   2405 	TRANS(SocketWritev),
   2406 #if XTRANS_SEND_FDS
   2407         TRANS(SocketSendFdInvalid),
   2408         TRANS(SocketRecvFdInvalid),
   2409 #endif
   2410 	TRANS(SocketDisconnect),
   2411 	TRANS(SocketINETClose),
   2412 	TRANS(SocketINETClose),
   2413 	};
   2414 
   2415 static Xtransport	TRANS(SocketINETFuncs) = {
   2416 	/* Socket Interface */
   2417 	"inet",
   2418 	0,
   2419 #ifdef TRANS_CLIENT
   2420 	TRANS(SocketOpenCOTSClient),
   2421 #endif /* TRANS_CLIENT */
   2422 #ifdef TRANS_SERVER
   2423 	NULL,
   2424 	TRANS(SocketOpenCOTSServer),
   2425 #endif /* TRANS_SERVER */
   2426 #ifdef TRANS_REOPEN
   2427 	TRANS(SocketReopenCOTSServer),
   2428 #endif
   2429 	TRANS(SocketSetOption),
   2430 #ifdef TRANS_SERVER
   2431 	TRANS(SocketINETCreateListener),
   2432 	NULL,		       			/* ResetListener */
   2433 	TRANS(SocketINETAccept),
   2434 #endif /* TRANS_SERVER */
   2435 #ifdef TRANS_CLIENT
   2436 	TRANS(SocketINETConnect),
   2437 #endif /* TRANS_CLIENT */
   2438 	TRANS(SocketBytesReadable),
   2439 	TRANS(SocketRead),
   2440 	TRANS(SocketWrite),
   2441 	TRANS(SocketReadv),
   2442 	TRANS(SocketWritev),
   2443 #if XTRANS_SEND_FDS
   2444         TRANS(SocketSendFdInvalid),
   2445         TRANS(SocketRecvFdInvalid),
   2446 #endif
   2447 	TRANS(SocketDisconnect),
   2448 	TRANS(SocketINETClose),
   2449 	TRANS(SocketINETClose),
   2450 	};
   2451 
   2452 #ifdef IPv6
   2453 static Xtransport     TRANS(SocketINET6Funcs) = {
   2454 	/* Socket Interface */
   2455 	"inet6",
   2456 	0,
   2457 #ifdef TRANS_CLIENT
   2458 	TRANS(SocketOpenCOTSClient),
   2459 #endif /* TRANS_CLIENT */
   2460 #ifdef TRANS_SERVER
   2461 	NULL,
   2462 	TRANS(SocketOpenCOTSServer),
   2463 #endif /* TRANS_SERVER */
   2464 #ifdef TRANS_REOPEN
   2465 	TRANS(SocketReopenCOTSServer),
   2466 #endif
   2467 	TRANS(SocketSetOption),
   2468 #ifdef TRANS_SERVER
   2469 	TRANS(SocketINETCreateListener),
   2470 	NULL,					/* ResetListener */
   2471 	TRANS(SocketINETAccept),
   2472 #endif /* TRANS_SERVER */
   2473 #ifdef TRANS_CLIENT
   2474 	TRANS(SocketINETConnect),
   2475 #endif /* TRANS_CLIENT */
   2476 	TRANS(SocketBytesReadable),
   2477 	TRANS(SocketRead),
   2478 	TRANS(SocketWrite),
   2479 	TRANS(SocketReadv),
   2480 	TRANS(SocketWritev),
   2481 #if XTRANS_SEND_FDS
   2482         TRANS(SocketSendFdInvalid),
   2483         TRANS(SocketRecvFdInvalid),
   2484 #endif
   2485 	TRANS(SocketDisconnect),
   2486 	TRANS(SocketINETClose),
   2487 	TRANS(SocketINETClose),
   2488 	};
   2489 #endif /* IPv6 */
   2490 #endif /* TCPCONN */
   2491 
   2492 #ifdef UNIXCONN
   2493 #if !defined(LOCALCONN)
   2494 static Xtransport	TRANS(SocketLocalFuncs) = {
   2495 	/* Socket Interface */
   2496 	"local",
   2497 #ifdef HAVE_ABSTRACT_SOCKETS
   2498 	TRANS_ABSTRACT,
   2499 #else
   2500 	0,
   2501 #endif
   2502 #ifdef TRANS_CLIENT
   2503 	TRANS(SocketOpenCOTSClient),
   2504 #endif /* TRANS_CLIENT */
   2505 #ifdef TRANS_SERVER
   2506 	NULL,
   2507 	TRANS(SocketOpenCOTSServer),
   2508 #endif /* TRANS_SERVER */
   2509 #ifdef TRANS_REOPEN
   2510 	TRANS(SocketReopenCOTSServer),
   2511 #endif
   2512 	TRANS(SocketSetOption),
   2513 #ifdef TRANS_SERVER
   2514 	TRANS(SocketUNIXCreateListener),
   2515 	TRANS(SocketUNIXResetListener),
   2516 	TRANS(SocketUNIXAccept),
   2517 #endif /* TRANS_SERVER */
   2518 #ifdef TRANS_CLIENT
   2519 	TRANS(SocketUNIXConnect),
   2520 #endif /* TRANS_CLIENT */
   2521 	TRANS(SocketBytesReadable),
   2522 	TRANS(SocketRead),
   2523 	TRANS(SocketWrite),
   2524 	TRANS(SocketReadv),
   2525 	TRANS(SocketWritev),
   2526 #if XTRANS_SEND_FDS
   2527         TRANS(SocketSendFd),
   2528         TRANS(SocketRecvFd),
   2529 #endif
   2530 	TRANS(SocketDisconnect),
   2531 	TRANS(SocketUNIXClose),
   2532 	TRANS(SocketUNIXCloseForCloning),
   2533 	};
   2534 #endif /* !LOCALCONN */
   2535 # ifdef TRANS_SERVER
   2536 #  if !defined(LOCALCONN)
   2537 static const char* unix_nolisten[] = { "local" , NULL };
   2538 #  endif
   2539 # endif
   2540 
   2541 static Xtransport	TRANS(SocketUNIXFuncs) = {
   2542 	/* Socket Interface */
   2543 	"unix",
   2544 #if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
   2545         TRANS_ALIAS,
   2546 #else
   2547 	0,
   2548 #endif
   2549 #ifdef TRANS_CLIENT
   2550 	TRANS(SocketOpenCOTSClient),
   2551 #endif /* TRANS_CLIENT */
   2552 #ifdef TRANS_SERVER
   2553 #if !defined(LOCALCONN)
   2554 	unix_nolisten,
   2555 #else
   2556 	NULL,
   2557 #endif
   2558 	TRANS(SocketOpenCOTSServer),
   2559 #endif /* TRANS_SERVER */
   2560 #ifdef TRANS_REOPEN
   2561 	TRANS(SocketReopenCOTSServer),
   2562 #endif
   2563 	TRANS(SocketSetOption),
   2564 #ifdef TRANS_SERVER
   2565 	TRANS(SocketUNIXCreateListener),
   2566 	TRANS(SocketUNIXResetListener),
   2567 	TRANS(SocketUNIXAccept),
   2568 #endif /* TRANS_SERVER */
   2569 #ifdef TRANS_CLIENT
   2570 	TRANS(SocketUNIXConnect),
   2571 #endif /* TRANS_CLIENT */
   2572 	TRANS(SocketBytesReadable),
   2573 	TRANS(SocketRead),
   2574 	TRANS(SocketWrite),
   2575 	TRANS(SocketReadv),
   2576 	TRANS(SocketWritev),
   2577 #if XTRANS_SEND_FDS
   2578         TRANS(SocketSendFd),
   2579         TRANS(SocketRecvFd),
   2580 #endif
   2581 	TRANS(SocketDisconnect),
   2582 	TRANS(SocketUNIXClose),
   2583 	TRANS(SocketUNIXCloseForCloning),
   2584 	};
   2585 
   2586 #endif /* UNIXCONN */
   2587