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 {
175 const char *transname;
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, const char *family)
262 prmsg (3,"SocketSelectFamily(%s)\n", family);
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);
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 = malloc (namelen)) == NULL)
321 "SocketINETGetAddr: Can't allocate space for the addr\n");
325 #if defined(IPv6) && defined(AF_INET6)
326 ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
328 ciptr->family = socknamev4.sin_family;
330 ciptr->addrlen = namelen;
331 memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
338 * This function gets the remote address of the socket and stores it in the
339 * XtransConnInfo structure for the connection.
343 TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
346 #if defined(IPv6) && defined(AF_INET6)
347 struct sockaddr_storage socknamev6;
349 struct sockaddr_in socknamev4;
353 #if defined(IPv6) && defined(AF_INET6)
354 if (ciptr->family == AF_INET6)
356 namelen = sizeof(socknamev6);
357 socknamePtr = &socknamev6;
362 namelen = sizeof(socknamev4);
363 socknamePtr = &socknamev4;
366 bzero(socknamePtr, namelen);
368 prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr);
370 if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
371 (void *)&namelen) < 0)
374 errno = WSAGetLastError();
376 prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
382 * Everything looks good: fill in the XtransConnInfo structure.
385 if ((ciptr->peeraddr = malloc (namelen)) == NULL)
388 "SocketINETGetPeerAddr: Can't allocate space for the addr\n");
392 ciptr->peeraddrlen = namelen;
393 memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
399 static XtransConnInfo
400 TRANS(SocketOpen) (int i, int type)
403 XtransConnInfo ciptr;
405 prmsg (3,"SocketOpen(%d,%d)\n", i, type);
407 if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
409 prmsg (1, "SocketOpen: malloc failed\n");
413 if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
414 Sockettrans2devtab[i].protocol)) < 0
416 #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
417 || ciptr->fd >= sysconf(_SC_OPEN_MAX)
422 errno = WSAGetLastError();
424 prmsg (2, "SocketOpen: socket() failed for %s\n",
425 Sockettrans2devtab[i].transname);
432 if (Sockettrans2devtab[i].family == AF_INET
433 #if defined(IPv6) && defined(AF_INET6)
434 || Sockettrans2devtab[i].family == AF_INET6
439 * turn off TCP coalescence for INET sockets
443 setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
444 (char *) &tmp, sizeof (int));
454 static XtransConnInfo
455 TRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, char *port)
458 XtransConnInfo ciptr;
460 struct sockaddr *addr;
463 prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
466 prmsg (1, "SocketReopen: port was null!\n");
470 portlen = strlen(port) + 1; // include space for trailing null
471 #ifdef SOCK_MAXADDRLEN
472 if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
473 prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
476 if (portlen < 14) portlen = 14;
478 if (portlen < 0 || portlen > 14) {
479 prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
482 #endif /*SOCK_MAXADDRLEN*/
484 if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
486 prmsg (1, "SocketReopen: malloc(ciptr) failed\n");
492 addrlen = portlen + offsetof(struct sockaddr, sa_data);
493 if ((addr = calloc (1, addrlen)) == NULL) {
494 prmsg (1, "SocketReopen: malloc(addr) failed\n");
498 ciptr->addr = (char *) addr;
499 ciptr->addrlen = addrlen;
501 if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) {
502 prmsg (1, "SocketReopen: malloc(portaddr) failed\n");
507 ciptr->peeraddrlen = addrlen;
509 /* Initialize ciptr structure as if it were a normally-opened unix socket */
510 ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
512 addr->sa_len = addrlen;
514 addr->sa_family = AF_UNIX;
516 strlcpy(addr->sa_data, port, portlen);
518 strncpy(addr->sa_data, port, portlen);
520 ciptr->family = AF_UNIX;
521 memcpy(ciptr->peeraddr, ciptr->addr, addrlen);
522 ciptr->port = rindex(addr->sa_data, ':');
523 if (ciptr->port == NULL) {
524 if (is_numeric(addr->sa_data)) {
525 ciptr->port = addr->sa_data;
527 } else if (ciptr->port[0] == ':') {
530 /* port should now point to portnum or NULL */
534 #endif /* TRANS_REOPEN */
538 * These functions are the interface supplied in the Xtransport structure
543 static XtransConnInfo
544 TRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol,
545 const char *host, const char *port, int previndex)
547 XtransConnInfo ciptr;
550 prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
551 protocol, host, port);
555 while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
556 if ((ciptr = TRANS(SocketOpen) (
557 i, Sockettrans2devtab[i].devcotsname)) != NULL) {
558 /* Save the index for later use */
566 prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
569 prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
577 static XtransConnInfo
578 TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
579 char *host, char *port)
581 return TRANS(SocketOpenCOTSClientBase)(
582 thistrans->TransName, protocol, host, port, -1);
586 #endif /* TRANS_CLIENT */
591 static XtransConnInfo
592 TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
593 char *host, char *port)
596 XtransConnInfo ciptr;
599 prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
603 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
604 if ((ciptr = TRANS(SocketOpen) (
605 i, Sockettrans2devtab[i].devcotsname)) != NULL)
610 prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
611 thistrans->TransName);
613 prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
614 thistrans->TransName);
619 * Using this prevents the bind() check for an existing server listening
620 * on the same port, but it is required for other reasons.
625 * SO_REUSEADDR only applied to AF_INET && AF_INET6
628 if (Sockettrans2devtab[i].family == AF_INET
629 #if defined(IPv6) && defined(AF_INET6)
630 || Sockettrans2devtab[i].family == AF_INET6
635 setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
636 (char *) &one, sizeof (int));
640 if (Sockettrans2devtab[i].family == AF_INET6)
643 setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
646 /* Save the index for later use */
653 #endif /* TRANS_SERVER */
658 static XtransConnInfo
659 TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
660 char *host, char *port)
663 XtransConnInfo ciptr;
666 prmsg (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
670 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
671 if ((ciptr = TRANS(SocketOpen) (
672 i, Sockettrans2devtab[i].devcotsname)) != NULL)
677 prmsg (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
678 thistrans->TransName);
680 prmsg (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
681 thistrans->TransName);
685 /* Save the index for later use */
692 #endif /* TRANS_CLIENT */
697 static XtransConnInfo
698 TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
699 char *host, char *port)
702 XtransConnInfo ciptr;
705 prmsg (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
709 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
710 if ((ciptr = TRANS(SocketOpen) (
711 i, Sockettrans2devtab[i].devcotsname)) != NULL)
716 prmsg (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
717 thistrans->TransName);
719 prmsg (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
720 thistrans->TransName);
725 if (Sockettrans2devtab[i].family == AF_INET6)
728 setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
731 /* Save the index for later use */
738 #endif /* TRANS_SERVER */
743 static XtransConnInfo
744 TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
747 XtransConnInfo ciptr;
751 "SocketReopenCOTSServer(%d, %s)\n", fd, port);
755 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
756 if ((ciptr = TRANS(SocketReopen) (
757 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
762 prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
763 thistrans->TransName);
765 prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
766 thistrans->TransName);
770 /* Save the index for later use */
777 static XtransConnInfo
778 TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
781 XtransConnInfo ciptr;
785 "SocketReopenCLTSServer(%d, %s)\n", fd, port);
789 while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
790 if ((ciptr = TRANS(SocketReopen) (
791 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
796 prmsg (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
797 thistrans->TransName);
799 prmsg (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
800 thistrans->TransName);
804 /* Save the index for later use */
811 #endif /* TRANS_REOPEN */
815 TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
818 prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
825 set_sun_path(const char *port, const char *upath, char *path, int abstract)
827 struct sockaddr_un s;
828 int maxlen = sizeof(s.sun_path) - 1;
831 if (!port || !*port || !path)
834 #ifdef HAVE_ABSTRACT_SOCKETS
841 if (*port == '/') /* a full pathname */
844 if (strlen(port) + strlen(upath) > maxlen)
846 snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port);
854 TRANS(SocketCreateListener) (XtransConnInfo ciptr,
855 struct sockaddr *sockname,
856 int socknamelen, unsigned int flags)
859 SOCKLEN_T namelen = socknamelen;
863 prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd);
865 if (Sockettrans2devtab[ciptr->index].family == AF_INET
866 #if defined(IPv6) && defined(AF_INET6)
867 || Sockettrans2devtab[ciptr->index].family == AF_INET6
874 while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
876 if (errno == EADDRINUSE) {
877 if (flags & ADDR_IN_USE_ALLOWED)
880 return TRANS_ADDR_IN_USE;
884 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");
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);
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 snprintf (portbuf, sizeof(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");
1041 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1044 "SocketINETCreateListener: ...SocketINETGetAddr() failed\n");
1045 return TRANS_CREATE_LISTENER_FAILED;
1051 #endif /* TCPCONN */
1057 TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
1061 struct sockaddr_un sockname;
1069 #ifdef HAVE_ABSTRACT_SOCKETS
1070 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1073 prmsg (2, "SocketUNIXCreateListener(%s)\n",
1074 port ? port : "NULL");
1076 /* Make sure the directory is created */
1078 oldUmask = umask (0);
1081 #ifdef HAS_STICKY_DIR_BIT
1086 if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
1087 prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
1089 (void) umask (oldUmask);
1090 return TRANS_CREATE_LISTENER_FAILED;
1094 memset(&sockname, 0, sizeof(sockname));
1095 sockname.sun_family = AF_UNIX;
1097 if (!(port && *port)) {
1098 snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
1101 if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1102 prmsg (1, "SocketUNIXCreateListener: path too long\n");
1103 return TRANS_CREATE_LISTENER_FAILED;
1106 #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
1107 sockname.sun_len = strlen(sockname.sun_path);
1110 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1111 namelen = SUN_LEN(&sockname);
1113 namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
1117 sockname.sun_path[0] = '\0';
1118 namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
1121 unlink (sockname.sun_path);
1123 if ((status = TRANS(SocketCreateListener) (ciptr,
1124 (struct sockaddr *) &sockname, namelen, flags)) < 0)
1127 "SocketUNIXCreateListener: ...SocketCreateListener() failed\n");
1128 (void) umask (oldUmask);
1133 * Now that the listener is esablished, create the addr info for
1134 * this connection. getpeername() doesn't work for UNIX Domain Sockets
1135 * on some systems (hpux at least), so we will just do it manually, instead
1136 * of calling something like TRANS(SocketUNIXGetAddr).
1139 namelen = sizeof (sockname); /* this will always make it the same size */
1141 if ((ciptr->addr = malloc (namelen)) == NULL)
1144 "SocketUNIXCreateListener: Can't allocate space for the addr\n");
1145 (void) umask (oldUmask);
1146 return TRANS_CREATE_LISTENER_FAILED;
1150 sockname.sun_path[0] = '@';
1152 ciptr->family = sockname.sun_family;
1153 ciptr->addrlen = namelen;
1154 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
1156 (void) umask (oldUmask);
1163 TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
1167 * See if the unix domain socket has disappeared. If it has, recreate it.
1170 struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
1172 int status = TRANS_RESET_NOOP;
1175 #ifdef HAVE_ABSTRACT_SOCKETS
1176 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1179 prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd);
1182 stat (unsock->sun_path, &statb) == -1 ||
1183 ((statb.st_mode & S_IFMT) !=
1184 #if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
1191 int oldUmask = umask (0);
1194 #ifdef HAS_STICKY_DIR_BIT
1199 if (trans_mkdir(UNIX_DIR, mode) == -1) {
1200 prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
1202 (void) umask (oldUmask);
1203 return TRANS_RESET_FAILURE;
1208 unlink (unsock->sun_path);
1210 if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
1212 TRANS(FreeConnInfo) (ciptr);
1213 (void) umask (oldUmask);
1214 return TRANS_RESET_FAILURE;
1217 if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
1220 TRANS(FreeConnInfo) (ciptr);
1221 return TRANS_RESET_FAILURE;
1224 if (listen (ciptr->fd, BACKLOG) < 0)
1227 TRANS(FreeConnInfo) (ciptr);
1228 (void) umask (oldUmask);
1229 return TRANS_RESET_FAILURE;
1234 status = TRANS_RESET_NEW_FD;
1240 #endif /* UNIXCONN */
1245 static XtransConnInfo
1246 TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
1249 XtransConnInfo newciptr;
1250 struct sockaddr_in sockname;
1251 SOCKLEN_T namelen = sizeof(sockname);
1253 prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd);
1255 if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
1257 prmsg (1, "SocketINETAccept: malloc failed\n");
1258 *status = TRANS_ACCEPT_BAD_MALLOC;
1262 if ((newciptr->fd = accept (ciptr->fd,
1263 (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
1266 errno = WSAGetLastError();
1268 prmsg (1, "SocketINETAccept: accept() failed\n");
1270 *status = TRANS_ACCEPT_FAILED;
1277 * turn off TCP coalescence for INET sockets
1281 setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
1282 (char *) &tmp, sizeof (int));
1287 * Get this address again because the transport may give a more
1288 * specific address now that a connection is established.
1291 if (TRANS(SocketINETGetAddr) (newciptr) < 0)
1294 "SocketINETAccept: ...SocketINETGetAddr() failed:\n");
1295 close (newciptr->fd);
1297 *status = TRANS_ACCEPT_MISC_ERROR;
1301 if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
1304 "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n");
1305 close (newciptr->fd);
1306 if (newciptr->addr) free (newciptr->addr);
1308 *status = TRANS_ACCEPT_MISC_ERROR;
1317 #endif /* TCPCONN */
1321 static XtransConnInfo
1322 TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
1325 XtransConnInfo newciptr;
1326 struct sockaddr_un sockname;
1327 SOCKLEN_T namelen = sizeof sockname;
1329 prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd);
1331 if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
1333 prmsg (1, "SocketUNIXAccept: malloc() failed\n");
1334 *status = TRANS_ACCEPT_BAD_MALLOC;
1338 if ((newciptr->fd = accept (ciptr->fd,
1339 (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
1341 prmsg (1, "SocketUNIXAccept: accept() failed\n");
1343 *status = TRANS_ACCEPT_FAILED;
1347 ciptr->addrlen = namelen;
1349 * Get the socket name and the peer name from the listener socket,
1350 * since this is unix domain.
1353 if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL)
1356 "SocketUNIXAccept: Can't allocate space for the addr\n");
1357 close (newciptr->fd);
1359 *status = TRANS_ACCEPT_BAD_MALLOC;
1364 * if the socket is abstract, we already modified the address to have a
1365 * @ instead of the initial NUL, so no need to do that again here.
1368 newciptr->addrlen = ciptr->addrlen;
1369 memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
1371 if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL)
1374 "SocketUNIXAccept: Can't allocate space for the addr\n");
1375 close (newciptr->fd);
1376 if (newciptr->addr) free (newciptr->addr);
1378 *status = TRANS_ACCEPT_BAD_MALLOC;
1382 newciptr->peeraddrlen = ciptr->addrlen;
1383 memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
1385 newciptr->family = AF_UNIX;
1392 #endif /* UNIXCONN */
1394 #endif /* TRANS_SERVER */
1401 #if defined(IPv6) && defined(AF_INET6)
1403 struct addrinfo * addr;
1404 struct addrinfo * firstaddr;
1405 char port[PORTBUFSIZE];
1406 char host[MAXHOSTNAMELEN];
1408 static struct addrlist *addrlist = NULL;
1413 TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
1416 struct sockaddr * socketaddr = NULL;
1417 int socketaddrlen = 0;
1419 #if defined(IPv6) && defined(AF_INET6)
1420 struct addrinfo hints;
1421 char ntopbuf[INET6_ADDRSTRLEN];
1424 struct sockaddr_in sockname;
1425 struct hostent *hostp;
1426 struct servent *servp;
1427 unsigned long tmpaddr;
1429 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1430 _Xgethostbynameparams hparams;
1431 _Xgetservbynameparams sparams;
1434 char portbuf[PORTBUFSIZE];
1437 char hostnamebuf[256]; /* tmp space */
1439 prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1443 hostnamebuf[0] = '\0';
1444 (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
1450 * X has a well known port, that is transport dependent. It is easier
1451 * to handle it here, than try and come up with a transport independent
1452 * representation that can be passed in and resolved the usual way.
1454 * The port that is passed here is really a string containing the idisplay
1455 * from ConnectDisplay().
1458 if (is_numeric (port))
1460 long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1461 snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
1466 #if defined(IPv6) && defined(AF_INET6)
1468 if (addrlist != NULL) {
1469 if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
1470 if (addrlist->firstaddr)
1471 freeaddrinfo(addrlist->firstaddr);
1472 addrlist->firstaddr = NULL;
1475 addrlist = malloc(sizeof(struct addrlist));
1476 addrlist->firstaddr = NULL;
1479 if (addrlist->firstaddr == NULL) {
1480 strncpy(addrlist->port, port, sizeof(addrlist->port));
1481 addrlist->port[sizeof(addrlist->port) - 1] = '\0';
1482 strncpy(addrlist->host, host, sizeof(addrlist->host));
1483 addrlist->host[sizeof(addrlist->host) - 1] = '\0';
1485 bzero(&hints,sizeof(hints));
1486 hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
1488 res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
1490 prmsg (1, "SocketINETConnect() can't get address "
1491 "for %s:%s: %s\n", host, port, gai_strerror(res));
1493 return TRANS_CONNECT_FAILED;
1495 for (res = 0, addrlist->addr = addrlist->firstaddr;
1496 addrlist->addr ; res++) {
1497 addrlist->addr = addrlist->addr->ai_next;
1499 prmsg(4,"Got New Address list with %d addresses\n", res);
1501 addrlist->addr = NULL;
1504 while (socketaddr == NULL) {
1505 if (addrlist->addr == NULL) {
1507 /* Already checked entire list - no usable addresses */
1508 prmsg (1, "SocketINETConnect() no usable address "
1509 "for %s:%s\n", host, port);
1510 return TRANS_CONNECT_FAILED;
1512 /* Go back to beginning of list */
1514 addrlist->addr = addrlist->firstaddr;
1518 socketaddr = addrlist->addr->ai_addr;
1519 socketaddrlen = addrlist->addr->ai_addrlen;
1521 if (addrlist->addr->ai_family == AF_INET) {
1522 struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
1524 prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n",
1525 inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
1526 ntopbuf,sizeof(ntopbuf)));
1528 prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n",
1529 ntohs(sin->sin_port));
1531 if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
1532 if (strcmp(Sockettrans2devtab[ciptr->index].transname,
1534 XtransConnInfo newciptr;
1537 * Our socket is an IPv6 socket, but the address is
1538 * IPv4. Close it and get an IPv4 socket. This is
1539 * needed for IPv4 connections to work on platforms
1540 * that don't allow IPv4 over IPv6 sockets.
1542 TRANS(SocketINETClose)(ciptr);
1543 newciptr = TRANS(SocketOpenCOTSClientBase)(
1544 "tcp", "tcp", host, port, ciptr->index);
1546 ciptr->fd = newciptr->fd;
1548 Sockettrans2devtab[newciptr->index].family !=
1551 prmsg (4,"SocketINETConnect() Cannot get IPv4 "
1552 " socketfor IPv4 address\n");
1558 prmsg (4,"SocketINETConnect Skipping IPv4 address\n");
1561 } else if (addrlist->addr->ai_family == AF_INET6) {
1562 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
1564 prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
1565 inet_ntop(addrlist->addr->ai_family,
1566 &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)));
1567 prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n",
1568 ntohs(sin6->sin6_port));
1570 if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
1571 if (strcmp(Sockettrans2devtab[ciptr->index].transname,
1573 XtransConnInfo newciptr;
1576 * Close the IPv4 socket and try to open an IPv6 socket.
1578 TRANS(SocketINETClose)(ciptr);
1579 newciptr = TRANS(SocketOpenCOTSClientBase)(
1580 "tcp", "tcp", host, port, -1);
1582 ciptr->fd = newciptr->fd;
1584 Sockettrans2devtab[newciptr->index].family !=
1587 prmsg (4,"SocketINETConnect() Cannot get IPv6 "
1588 "socket for IPv6 address\n");
1596 prmsg (4,"SocketINETConnect() Skipping IPv6 address\n");
1600 socketaddr = NULL; /* Unsupported address type */
1602 if (socketaddr == NULL) {
1603 addrlist->addr = addrlist->addr->ai_next;
1610 * Build the socket name.
1614 sockname.sin_len = sizeof (struct sockaddr_in);
1616 sockname.sin_family = AF_INET;
1623 #define INADDR_NONE ((in_addr_t) 0xffffffff)
1626 /* check for ww.xx.yy.zz host string */
1628 if (isascii (host[0]) && isdigit (host[0])) {
1629 tmpaddr = inet_addr (host); /* returns network byte order */
1631 tmpaddr = INADDR_NONE;
1634 prmsg (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr);
1636 if (tmpaddr == INADDR_NONE) {
1637 if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
1638 prmsg (1,"SocketINETConnect: Can't get address for %s\n",
1641 return TRANS_CONNECT_FAILED;
1643 if (hostp->h_addrtype != AF_INET) { /* is IP host? */
1644 prmsg (1,"SocketINETConnect: not INET host%s\n", host);
1646 return TRANS_CONNECT_FAILED;
1649 memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
1650 sizeof (sockname.sin_addr));
1653 sockname.sin_addr.s_addr = tmpaddr;
1660 /* Check for number in the port string */
1662 if (!is_numeric (port)) {
1663 if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
1664 prmsg (1,"SocketINETConnect: can't get service for %s\n",
1666 return TRANS_CONNECT_FAILED;
1668 sockname.sin_port = htons (servp->s_port);
1670 long tmpport = strtol (port, (char**)NULL, 10);
1671 if (tmpport < 1024 || tmpport > USHRT_MAX)
1672 return TRANS_CONNECT_FAILED;
1673 sockname.sin_port = htons (((unsigned short) tmpport));
1676 prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n",
1677 ntohs(sockname.sin_port));
1678 socketaddr = (struct sockaddr *) &sockname;
1679 socketaddrlen = sizeof(sockname);
1684 * Turn on socket keepalive so the client process will eventually
1685 * be notified with a SIGPIPE signal if the display server fails
1686 * to respond to a periodic transmission of messages
1687 * on the connected socket.
1688 * This is useful to avoid hung application processes when the
1689 * processes are not spawned from the xdm session and
1690 * the display server terminates abnormally.
1691 * (Someone turned off the power switch.)
1696 setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
1697 (char *) &tmp, sizeof (int));
1704 if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
1707 int olderrno = WSAGetLastError();
1709 int olderrno = errno;
1713 * If the error was ECONNREFUSED, the server may be overloaded
1714 * and we should try again.
1716 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
1717 * was non-blocking and we should poll using select
1719 * If the error was EINTR, the connect was interrupted and we
1722 * If multiple addresses are found for a host then we should
1723 * try to connect again with a different address for a larger
1724 * number of errors that made us quit before, since those
1725 * could be caused by trying to use an IPv6 address to contact
1726 * a machine with an IPv4-only server or other reasons that
1727 * only affect one of a set of addresses.
1730 if (olderrno == ECONNREFUSED || olderrno == EINTR
1731 #if defined(IPv6) && defined(AF_INET6)
1732 || (((addrlist->addr->ai_next != NULL) ||
1733 (addrlist->addr != addrlist->firstaddr)) &&
1734 (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
1735 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
1736 #if defined(EHOSTDOWN)
1737 || olderrno == EHOSTDOWN
1742 res = TRANS_TRY_CONNECT_AGAIN;
1743 else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
1744 res = TRANS_IN_PROGRESS;
1747 prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n",
1750 res = TRANS_CONNECT_FAILED;
1757 * Sync up the address fields of ciptr.
1760 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1763 "SocketINETConnect: ...SocketINETGetAddr() failed:\n");
1764 res = TRANS_CONNECT_FAILED;
1767 else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
1770 "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n");
1771 res = TRANS_CONNECT_FAILED;
1775 #if defined(IPv6) && defined(AF_INET6)
1777 addrlist->addr = addrlist->addr->ai_next;
1784 #endif /* TCPCONN */
1791 * Make sure 'host' is really local.
1795 UnixHostReallyLocal (char *host)
1798 char hostnamebuf[256];
1800 TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
1802 if (strcmp (hostnamebuf, host) == 0)
1806 #if defined(IPv6) && defined(AF_INET6)
1807 struct addrinfo *localhostaddr;
1808 struct addrinfo *otherhostaddr;
1809 struct addrinfo *i, *j;
1812 if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
1814 if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
1815 freeaddrinfo(localhostaddr);
1819 for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
1820 for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
1821 if (i->ai_family == j->ai_family) {
1822 if (i->ai_family == AF_INET) {
1823 struct sockaddr_in *sinA
1824 = (struct sockaddr_in *) i->ai_addr;
1825 struct sockaddr_in *sinB
1826 = (struct sockaddr_in *) j->ai_addr;
1827 struct in_addr *A = &sinA->sin_addr;
1828 struct in_addr *B = &sinB->sin_addr;
1830 if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
1833 } else if (i->ai_family == AF_INET6) {
1834 struct sockaddr_in6 *sinA
1835 = (struct sockaddr_in6 *) i->ai_addr;
1836 struct sockaddr_in6 *sinB
1837 = (struct sockaddr_in6 *) j->ai_addr;
1838 struct in6_addr *A = &sinA->sin6_addr;
1839 struct in6_addr *B = &sinB->sin6_addr;
1841 if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
1849 freeaddrinfo(localhostaddr);
1850 freeaddrinfo(otherhostaddr);
1854 * A host may have more than one network address. If any of the
1855 * network addresses of 'host' (specified to the connect call)
1856 * match any of the network addresses of 'hostname' (determined
1857 * by TRANS(GetHostname)), then the two hostnames are equivalent,
1858 * and we know that 'host' is really a local host.
1860 char specified_local_addr_list[10][4];
1861 int scount, equiv, i, j;
1862 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1863 _Xgethostbynameparams hparams;
1865 struct hostent *hostp;
1867 if ((hostp = _XGethostbyname (host,hparams)) == NULL)
1871 while (hostp->h_addr_list[scount] && scount <= 8)
1874 * The 2nd call to gethostname() overrides the data
1875 * from the 1st call, so we must save the address list.
1878 specified_local_addr_list[scount][0] =
1879 hostp->h_addr_list[scount][0];
1880 specified_local_addr_list[scount][1] =
1881 hostp->h_addr_list[scount][1];
1882 specified_local_addr_list[scount][2] =
1883 hostp->h_addr_list[scount][2];
1884 specified_local_addr_list[scount][3] =
1885 hostp->h_addr_list[scount][3];
1888 if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
1894 while (i < scount && !equiv)
1898 while (hostp->h_addr_list[j])
1900 if ((specified_local_addr_list[i][0] ==
1901 hostp->h_addr_list[j][0]) &&
1902 (specified_local_addr_list[i][1] ==
1903 hostp->h_addr_list[j][1]) &&
1904 (specified_local_addr_list[i][2] ==
1905 hostp->h_addr_list[j][2]) &&
1906 (specified_local_addr_list[i][3] ==
1907 hostp->h_addr_list[j][3]))
1909 /* They're equal, so we're done */
1926 TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
1929 struct sockaddr_un sockname;
1934 #ifdef HAVE_ABSTRACT_SOCKETS
1935 abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
1938 prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1941 * Make sure 'host' is really local. If not, we return failure.
1942 * The reason we make this check is because a process may advertise
1943 * a "local" network ID for which it can accept connections, but if
1944 * a process on a remote machine tries to connect to this network ID,
1945 * we know for sure it will fail.
1948 if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
1951 "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1953 return TRANS_CONNECT_FAILED;
1961 if (!port || !*port)
1963 prmsg (1,"SocketUNIXConnect: Missing port specification\n");
1964 return TRANS_CONNECT_FAILED;
1968 * Build the socket name.
1971 sockname.sun_family = AF_UNIX;
1973 if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1974 prmsg (1, "SocketUNIXConnect: path too long\n");
1975 return TRANS_CONNECT_FAILED;
1978 #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
1979 sockname.sun_len = strlen (sockname.sun_path);
1982 #if defined(BSD44SOCKETS) || defined(SUN_LEN)
1983 namelen = SUN_LEN (&sockname);
1985 namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
1991 * Adjust the socket path if using abstract sockets.
1992 * Done here because otherwise all the strlen() calls above would fail.
1996 sockname.sun_path[0] = '\0';
2003 if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
2005 int olderrno = errno;
2013 * If the error was ENOENT, the server may be starting up; we used
2014 * to suggest to try again in this case with
2015 * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
2016 * processes still referencing stale sockets in their environment.
2017 * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
2018 * is suggested that higher level stacks handle retries on their
2019 * level when they face a slow starting server.
2021 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
2022 * was non-blocking and we should poll using select
2024 * If the error was EINTR, the connect was interrupted and we
2028 if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
2029 return TRANS_IN_PROGRESS;
2030 else if (olderrno == EINTR)
2031 return TRANS_TRY_CONNECT_AGAIN;
2032 else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
2033 /* If opening as abstract socket failed, try again normally */
2035 ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
2036 return TRANS_TRY_CONNECT_AGAIN;
2038 return TRANS_CONNECT_FAILED;
2041 prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
2044 return TRANS_CONNECT_FAILED;
2050 * Get the socket name and the peer name from the connect socket,
2051 * since this is unix domain.
2054 if ((ciptr->addr = malloc(namelen)) == NULL ||
2055 (ciptr->peeraddr = malloc(namelen)) == NULL)
2058 "SocketUNIXCreateListener: Can't allocate space for the addr\n");
2059 return TRANS_CONNECT_FAILED;
2063 sockname.sun_path[0] = '@';
2065 ciptr->family = AF_UNIX;
2066 ciptr->addrlen = namelen;
2067 ciptr->peeraddrlen = namelen;
2068 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
2069 memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
2074 #endif /* UNIXCONN */
2076 #endif /* TRANS_CLIENT */
2080 TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
2083 prmsg (2,"SocketBytesReadable(%p,%d,%p)\n",
2084 ciptr, ciptr->fd, pend);
2087 int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
2088 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2092 #if defined(__i386__) && defined(SYSV) && !defined(SCO325)
2093 return ioctl (ciptr->fd, I_NREAD, (char *) pend);
2095 return ioctl (ciptr->fd, FIONREAD, (char *) pend);
2096 #endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
2102 TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
2105 prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
2109 int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
2111 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2116 return read (ciptr->fd, buf, size);
2122 TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
2125 prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
2129 int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
2131 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2136 return write (ciptr->fd, buf, size);
2142 TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
2145 prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
2147 return READV (ciptr, buf, size);
2152 TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
2155 prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
2157 return WRITEV (ciptr, buf, size);
2162 TRANS(SocketDisconnect) (XtransConnInfo ciptr)
2165 prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd);
2169 int ret = shutdown (ciptr->fd, 2);
2170 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2174 return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
2181 TRANS(SocketINETClose) (XtransConnInfo ciptr)
2184 prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd);
2188 int ret = close (ciptr->fd);
2189 if (ret == SOCKET_ERROR) errno = WSAGetLastError();
2193 return close (ciptr->fd);
2197 #endif /* TCPCONN */
2202 TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
2205 * If this is the server side, then once the socket is closed,
2206 * it must be unlinked to completely close it
2209 struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
2212 prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd);
2214 ret = close(ciptr->fd);
2218 && sockname->sun_family == AF_UNIX
2219 && sockname->sun_path[0])
2221 if (!(ciptr->flags & TRANS_NOUNLINK
2222 || ciptr->transptr->flags & TRANS_ABSTRACT))
2223 unlink (sockname->sun_path);
2230 TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
2234 * Don't unlink path.
2239 prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n",
2242 ret = close(ciptr->fd);
2247 #endif /* UNIXCONN */
2251 # ifdef TRANS_SERVER
2252 static const char* tcp_nolisten[] = {
2254 #if defined(IPv6) && defined(AF_INET6)
2261 Xtransport TRANS(SocketTCPFuncs) = {
2262 /* Socket Interface */
2266 TRANS(SocketOpenCOTSClient),
2267 #endif /* TRANS_CLIENT */
2270 TRANS(SocketOpenCOTSServer),
2271 #endif /* TRANS_SERVER */
2273 TRANS(SocketOpenCLTSClient),
2274 #endif /* TRANS_CLIENT */
2276 TRANS(SocketOpenCLTSServer),
2277 #endif /* TRANS_SERVER */
2279 TRANS(SocketReopenCOTSServer),
2280 TRANS(SocketReopenCLTSServer),
2282 TRANS(SocketSetOption),
2284 TRANS(SocketINETCreateListener),
2285 NULL, /* ResetListener */
2286 TRANS(SocketINETAccept),
2287 #endif /* TRANS_SERVER */
2289 TRANS(SocketINETConnect),
2290 #endif /* TRANS_CLIENT */
2291 TRANS(SocketBytesReadable),
2295 TRANS(SocketWritev),
2296 TRANS(SocketDisconnect),
2297 TRANS(SocketINETClose),
2298 TRANS(SocketINETClose),
2301 Xtransport TRANS(SocketINETFuncs) = {
2302 /* Socket Interface */
2306 TRANS(SocketOpenCOTSClient),
2307 #endif /* TRANS_CLIENT */
2310 TRANS(SocketOpenCOTSServer),
2311 #endif /* TRANS_SERVER */
2313 TRANS(SocketOpenCLTSClient),
2314 #endif /* TRANS_CLIENT */
2316 TRANS(SocketOpenCLTSServer),
2317 #endif /* TRANS_SERVER */
2319 TRANS(SocketReopenCOTSServer),
2320 TRANS(SocketReopenCLTSServer),
2322 TRANS(SocketSetOption),
2324 TRANS(SocketINETCreateListener),
2325 NULL, /* ResetListener */
2326 TRANS(SocketINETAccept),
2327 #endif /* TRANS_SERVER */
2329 TRANS(SocketINETConnect),
2330 #endif /* TRANS_CLIENT */
2331 TRANS(SocketBytesReadable),
2335 TRANS(SocketWritev),
2336 TRANS(SocketDisconnect),
2337 TRANS(SocketINETClose),
2338 TRANS(SocketINETClose),
2341 #if defined(IPv6) && defined(AF_INET6)
2342 Xtransport TRANS(SocketINET6Funcs) = {
2343 /* Socket Interface */
2347 TRANS(SocketOpenCOTSClient),
2348 #endif /* TRANS_CLIENT */
2351 TRANS(SocketOpenCOTSServer),
2352 #endif /* TRANS_SERVER */
2354 TRANS(SocketOpenCLTSClient),
2355 #endif /* TRANS_CLIENT */
2357 TRANS(SocketOpenCLTSServer),
2358 #endif /* TRANS_SERVER */
2360 TRANS(SocketReopenCOTSServer),
2361 TRANS(SocketReopenCLTSServer),
2363 TRANS(SocketSetOption),
2365 TRANS(SocketINETCreateListener),
2366 NULL, /* ResetListener */
2367 TRANS(SocketINETAccept),
2368 #endif /* TRANS_SERVER */
2370 TRANS(SocketINETConnect),
2371 #endif /* TRANS_CLIENT */
2372 TRANS(SocketBytesReadable),
2376 TRANS(SocketWritev),
2377 TRANS(SocketDisconnect),
2378 TRANS(SocketINETClose),
2379 TRANS(SocketINETClose),
2382 #endif /* TCPCONN */
2385 #if !defined(LOCALCONN)
2386 Xtransport TRANS(SocketLocalFuncs) = {
2387 /* Socket Interface */
2389 #ifdef HAVE_ABSTRACT_SOCKETS
2395 TRANS(SocketOpenCOTSClient),
2396 #endif /* TRANS_CLIENT */
2399 TRANS(SocketOpenCOTSServer),
2400 #endif /* TRANS_SERVER */
2402 TRANS(SocketOpenCLTSClient),
2403 #endif /* TRANS_CLIENT */
2405 TRANS(SocketOpenCLTSServer),
2406 #endif /* TRANS_SERVER */
2408 TRANS(SocketReopenCOTSServer),
2409 TRANS(SocketReopenCLTSServer),
2411 TRANS(SocketSetOption),
2413 TRANS(SocketUNIXCreateListener),
2414 TRANS(SocketUNIXResetListener),
2415 TRANS(SocketUNIXAccept),
2416 #endif /* TRANS_SERVER */
2418 TRANS(SocketUNIXConnect),
2419 #endif /* TRANS_CLIENT */
2420 TRANS(SocketBytesReadable),
2424 TRANS(SocketWritev),
2425 TRANS(SocketDisconnect),
2426 TRANS(SocketUNIXClose),
2427 TRANS(SocketUNIXCloseForCloning),
2429 #endif /* !LOCALCONN */
2430 # ifdef TRANS_SERVER
2431 # if !defined(LOCALCONN)
2432 static char* unix_nolisten[] = { "local" , NULL };
2436 Xtransport TRANS(SocketUNIXFuncs) = {
2437 /* Socket Interface */
2439 #if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
2445 TRANS(SocketOpenCOTSClient),
2446 #endif /* TRANS_CLIENT */
2448 #if !defined(LOCALCONN)
2453 TRANS(SocketOpenCOTSServer),
2454 #endif /* TRANS_SERVER */
2456 TRANS(SocketOpenCLTSClient),
2457 #endif /* TRANS_CLIENT */
2459 TRANS(SocketOpenCLTSServer),
2460 #endif /* TRANS_SERVER */
2462 TRANS(SocketReopenCOTSServer),
2463 TRANS(SocketReopenCLTSServer),
2465 TRANS(SocketSetOption),
2467 TRANS(SocketUNIXCreateListener),
2468 TRANS(SocketUNIXResetListener),
2469 TRANS(SocketUNIXAccept),
2470 #endif /* TRANS_SERVER */
2472 TRANS(SocketUNIXConnect),
2473 #endif /* TRANS_CLIENT */
2474 TRANS(SocketBytesReadable),
2478 TRANS(SocketWritev),
2479 TRANS(SocketDisconnect),
2480 TRANS(SocketUNIXClose),
2481 TRANS(SocketUNIXCloseForCloning),
2484 #endif /* UNIXCONN */