2 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
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:
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
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.
25 Copyright 1993, 1994, 1998 The Open Group
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
33 The above copyright notice and this permission notice shall be included
34 in all copies or substantial portions of the Software.
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.
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.
49 * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
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.
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.
74 #include <X11/Xthreads.h>
79 #if defined(TCPCONN) || defined(UNIXCONN)
80 #include <sys/socket.h>
81 #include <netinet/in.h>
82 #include <arpa/inet.h>
85 #if defined(TCPCONN) || defined(UNIXCONN)
86 #define X_INCLUDE_NETDB_H
87 #define XOS_USE_NO_LOCKING
88 #include <X11/Xos_r.h>
100 #if defined(linux) || defined(__GLIBC__)
101 #include <sys/param.h>
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 */
110 #include <sys/ioctl.h>
111 #if defined(SVR4) || defined(__SVR4)
112 #include <sys/filio.h>
115 #if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
116 #include <net/errno.h>
119 #if defined(__i386__) && defined(SYSV)
120 #include <sys/stropts.h>
127 #include <X11/Xwinsock.h>
128 #include <X11/Xwindows.h>
129 #include <X11/Xw32defs.h>
131 #define close closesocket
132 #define ECONNREFUSED WSAECONNREFUSED
133 #define EADDRINUSE WSAEADDRINUSE
134 #define EPROTOTYPE WSAEPROTOTYPE
136 #define EWOULDBLOCK WSAEWOULDBLOCK
137 #define EINPROGRESS WSAEINPROGRESS
139 #define EINTR WSAEINTR
140 #define X_INCLUDE_NETDB_H
141 #define XOS_USE_MTSAFE_NETDBAPI
142 #include <X11/Xos_r.h>
145 #if defined(SO_DONTLINGER) && defined(SO_LINGER)
149 /* others don't need this */
150 #define SocketInitOnce() /**/
153 #define HAVE_ABSTRACT_SOCKETS
156 #define MIN_BACKLOG 128
158 #if SOMAXCONN > MIN_BACKLOG
159 #define BACKLOG SOMAXCONN
163 #define BACKLOG MIN_BACKLOG
167 * This is the Socket implementation of the X Transport service layer
169 * This file contains the implementation for both the UNIX and INET domains,
170 * and can be built for either one, or both.
174 typedef struct _Sockettrans2dev {
182 static Sockettrans2dev Sockettrans2devtab[] = {
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},
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},
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 */
201 #define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
204 static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
211 #define UNIX_PATH "/tmp/.X11-unix/X"
212 #define UNIX_DIR "/tmp/.X11-unix"
215 #define UNIX_PATH "/tmp/.XIM-unix/XIM"
216 #define UNIX_DIR "/tmp/.XIM-unix"
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 */
223 #define UNIX_PATH "/tmp/.ICE-unix/"
224 #define UNIX_DIR "/tmp/.ICE-unix"
227 #define UNIX_PATH "/tmp/.Test-unix/test"
228 #define UNIX_DIR "/tmp/.Test-unix"
230 #if defined(LBXPROXY_t)
231 #define UNIX_PATH "/tmp/.X11-unix/X"
232 #define UNIX_DIR "/tmp/.X11-unix"
236 #endif /* UNIXCONN */
238 #define PORTBUFSIZE 32
240 #ifndef MAXHOSTNAMELEN
241 #define MAXHOSTNAMELEN 255
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
249 # define SOCKLEN_T int
253 * These are some utility function used by the real interface function below.
257 TRANS(SocketSelectFamily) (int first, char *family)
262 PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
264 for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
266 if (!strcmp (family, Sockettrans2devtab[i].transname))
270 return (first == -1 ? -2 : -1);
275 * This function gets the local address of the socket and stores it in the
276 * XtransConnInfo structure for the connection.
280 TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
283 #if defined(IPv6) && defined(AF_INET6)
284 struct sockaddr_storage socknamev6;
286 struct sockaddr_in socknamev4;
291 PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
293 #if defined(IPv6) && defined(AF_INET6)
294 namelen = sizeof(socknamev6);
295 socknamePtr = &socknamev6;
297 namelen = sizeof(socknamev4);
298 socknamePtr = &socknamev4;
301 bzero(socknamePtr, namelen);
303 if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
304 (void *)&namelen) < 0)
307 errno = WSAGetLastError();
309 PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
315 * Everything looks good: fill in the XtransConnInfo structure.
318 if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
321 "SocketINETGetAddr: Can't allocate space for the addr\n",
326 #if defined(IPv6) && defined(AF_INET6)
327 ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
329 ciptr->family = socknamev4.sin_family;
331 ciptr->addrlen = namelen;
332 memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
339 * This function gets the remote address of the socket and stores it in the
340 * XtransConnInfo structure for the connection.
344 TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
347 #if defined(IPv6) && defined(AF_INET6)
348 struct sockaddr_storage socknamev6;
350 struct sockaddr_in socknamev4;
354 #if defined(IPv6) && defined(AF_INET6)
355 if (ciptr->family == AF_INET6)
357 namelen = sizeof(socknamev6);
358 socknamePtr = &socknamev6;
363 namelen = sizeof(socknamev4);
364 socknamePtr = &socknamev4;
367 bzero(socknamePtr, namelen);
369 PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
371 if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
372 (void *)&namelen) < 0)
375 errno = WSAGetLastError();
377 PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
383 * Everything looks good: fill in the XtransConnInfo structure.
386 if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
389 "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
394 ciptr->peeraddrlen = namelen;
395 memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
401 static XtransConnInfo
402 TRANS(SocketOpen) (int i, int type)
405 XtransConnInfo ciptr;
407 PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
409 if ((ciptr = (XtransConnInfo) xcalloc (
410 1, sizeof(struct _XtransConnInfo))) == NULL)
412 PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
416 if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
417 Sockettrans2devtab[i].protocol)) < 0
419 #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
420 || ciptr->fd >= sysconf(_SC_OPEN_MAX)
425 errno = WSAGetLastError();
427 PRMSG (2, "SocketOpen: socket() failed for %s\n",
428 Sockettrans2devtab[i].transname, 0, 0);
430 xfree ((char *) ciptr);
435 if (Sockettrans2devtab[i].family == AF_INET
436 #if defined(IPv6) && defined(AF_INET6)
437 || Sockettrans2devtab[i].family == AF_INET6
442 * turn off TCP coalescence for INET sockets
446 setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
447 (char *) &tmp, sizeof (int));
457 static XtransConnInfo
458 TRANS(SocketReopen) (int i, int type, int fd, char *port)
461 XtransConnInfo ciptr;
463 struct sockaddr *addr;
465 PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
468 PRMSG (1, "SocketReopen: port was null!\n", 0, 0, 0);
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);
478 if (portlen < 14) portlen = 14;
480 if (portlen < 0 || portlen > 14) {
481 PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0);
484 #endif /*SOCK_MAXADDRLEN*/
486 if ((ciptr = (XtransConnInfo) xcalloc (
487 1, sizeof(struct _XtransConnInfo))) == NULL)
489 PRMSG (1, "SocketReopen: malloc(ciptr) failed\n", 0, 0, 0);
495 if ((addr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) {
496 PRMSG (1, "SocketReopen: malloc(addr) failed\n", 0, 0, 0);
499 ciptr->addr = (char *) addr;
500 ciptr->addrlen = portlen + 2;
502 if ((ciptr->peeraddr = (char *) xcalloc (1, portlen + 2)) == NULL) {
503 PRMSG (1, "SocketReopen: malloc(portaddr) failed\n", 0, 0, 0);
506 ciptr->peeraddrlen = portlen + 2;
508 /* Initialize ciptr structure as if it were a normally-opened unix socket */
509 ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
511 addr->sa_len = portlen + 1;
513 addr->sa_family = AF_UNIX;
515 strlcpy(addr->sa_data, port, portlen);
517 strncpy(addr->sa_data, port, portlen);
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;
526 } else if (ciptr->port[0] == ':') {
529 /* port should now point to portnum or NULL */
533 #endif /* TRANS_REOPEN */
537 * These functions are the interface supplied in the Xtransport structure
542 static XtransConnInfo
543 TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
544 char *host, char *port, int previndex)
546 XtransConnInfo ciptr;
549 PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
550 protocol, host, port);
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 */
565 PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
568 PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
576 static XtransConnInfo
577 TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
578 char *host, char *port)
580 return TRANS(SocketOpenCOTSClientBase)(
581 thistrans->TransName, protocol, host, port, -1);
585 #endif /* TRANS_CLIENT */
590 static XtransConnInfo
591 TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
592 char *host, char *port)
595 XtransConnInfo ciptr;
598 PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
602 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
603 if ((ciptr = TRANS(SocketOpen) (
604 i, Sockettrans2devtab[i].devcotsname)) != NULL)
609 PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
610 thistrans->TransName, 0, 0);
612 PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
613 thistrans->TransName, 0, 0);
618 * Using this prevents the bind() check for an existing server listening
619 * on the same port, but it is required for other reasons.
624 * SO_REUSEADDR only applied to AF_INET && AF_INET6
627 if (Sockettrans2devtab[i].family == AF_INET
628 #if defined(IPv6) && defined(AF_INET6)
629 || Sockettrans2devtab[i].family == AF_INET6
634 setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
635 (char *) &one, sizeof (int));
639 if (Sockettrans2devtab[i].family == AF_INET6)
642 setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
645 /* Save the index for later use */
652 #endif /* TRANS_SERVER */
657 static XtransConnInfo
658 TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
659 char *host, char *port)
662 XtransConnInfo ciptr;
665 PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
669 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
670 if ((ciptr = TRANS(SocketOpen) (
671 i, Sockettrans2devtab[i].devcotsname)) != NULL)
676 PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
677 thistrans->TransName, 0, 0);
679 PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
680 thistrans->TransName, 0, 0);
684 /* Save the index for later use */
691 #endif /* TRANS_CLIENT */
696 static XtransConnInfo
697 TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
698 char *host, char *port)
701 XtransConnInfo ciptr;
704 PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
708 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
709 if ((ciptr = TRANS(SocketOpen) (
710 i, Sockettrans2devtab[i].devcotsname)) != NULL)
715 PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
716 thistrans->TransName, 0, 0);
718 PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
719 thistrans->TransName, 0, 0);
724 if (Sockettrans2devtab[i].family == AF_INET6)
727 setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
730 /* Save the index for later use */
737 #endif /* TRANS_SERVER */
742 static XtransConnInfo
743 TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
746 XtransConnInfo ciptr;
750 "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
754 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
755 if ((ciptr = TRANS(SocketReopen) (
756 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
761 PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
762 thistrans->TransName, 0, 0);
764 PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
765 thistrans->TransName, 0, 0);
769 /* Save the index for later use */
776 static XtransConnInfo
777 TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
780 XtransConnInfo ciptr;
784 "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
788 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
789 if ((ciptr = TRANS(SocketReopen) (
790 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
795 PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
796 thistrans->TransName, 0, 0);
798 PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
799 thistrans->TransName, 0, 0);
803 /* Save the index for later use */
810 #endif /* TRANS_REOPEN */
814 TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
817 PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
824 set_sun_path(const char *port, const char *upath, char *path, int abstract)
826 struct sockaddr_un s;
827 int maxlen = sizeof(s.sun_path) - 1;
830 if (!port || !*port || !path)
833 #ifdef HAVE_ABSTRACT_SOCKETS
840 if (*port == '/') /* a full pathname */
843 if (strlen(port) + strlen(upath) > maxlen)
845 sprintf(path, "%s%s%s", at, upath, port);
853 TRANS(SocketCreateListener) (XtransConnInfo ciptr,
854 struct sockaddr *sockname,
855 int socknamelen, unsigned int flags)
858 SOCKLEN_T namelen = socknamelen;
862 PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
864 if (Sockettrans2devtab[ciptr->index].family == AF_INET
865 #if defined(IPv6) && defined(AF_INET6)
866 || Sockettrans2devtab[ciptr->index].family == AF_INET6
873 while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
875 if (errno == EADDRINUSE) {
876 if (flags & ADDR_IN_USE_ALLOWED)
879 return TRANS_ADDR_IN_USE;
883 PRMSG (1, "SocketCreateListener: failed to bind listener\n",
886 return TRANS_CREATE_LISTENER_FAILED;
892 #endif /* SO_REUSEDADDR */
895 if (Sockettrans2devtab[ciptr->index].family == AF_INET
896 #if defined(IPv6) && defined(AF_INET6)
897 || Sockettrans2devtab[ciptr->index].family == AF_INET6
901 setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
905 static int linger[2] = { 0, 0 };
906 setsockopt (fd, SOL_SOCKET, SO_LINGER,
907 (char *) linger, sizeof (linger));
913 if (listen (fd, BACKLOG) < 0)
915 PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
917 return TRANS_CREATE_LISTENER_FAILED;
920 /* Set a flag to indicate that this connection is a listener */
922 ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
929 TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
932 #if defined(IPv6) && defined(AF_INET6)
933 struct sockaddr_storage sockname;
935 struct sockaddr_in sockname;
937 unsigned short sport;
938 SOCKLEN_T namelen = sizeof(sockname);
941 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
942 _Xgetservbynameparams sparams;
944 struct servent *servp;
947 char portbuf[PORTBUFSIZE];
950 PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
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.
958 * The port that is passed here is really a string containing the idisplay
959 * from ConnectDisplay().
962 if (is_numeric (port))
964 /* fixup the server port address */
965 tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
966 sprintf (portbuf,"%lu", tmpport);
973 /* Check to see if the port string is just a number (handles X11) */
975 if (!is_numeric (port))
977 if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
980 "SocketINETCreateListener: Unable to get service for %s\n",
982 return TRANS_CREATE_LISTENER_FAILED;
984 /* we trust getservbyname to return a valid number */
985 sport = servp->s_port;
989 tmpport = strtol (port, (char**)NULL, 10);
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`.
996 if (tmpport < 1024 || tmpport > USHRT_MAX)
997 return TRANS_CREATE_LISTENER_FAILED;
999 sport = (unsigned short) tmpport;
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);
1010 ((struct sockaddr_in *)&sockname)->sin_len = namelen;
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);
1016 namelen = sizeof (struct sockaddr_in6);
1018 ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
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;
1026 sockname.sin_len = sizeof (sockname);
1028 sockname.sin_family = AF_INET;
1029 sockname.sin_port = htons (sport);
1030 sockname.sin_addr.s_addr = htonl (INADDR_ANY);
1033 if ((status = TRANS(SocketCreateListener) (ciptr,
1034 (struct sockaddr *) &sockname, namelen, flags)) < 0)
1037 "SocketINETCreateListener: ...SocketCreateListener() failed\n",
1042 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1045 "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
1047 return TRANS_CREATE_LISTENER_FAILED;
1053 #endif /* TCPCONN */
1059 TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
1063 struct sockaddr_un sockname;
1071 #ifdef HAVE_ABSTRACT_SOCKETS
1072 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1075 PRMSG (2, "SocketUNIXCreateListener(%s)\n",
1076 port ? port : "NULL", 0, 0);
1078 /* Make sure the directory is created */
1080 oldUmask = umask (0);
1083 #ifdef HAS_STICKY_DIR_BIT
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;
1096 memset(&sockname, 0, sizeof(sockname));
1097 sockname.sun_family = AF_UNIX;
1099 if (!(port && *port)) {
1100 snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
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;
1108 #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
1109 sockname.sun_len = strlen(sockname.sun_path);
1112 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1113 namelen = SUN_LEN(&sockname);
1115 namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
1119 sockname.sun_path[0] = '\0';
1120 namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
1123 unlink (sockname.sun_path);
1125 if ((status = TRANS(SocketCreateListener) (ciptr,
1126 (struct sockaddr *) &sockname, namelen, flags)) < 0)
1129 "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
1131 (void) umask (oldUmask);
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).
1142 namelen = sizeof (sockname); /* this will always make it the same size */
1144 if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
1147 "SocketUNIXCreateListener: Can't allocate space for the addr\n",
1149 (void) umask (oldUmask);
1150 return TRANS_CREATE_LISTENER_FAILED;
1154 sockname.sun_path[0] = '@';
1156 ciptr->family = sockname.sun_family;
1157 ciptr->addrlen = namelen;
1158 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
1160 (void) umask (oldUmask);
1167 TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
1171 * See if the unix domain socket has disappeared. If it has, recreate it.
1174 struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
1176 int status = TRANS_RESET_NOOP;
1179 #ifdef HAVE_ABSTRACT_SOCKETS
1180 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1183 PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
1186 stat (unsock->sun_path, &statb) == -1 ||
1187 ((statb.st_mode & S_IFMT) !=
1188 #if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
1195 int oldUmask = umask (0);
1198 #ifdef HAS_STICKY_DIR_BIT
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;
1212 unlink (unsock->sun_path);
1214 if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
1216 TRANS(FreeConnInfo) (ciptr);
1217 (void) umask (oldUmask);
1218 return TRANS_RESET_FAILURE;
1221 if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
1224 TRANS(FreeConnInfo) (ciptr);
1225 return TRANS_RESET_FAILURE;
1228 if (listen (ciptr->fd, BACKLOG) < 0)
1231 TRANS(FreeConnInfo) (ciptr);
1232 (void) umask (oldUmask);
1233 return TRANS_RESET_FAILURE;
1238 status = TRANS_RESET_NEW_FD;
1244 #endif /* UNIXCONN */
1249 static XtransConnInfo
1250 TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
1253 XtransConnInfo newciptr;
1254 struct sockaddr_in sockname;
1255 SOCKLEN_T namelen = sizeof(sockname);
1257 PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
1259 if ((newciptr = (XtransConnInfo) xcalloc (
1260 1, sizeof(struct _XtransConnInfo))) == NULL)
1262 PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
1263 *status = TRANS_ACCEPT_BAD_MALLOC;
1267 if ((newciptr->fd = accept (ciptr->fd,
1268 (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
1271 errno = WSAGetLastError();
1273 PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
1275 *status = TRANS_ACCEPT_FAILED;
1282 * turn off TCP coalescence for INET sockets
1286 setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
1287 (char *) &tmp, sizeof (int));
1292 * Get this address again because the transport may give a more
1293 * specific address now that a connection is established.
1296 if (TRANS(SocketINETGetAddr) (newciptr) < 0)
1299 "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
1301 close (newciptr->fd);
1303 *status = TRANS_ACCEPT_MISC_ERROR;
1307 if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
1310 "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
1312 close (newciptr->fd);
1313 if (newciptr->addr) xfree (newciptr->addr);
1315 *status = TRANS_ACCEPT_MISC_ERROR;
1324 #endif /* TCPCONN */
1328 static XtransConnInfo
1329 TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
1332 XtransConnInfo newciptr;
1333 struct sockaddr_un sockname;
1334 SOCKLEN_T namelen = sizeof sockname;
1336 PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
1338 if ((newciptr = (XtransConnInfo) xcalloc (
1339 1, sizeof(struct _XtransConnInfo))) == NULL)
1341 PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
1342 *status = TRANS_ACCEPT_BAD_MALLOC;
1346 if ((newciptr->fd = accept (ciptr->fd,
1347 (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
1349 PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
1351 *status = TRANS_ACCEPT_FAILED;
1355 ciptr->addrlen = namelen;
1357 * Get the socket name and the peer name from the listener socket,
1358 * since this is unix domain.
1361 if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
1364 "SocketUNIXAccept: Can't allocate space for the addr\n",
1366 close (newciptr->fd);
1368 *status = TRANS_ACCEPT_BAD_MALLOC;
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.
1377 newciptr->addrlen = ciptr->addrlen;
1378 memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
1380 if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
1383 "SocketUNIXAccept: Can't allocate space for the addr\n",
1385 close (newciptr->fd);
1386 if (newciptr->addr) xfree (newciptr->addr);
1388 *status = TRANS_ACCEPT_BAD_MALLOC;
1392 newciptr->peeraddrlen = ciptr->addrlen;
1393 memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
1395 newciptr->family = AF_UNIX;
1402 #endif /* UNIXCONN */
1404 #endif /* TRANS_SERVER */
1411 #if defined(IPv6) && defined(AF_INET6)
1413 struct addrinfo * addr;
1414 struct addrinfo * firstaddr;
1415 char port[PORTBUFSIZE];
1416 char host[MAXHOSTNAMELEN];
1418 static struct addrlist *addrlist = NULL;
1423 TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
1426 struct sockaddr * socketaddr = NULL;
1427 int socketaddrlen = 0;
1429 #if defined(IPv6) && defined(AF_INET6)
1430 struct addrinfo hints;
1431 char ntopbuf[INET6_ADDRSTRLEN];
1434 struct sockaddr_in sockname;
1435 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1436 _Xgethostbynameparams hparams;
1437 _Xgetservbynameparams sparams;
1439 struct hostent *hostp;
1440 struct servent *servp;
1441 unsigned long tmpaddr;
1443 char portbuf[PORTBUFSIZE];
1447 char hostnamebuf[256]; /* tmp space */
1449 PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1453 hostnamebuf[0] = '\0';
1454 (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
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.
1464 * The port that is passed here is really a string containing the idisplay
1465 * from ConnectDisplay().
1468 if (is_numeric (port))
1470 tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1471 sprintf (portbuf, "%lu", tmpport);
1476 #if defined(IPv6) && defined(AF_INET6)
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;
1485 addrlist = malloc(sizeof(struct addrlist));
1486 addrlist->firstaddr = NULL;
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';
1495 bzero(&hints,sizeof(hints));
1496 hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
1498 res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
1500 PRMSG (1, "SocketINETConnect() can't get address "
1501 "for %s:%s: %s\n", host, port, gai_strerror(res));
1503 return TRANS_CONNECT_FAILED;
1505 for (res = 0, addrlist->addr = addrlist->firstaddr;
1506 addrlist->addr ; res++) {
1507 addrlist->addr = addrlist->addr->ai_next;
1509 PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
1511 addrlist->addr = NULL;
1514 while (socketaddr == NULL) {
1515 if (addrlist->addr == NULL) {
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;
1522 /* Go back to beginning of list */
1524 addrlist->addr = addrlist->firstaddr;
1528 socketaddr = addrlist->addr->ai_addr;
1529 socketaddrlen = addrlist->addr->ai_addrlen;
1531 if (addrlist->addr->ai_family == AF_INET) {
1532 struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
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);
1538 PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
1539 ntohs(sin->sin_port), 0, 0);
1541 if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
1542 if (strcmp(Sockettrans2devtab[ciptr->index].transname,
1544 XtransConnInfo newciptr;
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.
1552 TRANS(SocketINETClose)(ciptr);
1553 newciptr = TRANS(SocketOpenCOTSClientBase)(
1554 "tcp", "tcp", host, port, ciptr->index);
1556 ciptr->fd = newciptr->fd;
1558 Sockettrans2devtab[newciptr->index].family !=
1561 PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
1562 " socketfor IPv4 address\n", 0,0,0);
1568 PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
1572 } else if (addrlist->addr->ai_family == AF_INET6) {
1573 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
1575 PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
1576 inet_ntop(addrlist->addr->ai_family,
1577 &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
1579 PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
1580 ntohs(sin6->sin6_port), 0, 0);
1582 if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
1583 if (strcmp(Sockettrans2devtab[ciptr->index].transname,
1585 XtransConnInfo newciptr;
1588 * Close the IPv4 socket and try to open an IPv6 socket.
1590 TRANS(SocketINETClose)(ciptr);
1591 newciptr = TRANS(SocketOpenCOTSClientBase)(
1592 "tcp", "tcp", host, port, -1);
1594 ciptr->fd = newciptr->fd;
1596 Sockettrans2devtab[newciptr->index].family !=
1599 PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
1600 "socket for IPv6 address\n", 0,0,0);
1608 PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
1613 socketaddr = NULL; /* Unsupported address type */
1615 if (socketaddr == NULL) {
1616 addrlist->addr = addrlist->addr->ai_next;
1623 * Build the socket name.
1627 sockname.sin_len = sizeof (struct sockaddr_in);
1629 sockname.sin_family = AF_INET;
1636 #define INADDR_NONE ((in_addr_t) 0xffffffff)
1639 /* check for ww.xx.yy.zz host string */
1641 if (isascii (host[0]) && isdigit (host[0])) {
1642 tmpaddr = inet_addr (host); /* returns network byte order */
1644 tmpaddr = INADDR_NONE;
1647 PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
1649 if (tmpaddr == INADDR_NONE) {
1650 if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
1651 PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
1654 return TRANS_CONNECT_FAILED;
1656 if (hostp->h_addrtype != AF_INET) { /* is IP host? */
1657 PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
1659 return TRANS_CONNECT_FAILED;
1662 memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
1663 sizeof (sockname.sin_addr));
1666 sockname.sin_addr.s_addr = tmpaddr;
1673 /* Check for number in the port string */
1675 if (!is_numeric (port)) {
1676 if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
1677 PRMSG (1,"SocketINETConnect: can't get service for %s\n",
1679 return TRANS_CONNECT_FAILED;
1681 sockname.sin_port = htons (servp->s_port);
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));
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);
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.)
1709 setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
1710 (char *) &tmp, sizeof (int));
1717 if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
1720 int olderrno = WSAGetLastError();
1722 int olderrno = errno;
1726 * If the error was ECONNREFUSED, the server may be overloaded
1727 * and we should try again.
1729 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
1730 * was non-blocking and we should poll using select
1732 * If the error was EINTR, the connect was interrupted and we
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.
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
1755 res = TRANS_TRY_CONNECT_AGAIN;
1756 else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
1757 res = TRANS_IN_PROGRESS;
1760 PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
1763 res = TRANS_CONNECT_FAILED;
1770 * Sync up the address fields of ciptr.
1773 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1776 "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
1778 res = TRANS_CONNECT_FAILED;
1781 else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
1784 "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
1786 res = TRANS_CONNECT_FAILED;
1790 #if defined(IPv6) && defined(AF_INET6)
1792 addrlist->addr = addrlist->addr->ai_next;
1799 #endif /* TCPCONN */
1806 * Make sure 'host' is really local.
1810 UnixHostReallyLocal (char *host)
1813 char hostnamebuf[256];
1815 TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
1817 if (strcmp (hostnamebuf, host) == 0)
1821 #if defined(IPv6) && defined(AF_INET6)
1822 struct addrinfo *localhostaddr;
1823 struct addrinfo *otherhostaddr;
1824 struct addrinfo *i, *j;
1827 if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
1829 if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
1830 freeaddrinfo(localhostaddr);
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;
1845 if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
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;
1856 if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
1864 freeaddrinfo(localhostaddr);
1865 freeaddrinfo(otherhostaddr);
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.
1875 char specified_local_addr_list[10][4];
1876 int scount, equiv, i, j;
1877 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1878 _Xgethostbynameparams hparams;
1880 struct hostent *hostp;
1882 if ((hostp = _XGethostbyname (host,hparams)) == NULL)
1886 while (hostp->h_addr_list[scount] && scount <= 8)
1889 * The 2nd call to gethostname() overrides the data
1890 * from the 1st call, so we must save the address list.
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];
1903 if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
1909 while (i < scount && !equiv)
1913 while (hostp->h_addr_list[j])
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]))
1924 /* They're equal, so we're done */
1941 TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
1944 struct sockaddr_un sockname;
1949 #ifdef HAVE_ABSTRACT_SOCKETS
1950 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1953 PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
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.
1963 if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
1966 "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1968 return TRANS_CONNECT_FAILED;
1976 if (!port || !*port)
1978 PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
1980 return TRANS_CONNECT_FAILED;
1984 * Build the socket name.
1987 sockname.sun_family = AF_UNIX;
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;
1994 #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
1995 sockname.sun_len = strlen (sockname.sun_path);
1998 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1999 namelen = SUN_LEN (&sockname);
2001 namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
2007 * Adjust the socket path if using abstract sockets.
2008 * Done here because otherwise all the strlen() calls above would fail.
2012 sockname.sun_path[0] = '\0';
2019 if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
2021 int olderrno = errno;
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.
2037 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
2038 * was non-blocking and we should poll using select
2040 * If the error was EINTR, the connect was interrupted and we
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 */
2051 ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
2052 return TRANS_TRY_CONNECT_AGAIN;
2054 return TRANS_CONNECT_FAILED;
2057 PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
2060 return TRANS_CONNECT_FAILED;
2066 * Get the socket name and the peer name from the connect socket,
2067 * since this is unix domain.
2070 if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
2071 (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
2074 "SocketUNIXCreateListener: Can't allocate space for the addr\n",
2076 return TRANS_CONNECT_FAILED;
2080 sockname.sun_path[0] = '@';
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);
2091 #endif /* UNIXCONN */
2093 #endif /* TRANS_CLIENT */
2097 TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
2100 PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
2101 ciptr, ciptr->fd, pend);
2104 int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
2105 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2109 #if defined(__i386__) && defined(SYSV) && !defined(SCO325)
2110 return ioctl (ciptr->fd, I_NREAD, (char *) pend);
2112 return ioctl (ciptr->fd, FIONREAD, (char *) pend);
2113 #endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
2119 TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
2122 PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
2126 int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
2128 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2133 return read (ciptr->fd, buf, size);
2139 TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
2142 PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
2146 int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
2148 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2153 return write (ciptr->fd, buf, size);
2159 TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
2162 PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
2164 return READV (ciptr, buf, size);
2169 TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
2172 PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
2174 return WRITEV (ciptr, buf, size);
2179 TRANS(SocketDisconnect) (XtransConnInfo ciptr)
2182 PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
2186 int ret = shutdown (ciptr->fd, 2);
2187 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2191 return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
2198 TRANS(SocketINETClose) (XtransConnInfo ciptr)
2201 PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
2205 int ret = close (ciptr->fd);
2206 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2210 return close (ciptr->fd);
2214 #endif /* TCPCONN */
2219 TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
2222 * If this is the server side, then once the socket is closed,
2223 * it must be unlinked to completely close it
2226 struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
2229 PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
2231 ret = close(ciptr->fd);
2235 && sockname->sun_family == AF_UNIX
2236 && sockname->sun_path[0])
2238 if (!(ciptr->flags & TRANS_NOUNLINK
2239 || ciptr->transptr->flags & TRANS_ABSTRACT))
2240 unlink (sockname->sun_path);
2247 TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
2251 * Don't unlink path.
2256 PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
2257 ciptr, ciptr->fd, 0);
2259 ret = close(ciptr->fd);
2264 #endif /* UNIXCONN */
2268 # ifdef TRANS_SERVER
2269 static char* tcp_nolisten[] = {
2271 #if defined(IPv6) && defined(AF_INET6)
2278 Xtransport TRANS(SocketTCPFuncs) = {
2279 /* Socket Interface */
2283 TRANS(SocketOpenCOTSClient),
2284 #endif /* TRANS_CLIENT */
2287 TRANS(SocketOpenCOTSServer),
2288 #endif /* TRANS_SERVER */
2290 TRANS(SocketOpenCLTSClient),
2291 #endif /* TRANS_CLIENT */
2293 TRANS(SocketOpenCLTSServer),
2294 #endif /* TRANS_SERVER */
2296 TRANS(SocketReopenCOTSServer),
2297 TRANS(SocketReopenCLTSServer),
2299 TRANS(SocketSetOption),
2301 TRANS(SocketINETCreateListener),
2302 NULL, /* ResetListener */
2303 TRANS(SocketINETAccept),
2304 #endif /* TRANS_SERVER */
2306 TRANS(SocketINETConnect),
2307 #endif /* TRANS_CLIENT */
2308 TRANS(SocketBytesReadable),
2312 TRANS(SocketWritev),
2313 TRANS(SocketDisconnect),
2314 TRANS(SocketINETClose),
2315 TRANS(SocketINETClose),
2318 Xtransport TRANS(SocketINETFuncs) = {
2319 /* Socket Interface */
2323 TRANS(SocketOpenCOTSClient),
2324 #endif /* TRANS_CLIENT */
2327 TRANS(SocketOpenCOTSServer),
2328 #endif /* TRANS_SERVER */
2330 TRANS(SocketOpenCLTSClient),
2331 #endif /* TRANS_CLIENT */
2333 TRANS(SocketOpenCLTSServer),
2334 #endif /* TRANS_SERVER */
2336 TRANS(SocketReopenCOTSServer),
2337 TRANS(SocketReopenCLTSServer),
2339 TRANS(SocketSetOption),
2341 TRANS(SocketINETCreateListener),
2342 NULL, /* ResetListener */
2343 TRANS(SocketINETAccept),
2344 #endif /* TRANS_SERVER */
2346 TRANS(SocketINETConnect),
2347 #endif /* TRANS_CLIENT */
2348 TRANS(SocketBytesReadable),
2352 TRANS(SocketWritev),
2353 TRANS(SocketDisconnect),
2354 TRANS(SocketINETClose),
2355 TRANS(SocketINETClose),
2358 #if defined(IPv6) && defined(AF_INET6)
2359 Xtransport TRANS(SocketINET6Funcs) = {
2360 /* Socket Interface */
2364 TRANS(SocketOpenCOTSClient),
2365 #endif /* TRANS_CLIENT */
2368 TRANS(SocketOpenCOTSServer),
2369 #endif /* TRANS_SERVER */
2371 TRANS(SocketOpenCLTSClient),
2372 #endif /* TRANS_CLIENT */
2374 TRANS(SocketOpenCLTSServer),
2375 #endif /* TRANS_SERVER */
2377 TRANS(SocketReopenCOTSServer),
2378 TRANS(SocketReopenCLTSServer),
2380 TRANS(SocketSetOption),
2382 TRANS(SocketINETCreateListener),
2383 NULL, /* ResetListener */
2384 TRANS(SocketINETAccept),
2385 #endif /* TRANS_SERVER */
2387 TRANS(SocketINETConnect),
2388 #endif /* TRANS_CLIENT */
2389 TRANS(SocketBytesReadable),
2393 TRANS(SocketWritev),
2394 TRANS(SocketDisconnect),
2395 TRANS(SocketINETClose),
2396 TRANS(SocketINETClose),
2399 #endif /* TCPCONN */
2402 #if !defined(LOCALCONN)
2403 Xtransport TRANS(SocketLocalFuncs) = {
2404 /* Socket Interface */
2406 #ifdef HAVE_ABSTRACT_SOCKETS
2412 TRANS(SocketOpenCOTSClient),
2413 #endif /* TRANS_CLIENT */
2416 TRANS(SocketOpenCOTSServer),
2417 #endif /* TRANS_SERVER */
2419 TRANS(SocketOpenCLTSClient),
2420 #endif /* TRANS_CLIENT */
2422 TRANS(SocketOpenCLTSServer),
2423 #endif /* TRANS_SERVER */
2425 TRANS(SocketReopenCOTSServer),
2426 TRANS(SocketReopenCLTSServer),
2428 TRANS(SocketSetOption),
2430 TRANS(SocketUNIXCreateListener),
2431 TRANS(SocketUNIXResetListener),
2432 TRANS(SocketUNIXAccept),
2433 #endif /* TRANS_SERVER */
2435 TRANS(SocketUNIXConnect),
2436 #endif /* TRANS_CLIENT */
2437 TRANS(SocketBytesReadable),
2441 TRANS(SocketWritev),
2442 TRANS(SocketDisconnect),
2443 TRANS(SocketUNIXClose),
2444 TRANS(SocketUNIXCloseForCloning),
2446 #endif /* !LOCALCONN */
2447 # ifdef TRANS_SERVER
2448 # if !defined(LOCALCONN)
2449 static char* unix_nolisten[] = { "local" , NULL };
2453 Xtransport TRANS(SocketUNIXFuncs) = {
2454 /* Socket Interface */
2456 #if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
2462 TRANS(SocketOpenCOTSClient),
2463 #endif /* TRANS_CLIENT */
2465 #if !defined(LOCALCONN)
2470 TRANS(SocketOpenCOTSServer),
2471 #endif /* TRANS_SERVER */
2473 TRANS(SocketOpenCLTSClient),
2474 #endif /* TRANS_CLIENT */
2476 TRANS(SocketOpenCLTSServer),
2477 #endif /* TRANS_SERVER */
2479 TRANS(SocketReopenCOTSServer),
2480 TRANS(SocketReopenCLTSServer),
2482 TRANS(SocketSetOption),
2484 TRANS(SocketUNIXCreateListener),
2485 TRANS(SocketUNIXResetListener),
2486 TRANS(SocketUNIXAccept),
2487 #endif /* TRANS_SERVER */
2489 TRANS(SocketUNIXConnect),
2490 #endif /* TRANS_CLIENT */
2491 TRANS(SocketBytesReadable),
2495 TRANS(SocketWritev),
2496 TRANS(SocketDisconnect),
2497 TRANS(SocketUNIXClose),
2498 TRANS(SocketUNIXCloseForCloning),
2501 #endif /* UNIXCONN */