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