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