1 /* $XConsortium: Xtranssock.c /main/58 1996/12/04 10:22:50 lehors $ */
2 /* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.25.2.4 1998/02/01 16:04:34 robin Exp $ */
5 Copyright (c) 1993, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
33 /* Copyright (c) 1993, 1994 NCR Corporation - Dayton, Ohio, USA
37 * Permission to use, copy, modify, and distribute this software and its
38 * documentation for any purpose and without fee is hereby granted, provided
39 * that the above copyright notice appear in all copies and that both that
40 * copyright notice and this permission notice appear in supporting
41 * documentation, and that the name NCR not be used in advertising
42 * or publicity pertaining to distribution of the software without specific,
43 * written prior permission. NCR makes no representations about the
44 * suitability of this software for any purpose. It is provided "as is"
45 * without express or implied warranty.
47 * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
48 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
49 * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
50 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
51 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
52 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
53 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
58 #include <X11/Xthreads.h>
62 #if defined(TCPCONN) || defined(UNIXCONN)
63 #include <netinet/in.h>
69 #if defined(TCPCONN) || defined(UNIXCONN)
70 #define X_INCLUDE_NETDB_H
71 #define XOS_USE_NO_LOCKING
72 #include <X11/Xos_r.h>
86 #if defined(hpux) || defined(__EMX__)
96 #include <sys/param.h>
98 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
99 #include <machine/endian.h>
100 #endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */
101 #include <netinet/tcp.h>
102 #endif /* !NO_TCP_H */
103 #include <sys/ioctl.h>
104 #if defined(SVR4) && !defined(SCO325)
105 #include <sys/filio.h>
107 #if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
108 #if !defined(_SEQUENT_) && !defined(ESIX) && !defined(sco)
109 #include <net/errno.h>
110 #endif /* _SEQUENT_ || ESIX || SCO */
111 #if !defined(ISC) || !defined(I_NREAD) || defined(SCO325)
112 #include <sys/stropts.h>
114 #endif /* i386 && SYSV || _SEQUENT_ */
118 #include <X11/Xwinsock.h>
119 #include <X11/Xw32defs.h>
121 #define close closesocket
122 #define ECONNREFUSED WSAECONNREFUSED
123 #define EADDRINUSE WSAEADDRINUSE
124 #define EPROTOTYPE WSAEPROTOTYPE
126 #define EWOULDBLOCK WSAEWOULDBLOCK
128 #define EINTR WSAEINTR
129 #define X_INCLUDE_NETDB_H
130 #define XOS_USE_MTSAFE_NETDBAPI
131 #include <X11/Xos_r.h>
134 #if defined(SO_DONTLINGER) && defined(SO_LINGER)
139 #if defined(NOT_EMX09A)
140 static int IBMsockInit = 0;
141 #define SocketInitOnce()\
147 #define EINTR SOCEINTR
149 #define EINVAL SOCEINVAL
151 #define errno sock_errno()
153 #define close soclose
155 #define ioctl sockioctl
157 #define SocketInitOnce() /**/
159 /* this is still not there */
162 /* others don't need this */
163 #define SocketInitOnce() /**/
166 #define MIN_BACKLOG 128
168 #if SOMAXCONN > MIN_BACKLOG
169 #define BACKLOG SOMAXCONN
173 #define BACKLOG MIN_BACKLOG
176 * This is the Socket implementation of the X Transport service layer
178 * This file contains the implementation for both the UNIX and INET domains,
179 * and can be built for either one, or both.
183 typedef struct _Sockettrans2dev {
191 static Sockettrans2dev Sockettrans2devtab[] = {
193 {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
194 {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
197 {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
198 #if !defined(LOCALCONN)
199 {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
200 #endif /* !LOCALCONN */
201 #endif /* UNIXCONN */
204 #define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
212 #define UNIX_PATH "/usr/spool/sockets/X11/"
213 #define UNIX_DIR "/usr/spool/sockets/X11"
214 #define OLD_UNIX_PATH "/tmp/.X11-unix/X"
217 #define UNIX_PATH "/usr/spool/sockets/XIM/"
218 #define UNIX_DIR "/usr/spool/sockets/XIM"
219 #define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
221 #if defined(FS_t) || defined(FONT_t)
222 #define UNIX_PATH "/usr/spool/sockets/fontserv/"
223 #define UNIX_DIR "/usr/spool/sockets/fontserv"
224 #endif /* FS_t || FONT_t */
226 #define UNIX_PATH "/usr/spool/sockets/ICE/"
227 #define UNIX_DIR "/usr/spool/sockets/ICE"
230 #define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
231 #define UNIX_DIR "/usr/spool/sockets/xtrans_test"
237 #define UNIX_PATH "/tmp/.X11-unix/X"
238 #define UNIX_DIR "/tmp/.X11-unix"
241 #define UNIX_PATH "/tmp/.XIM-unix/XIM"
242 #define UNIX_DIR "/tmp/.XIM-unix"
244 #if defined(FS_t) || defined(FONT_t)
245 #define UNIX_PATH "/tmp/.font-unix/fs"
246 #define UNIX_DIR "/tmp/.font-unix"
247 #endif /* FS_t || FONT_t */
249 #define UNIX_PATH "/tmp/.ICE-unix/"
250 #define UNIX_DIR "/tmp/.ICE-unix"
253 #define UNIX_PATH "/tmp/.Test-unix/test"
254 #define UNIX_DIR "/tmp/.Test-unix"
259 #endif /* UNIXCONN */
263 * These are some utility function used by the real interface function below.
267 TRANS(SocketSelectFamily) (family)
274 PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
276 for (i = 0; i < NUMSOCKETFAMILIES;i++)
278 if (!strcmp (family, Sockettrans2devtab[i].transname))
287 * This function gets the local address of the socket and stores it in the
288 * XtransConnInfo structure for the connection.
292 TRANS(SocketINETGetAddr) (ciptr)
294 XtransConnInfo ciptr;
297 struct sockaddr_in sockname;
298 #if defined(SVR4) || defined(SCO325)
299 size_t namelen = sizeof sockname;
301 int namelen = sizeof sockname;
304 PRMSG (3,"SocketINETGetAddr(%x)\n", ciptr, 0, 0);
306 if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0)
308 PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
314 * Everything looks good: fill in the XtransConnInfo structure.
317 if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
320 "SocketINETGetAddr: Can't allocate space for the addr\n",
325 ciptr->family = sockname.sin_family;
326 ciptr->addrlen = namelen;
327 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
334 * This function gets the remote address of the socket and stores it in the
335 * XtransConnInfo structure for the connection.
339 TRANS(SocketINETGetPeerAddr) (ciptr)
341 XtransConnInfo ciptr;
344 struct sockaddr_in sockname;
345 #if defined(SVR4) || defined(SCO325)
346 size_t namelen = sizeof sockname;
348 int namelen = sizeof sockname;
351 PRMSG (3,"SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0);
353 if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
355 PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
361 * Everything looks good: fill in the XtransConnInfo structure.
364 if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
367 "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
372 ciptr->peeraddrlen = namelen;
373 memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
379 static XtransConnInfo
380 TRANS(SocketOpen) (i, type)
386 XtransConnInfo ciptr;
388 PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
390 if ((ciptr = (XtransConnInfo) xcalloc (
391 1, sizeof(struct _XtransConnInfo))) == NULL)
393 PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
397 if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
398 Sockettrans2devtab[i].protocol)) < 0
400 #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
401 || ciptr->fd >= TRANS_OPEN_MAX
405 PRMSG (1, "SocketOpen: socket() failed for %s\n",
406 Sockettrans2devtab[i].transname, 0, 0);
408 xfree ((char *) ciptr);
413 if (Sockettrans2devtab[i].family == AF_INET)
416 * turn off TCP coalescence for INET sockets
420 setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
421 (char *) &tmp, sizeof (int));
431 static XtransConnInfo
432 TRANS(SocketReopen) (i, type, fd, port)
440 XtransConnInfo ciptr;
442 PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
444 if ((ciptr = (XtransConnInfo) xcalloc (
445 1, sizeof(struct _XtransConnInfo))) == NULL)
447 PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
456 #endif /* TRANS_REOPEN */
460 * These functions are the interface supplied in the Xtransport structure
465 static XtransConnInfo
466 TRANS(SocketOpenCOTSClient) (thistrans, protocol, host, port)
468 Xtransport *thistrans;
474 XtransConnInfo ciptr;
477 PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
478 protocol, host, port);
482 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
485 "SocketOpenCOTSClient: Unable to determine socket type for %s\n",
486 thistrans->TransName, 0, 0);
490 if ((ciptr = TRANS(SocketOpen) (
491 i, Sockettrans2devtab[i].devcotsname)) == NULL)
493 PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
494 thistrans->TransName, 0, 0);
498 /* Save the index for later use */
505 #endif /* TRANS_CLIENT */
510 static XtransConnInfo
511 TRANS(SocketOpenCOTSServer) (thistrans, protocol, host, port)
513 Xtransport *thistrans;
519 XtransConnInfo ciptr;
522 PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
526 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
529 "SocketOpenCOTSServer: Unable to determine socket type for %s\n",
530 thistrans->TransName, 0, 0);
534 if ((ciptr = TRANS(SocketOpen) (
535 i, Sockettrans2devtab[i].devcotsname)) == NULL)
537 PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
538 thistrans->TransName, 0, 0);
543 * Using this prevents the bind() check for an existing server listening
544 * on the same port, but it is required for other reasons.
549 * SO_REUSEADDR only applied to AF_INET
552 if (Sockettrans2devtab[i].family == AF_INET)
555 setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
556 (char *) &one, sizeof (int));
560 /* Save the index for later use */
567 #endif /* TRANS_SERVER */
572 static XtransConnInfo
573 TRANS(SocketOpenCLTSClient) (thistrans, protocol, host, port)
575 Xtransport *thistrans;
581 XtransConnInfo ciptr;
584 PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
588 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
591 "SocketOpenCLTSClient: Unable to determine socket type for %s\n",
592 thistrans->TransName, 0, 0);
596 if ((ciptr = TRANS(SocketOpen) (
597 i, Sockettrans2devtab[i].devcotsname)) == NULL)
599 PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
600 thistrans->TransName, 0, 0);
604 /* Save the index for later use */
611 #endif /* TRANS_CLIENT */
616 static XtransConnInfo
617 TRANS(SocketOpenCLTSServer) (thistrans, protocol, host, port)
619 Xtransport *thistrans;
625 XtransConnInfo ciptr;
628 PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
632 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
635 "SocketOpenCLTSServer: Unable to determine socket type for %s\n",
636 thistrans->TransName, 0, 0);
640 if ((ciptr = TRANS(SocketOpen) (
641 i, Sockettrans2devtab[i].devcotsname)) == NULL)
643 PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
644 thistrans->TransName, 0, 0);
648 /* Save the index for later use */
655 #endif /* TRANS_SERVER */
660 static XtransConnInfo
661 TRANS(SocketReopenCOTSServer) (thistrans, fd, port)
663 Xtransport *thistrans;
668 XtransConnInfo ciptr;
672 "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
676 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
679 "SocketReopenCOTSServer: Unable to determine socket type for %s\n",
680 thistrans->TransName, 0, 0);
684 if ((ciptr = TRANS(SocketReopen) (
685 i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
688 "SocketReopenCOTSServer: Unable to reopen socket for %s\n",
689 thistrans->TransName, 0, 0);
693 /* Save the index for later use */
700 static XtransConnInfo
701 TRANS(SocketReopenCLTSServer) (thistrans, fd, port)
703 Xtransport *thistrans;
708 XtransConnInfo ciptr;
712 "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
716 if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
719 "SocketReopenCLTSServer: Unable to determine socket type for %s\n",
720 thistrans->TransName, 0, 0);
724 if ((ciptr = TRANS(SocketReopen) (
725 i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
728 "SocketReopenCLTSServer: Unable to reopen socket for %s\n",
729 thistrans->TransName, 0, 0);
733 /* Save the index for later use */
740 #endif /* TRANS_REOPEN */
744 TRANS(SocketSetOption) (ciptr, option, arg)
746 XtransConnInfo ciptr;
751 PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
760 TRANS(SocketCreateListener) (ciptr, sockname, socknamelen)
762 XtransConnInfo ciptr;
763 struct sockaddr *sockname;
767 int namelen = socknamelen;
771 PRMSG (3, "SocketCreateListener(%x,%d)\n", ciptr, fd, 0);
773 if (Sockettrans2devtab[ciptr->index].family == AF_INET)
778 while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
780 if (errno == EADDRINUSE)
781 return TRANS_ADDR_IN_USE;
784 PRMSG (1, "SocketCreateListener: failed to bind listener\n",
787 return TRANS_CREATE_LISTENER_FAILED;
793 #endif /* SO_REUSEDADDR */
796 if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
798 setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
802 static int linger[2] = { 0, 0 };
803 setsockopt (fd, SOL_SOCKET, SO_LINGER,
804 (char *) linger, sizeof (linger));
810 if (listen (fd, BACKLOG) < 0)
812 PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
814 return TRANS_CREATE_LISTENER_FAILED;
817 /* Set a flag to indicate that this connection is a listener */
827 TRANS(SocketINETCreateListener) (ciptr, port)
829 XtransConnInfo ciptr;
833 struct sockaddr_in sockname;
834 int namelen = sizeof(sockname);
837 _Xgetservbynameparams sparams;
838 struct servent *servp;
840 #define PORTBUFSIZE 64 /* what is a real size for this? */
842 char portbuf[PORTBUFSIZE];
844 PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
848 * X has a well known port, that is transport dependent. It is easier
849 * to handle it here, than try and come up with a transport independent
850 * representation that can be passed in and resolved the usual way.
852 * The port that is passed here is really a string containing the idisplay
853 * from ConnectDisplay().
856 if (is_numeric (port))
858 tmpport = (short) atoi (port);
860 sprintf (portbuf,"%d", X_TCP_PORT+tmpport);
863 strncpy (portbuf, port, PORTBUFSIZE);
870 /* Check to see if the port string is just a number (handles X11) */
872 if (!is_numeric (port))
874 if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
877 "SocketINETCreateListener: Unable to get service for %s\n",
879 return TRANS_CREATE_LISTENER_FAILED;
881 sockname.sin_port = servp->s_port;
885 tmpport = (short) atoi (port);
886 sockname.sin_port = htons (tmpport);
890 sockname.sin_port = htons (0);
893 sockname.sin_len = sizeof (sockname);
895 sockname.sin_family = AF_INET;
896 sockname.sin_addr.s_addr = htonl (INADDR_ANY);
898 if ((status = TRANS(SocketCreateListener) (ciptr,
899 (struct sockaddr *) &sockname, namelen)) < 0)
902 "SocketINETCreateListener: ...SocketCreateListener() failed\n",
907 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
910 "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
912 return TRANS_CREATE_LISTENER_FAILED;
918 #endif /* SOCKCONN */
924 TRANS(SocketUNIXCreateListener) (ciptr, port)
926 XtransConnInfo ciptr;
930 struct sockaddr_un sockname;
935 PRMSG (2, "SocketUNIXCreateListener(%s)\n",
936 port ? port : "NULL", 0, 0);
938 /* Make sure the directory is created */
940 oldUmask = umask (0);
943 if (!mkdir (UNIX_DIR, 01777))
944 chmod (UNIX_DIR, 01777);
947 sockname.sun_family = AF_UNIX;
950 if (*port == '/') { /* a full pathname */
951 sprintf (sockname.sun_path, "%s", port);
953 sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port);
956 sprintf (sockname.sun_path, "%s%d", UNIX_PATH, getpid());
959 #if defined(BSD44SOCKETS) && !defined(Lynx)
960 sockname.sun_len = strlen(sockname.sun_path);
961 namelen = SUN_LEN(&sockname);
963 namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
966 unlink (sockname.sun_path);
968 if ((status = TRANS(SocketCreateListener) (ciptr,
969 (struct sockaddr *) &sockname, namelen)) < 0)
972 "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
978 * Now that the listener is esablished, create the addr info for
979 * this connection. getpeername() doesn't work for UNIX Domain Sockets
980 * on some systems (hpux at least), so we will just do it manually, instead
981 * of calling something like TRANS(SocketUNIXGetAddr).
984 namelen = sizeof (sockname); /* this will always make it the same size */
986 if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
989 "SocketUNIXCreateListener: Can't allocate space for the addr\n",
991 return TRANS_CREATE_LISTENER_FAILED;
994 ciptr->family = sockname.sun_family;
995 ciptr->addrlen = namelen;
996 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
998 (void) umask (oldUmask);
1005 TRANS(SocketUNIXResetListener) (ciptr)
1007 XtransConnInfo ciptr;
1011 * See if the unix domain socket has disappeared. If it has, recreate it.
1014 struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
1016 int status = TRANS_RESET_NOOP;
1017 void TRANS(FreeConnInfo) ();
1019 PRMSG (3, "SocketUNIXResetListener(%x,%d)\n", ciptr, ciptr->fd, 0);
1021 if (stat (unsock->sun_path, &statb) == -1 ||
1022 ((statb.st_mode & S_IFMT) !=
1023 #if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO) || defined(sco) || !defined(S_IFSOCK)
1029 int oldUmask = umask (0);
1032 if (!mkdir (UNIX_DIR, 01777))
1033 chmod (UNIX_DIR, 01777);
1037 unlink (unsock->sun_path);
1039 if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
1041 TRANS(FreeConnInfo) (ciptr);
1042 return TRANS_RESET_FAILURE;
1045 if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
1048 TRANS(FreeConnInfo) (ciptr);
1049 return TRANS_RESET_FAILURE;
1052 if (listen (ciptr->fd, BACKLOG) < 0)
1055 TRANS(FreeConnInfo) (ciptr);
1056 return TRANS_RESET_FAILURE;
1061 status = TRANS_RESET_NEW_FD;
1067 #endif /* UNIXCONN */
1072 static XtransConnInfo
1073 TRANS(SocketINETAccept) (ciptr, status)
1075 XtransConnInfo ciptr;
1079 XtransConnInfo newciptr;
1080 struct sockaddr_in sockname;
1081 int namelen = sizeof(sockname);
1083 PRMSG (2, "SocketINETAccept(%x,%d)\n", ciptr, ciptr->fd, 0);
1085 if ((newciptr = (XtransConnInfo) xcalloc (
1086 1, sizeof(struct _XtransConnInfo))) == NULL)
1088 PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
1089 *status = TRANS_ACCEPT_BAD_MALLOC;
1093 if ((newciptr->fd = accept (ciptr->fd,
1094 (struct sockaddr *) &sockname, &namelen)) < 0)
1096 PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
1098 *status = TRANS_ACCEPT_FAILED;
1105 * turn off TCP coalescence for INET sockets
1109 setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
1110 (char *) &tmp, sizeof (int));
1115 * Get this address again because the transport may give a more
1116 * specific address now that a connection is established.
1119 if (TRANS(SocketINETGetAddr) (newciptr) < 0)
1122 "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
1124 close (newciptr->fd);
1126 *status = TRANS_ACCEPT_MISC_ERROR;
1130 if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
1133 "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
1135 close (newciptr->fd);
1136 if (newciptr->addr) xfree (newciptr->addr);
1138 *status = TRANS_ACCEPT_MISC_ERROR;
1147 #endif /* TCPCONN */
1151 static XtransConnInfo
1152 TRANS(SocketUNIXAccept) (ciptr, status)
1154 XtransConnInfo ciptr;
1158 XtransConnInfo newciptr;
1159 struct sockaddr_un sockname;
1160 #if defined(SVR4) || defined(SCO325)
1161 size_t namelen = sizeof sockname;
1163 int namelen = sizeof sockname;
1166 PRMSG (2, "SocketUNIXAccept(%x,%d)\n", ciptr, ciptr->fd, 0);
1168 if ((newciptr = (XtransConnInfo) xcalloc (
1169 1, sizeof(struct _XtransConnInfo))) == NULL)
1171 PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
1172 *status = TRANS_ACCEPT_BAD_MALLOC;
1176 if ((newciptr->fd = accept (ciptr->fd,
1177 (struct sockaddr *) &sockname, &namelen)) < 0)
1179 PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
1181 *status = TRANS_ACCEPT_FAILED;
1186 * Get the socket name and the peer name from the listener socket,
1187 * since this is unix domain.
1190 if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
1193 "SocketUNIXAccept: Can't allocate space for the addr\n",
1195 close (newciptr->fd);
1197 *status = TRANS_ACCEPT_BAD_MALLOC;
1202 newciptr->addrlen = ciptr->addrlen;
1203 memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
1205 if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
1208 "SocketUNIXAccept: Can't allocate space for the addr\n",
1210 close (newciptr->fd);
1211 if (newciptr->addr) xfree (newciptr->addr);
1213 *status = TRANS_ACCEPT_BAD_MALLOC;
1217 newciptr->peeraddrlen = ciptr->addrlen;
1218 memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
1220 newciptr->family = AF_UNIX;
1227 #endif /* UNIXCONN */
1229 #endif /* TRANS_SERVER */
1236 TRANS(SocketINETConnect) (ciptr, host, port)
1238 XtransConnInfo ciptr;
1243 struct sockaddr_in sockname;
1244 #if defined(SVR4) || defined(SCO325)
1245 size_t namelen = sizeof sockname;
1247 int namelen = sizeof sockname;
1249 _Xgethostbynameparams hparams;
1250 _Xgetservbynameparams sparams;
1251 struct hostent *hostp;
1252 struct servent *servp;
1254 #define PORTBUFSIZE 64 /* what is a real size for this? */
1255 char portbuf[PORTBUFSIZE];
1259 unsigned long tmpaddr;
1260 char hostnamebuf[256]; /* tmp space */
1262 PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1266 hostnamebuf[0] = '\0';
1267 (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
1273 * X has a well known port, that is transport dependent. It is easier
1274 * to handle it here, than try and come up with a transport independent
1275 * representation that can be passed in and resolved the usual way.
1277 * The port that is passed here is really a string containing the idisplay
1278 * from ConnectDisplay().
1281 if (is_numeric (port))
1283 tmpport = (short) atoi (port);
1285 sprintf (portbuf, "%d", X_TCP_PORT + tmpport);
1289 strncpy (portbuf, port, PORTBUFSIZE);
1292 * Build the socket name.
1296 sockname.sin_len = sizeof (struct sockaddr_in);
1298 sockname.sin_family = AF_INET;
1304 /* check for ww.xx.yy.zz host string */
1306 if (isascii (host[0]) && isdigit (host[0])) {
1307 tmpaddr = inet_addr (host); /* returns network byte order */
1312 PRMSG (4,"SocketINETConnect: inet_addr(%s) = %x\n",
1317 if ((hostp = _XGethostbyname(host,hparams)) == NULL)
1319 PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
1322 return TRANS_CONNECT_FAILED;
1324 if (hostp->h_addrtype != AF_INET) /* is IP host? */
1326 PRMSG (1,"SocketINETConnect: not INET host%s\n",
1329 return TRANS_CONNECT_FAILED;
1332 #if defined(CRAY) && defined(OLDTCP)
1333 /* Only Cray UNICOS3 and UNICOS4 will define this */
1336 memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
1337 sockname.sin_addr = t;
1340 memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
1341 sizeof (sockname.sin_addr));
1342 #endif /* CRAY and OLDTCP */
1347 #if defined(CRAY) && defined(OLDTCP)
1348 /* Only Cray UNICOS3 and UNICOS4 will define this */
1349 sockname.sin_addr = tmpaddr;
1351 sockname.sin_addr.s_addr = tmpaddr;
1352 #endif /* CRAY and OLDTCP */
1359 /* Check for number in the port string */
1361 if (!is_numeric (portbuf))
1363 if ((servp = _XGetservbyname (portbuf,"tcp",sparams)) == NULL)
1365 PRMSG (1,"SocketINETConnect: Can't get service for %s\n",
1367 return TRANS_CONNECT_FAILED;
1369 sockname.sin_port = servp->s_port;
1373 tmpport = (short) atoi (portbuf);
1374 sockname.sin_port = htons (tmpport);
1377 PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
1378 ntohs(sockname.sin_port), 0, 0);
1384 if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
1387 int olderrno = WSAGetLastError();
1389 int olderrno = errno;
1392 PRMSG (1,"SocketINETConnect: Can't connect: errno = %d\n",
1396 * If the error was ECONNREFUSED, the server may be overloaded
1397 * and we should try again.
1399 * If the error was EINTR, the connect was interrupted and we
1403 if (olderrno == ECONNREFUSED || olderrno == EINTR)
1404 return TRANS_TRY_CONNECT_AGAIN;
1406 return TRANS_CONNECT_FAILED;
1411 * Sync up the address fields of ciptr.
1414 if (TRANS(SocketINETGetAddr) (ciptr) < 0)
1417 "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
1419 return TRANS_CONNECT_FAILED;
1422 if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
1425 "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
1427 return TRANS_CONNECT_FAILED;
1433 #endif /* TCPCONN */
1440 * Make sure 'host' is really local.
1444 UnixHostReallyLocal (host)
1449 char hostnamebuf[256];
1451 TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
1453 if (strcmp (hostnamebuf, host) == 0)
1460 * A host may have more than one network address. If any of the
1461 * network addresses of 'host' (specified to the connect call)
1462 * match any of the network addresses of 'hostname' (determined
1463 * by TRANS(GetHostname)), then the two hostnames are equivalent,
1464 * and we know that 'host' is really a local host.
1466 char specified_local_addr_list[10][4];
1467 int scount, equiv, i, j;
1468 _Xgethostbynameparams hparams;
1469 struct hostent *hostp;
1471 if ((hostp = _XGethostbyname (host,hparams)) == NULL)
1475 while (hostp->h_addr_list[scount] && scount <= 8)
1478 * The 2nd call to gethostname() overrides the data
1479 * from the 1st call, so we must save the address list.
1482 specified_local_addr_list[scount][0] =
1483 hostp->h_addr_list[scount][0];
1484 specified_local_addr_list[scount][1] =
1485 hostp->h_addr_list[scount][1];
1486 specified_local_addr_list[scount][2] =
1487 hostp->h_addr_list[scount][2];
1488 specified_local_addr_list[scount][3] =
1489 hostp->h_addr_list[scount][3];
1492 if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
1498 while (i < scount && !equiv)
1502 while (hostp->h_addr_list[j])
1504 if ((specified_local_addr_list[i][0] ==
1505 hostp->h_addr_list[j][0]) &&
1506 (specified_local_addr_list[i][1] ==
1507 hostp->h_addr_list[j][1]) &&
1508 (specified_local_addr_list[i][2] ==
1509 hostp->h_addr_list[j][2]) &&
1510 (specified_local_addr_list[i][3] ==
1511 hostp->h_addr_list[j][3]))
1513 /* They're equal, so we're done */
1530 TRANS(SocketUNIXConnect) (ciptr, host, port)
1532 XtransConnInfo ciptr;
1537 struct sockaddr_un sockname;
1540 #if defined(hpux) && defined(X11_t)
1541 struct sockaddr_un old_sockname;
1546 PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1549 * Make sure 'host' is really local. If not, we return failure.
1550 * The reason we make this check is because a process may advertise
1551 * a "local" network ID for which it can accept connections, but if
1552 * a process on a remote machine tries to connect to this network ID,
1553 * we know for sure it will fail.
1556 if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
1559 "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1561 return TRANS_CONNECT_FAILED;
1569 if (!port || !*port)
1571 PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
1573 return TRANS_CONNECT_FAILED;
1577 * Build the socket name.
1580 sockname.sun_family = AF_UNIX;
1582 if (*port == '/') { /* a full pathname */
1583 sprintf (sockname.sun_path, "%s", port);
1585 sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port);
1588 #if defined(BSD44SOCKETS) && !defined(Lynx)
1589 sockname.sun_len = strlen (sockname.sun_path);
1590 namelen = SUN_LEN (&sockname);
1592 namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family);
1596 #if defined(hpux) && defined(X11_t)
1598 * This is gross, but it was in Xlib
1600 old_sockname.sun_family = AF_UNIX;
1601 if (*port == '/') { /* a full pathname */
1602 sprintf (old_sockname.sun_path, "%s", port);
1604 sprintf (old_sockname.sun_path, "%s%s", OLD_UNIX_PATH, port);
1606 old_namelen = strlen (old_sockname.sun_path) +
1607 sizeof (old_sockname.sun_family);
1615 if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
1617 int olderrno = errno;
1620 #if defined(hpux) && defined(X11_t)
1621 if (olderrno == ENOENT)
1623 if (connect (ciptr->fd,
1624 (struct sockaddr *) &old_sockname, old_namelen) >= 0)
1636 PRMSG (1,"SocketUNIXConnect: Can't connect: errno = %d\n",
1639 if (olderrno == ENOENT || olderrno == EINTR)
1640 return TRANS_TRY_CONNECT_AGAIN;
1642 return TRANS_CONNECT_FAILED;
1647 * Get the socket name and the peer name from the connect socket,
1648 * since this is unix domain.
1651 if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
1652 (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
1655 "SocketUNIXCreateListener: Can't allocate space for the addr\n",
1657 return TRANS_CONNECT_FAILED;
1660 ciptr->family = AF_UNIX;
1661 ciptr->addrlen = namelen;
1662 ciptr->peeraddrlen = namelen;
1663 memcpy (ciptr->addr, &sockname, ciptr->addrlen);
1664 memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
1669 #endif /* UNIXCONN */
1671 #endif /* TRANS_CLIENT */
1675 TRANS(SocketBytesReadable) (ciptr, pend)
1677 XtransConnInfo ciptr;
1678 BytesReadable_t *pend;
1680 PRMSG (2,"SocketBytesReadable(%x,%d,%x)\n",
1681 ciptr, ciptr->fd, pend);
1684 return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
1686 #if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
1687 return ioctl (ciptr->fd, I_NREAD, (char *) pend);
1689 #if defined(__EMX__)
1690 return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
1692 return ioctl (ciptr->fd, FIONREAD, (char *) pend);
1693 #endif /* __EMX__ */
1694 #endif /* i386 && SYSV && !SCO || _SEQUENT_ */
1700 TRANS(SocketRead) (ciptr, buf, size)
1702 XtransConnInfo ciptr;
1707 PRMSG (2,"SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size);
1709 #if defined(WIN32) || defined(__EMX__)
1710 return recv ((SOCKET)ciptr->fd, buf, size, 0);
1712 return read (ciptr->fd, buf, size);
1718 TRANS(SocketWrite) (ciptr, buf, size)
1720 XtransConnInfo ciptr;
1725 PRMSG (2,"SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
1727 #if defined(WIN32) || defined(__EMX__)
1728 return send ((SOCKET)ciptr->fd, buf, size, 0);
1730 return write (ciptr->fd, buf, size);
1736 TRANS(SocketReadv) (ciptr, buf, size)
1738 XtransConnInfo ciptr;
1743 PRMSG (2,"SocketReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
1745 return READV (ciptr, buf, size);
1750 TRANS(SocketWritev) (ciptr, buf, size)
1752 XtransConnInfo ciptr;
1757 PRMSG (2,"SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
1759 return WRITEV (ciptr, buf, size);
1764 TRANS(SocketDisconnect) (ciptr)
1766 XtransConnInfo ciptr;
1769 PRMSG (2,"SocketDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
1771 return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
1777 TRANS(SocketINETClose) (ciptr)
1779 XtransConnInfo ciptr;
1782 PRMSG (2,"SocketINETClose(%x,%d)\n", ciptr, ciptr->fd, 0);
1784 return close (ciptr->fd);
1787 #endif /* TCPCONN */
1792 TRANS(SocketUNIXClose) (ciptr)
1794 XtransConnInfo ciptr;
1798 * If this is the server side, then once the socket is closed,
1799 * it must be unlinked to completely close it
1802 struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
1803 char path[200]; /* > sizeof sun_path +1 */
1806 PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
1808 ret = close(ciptr->fd);
1812 && sockname->sun_family == AF_UNIX
1813 && sockname->sun_path[0])
1815 strncpy (path, sockname->sun_path,
1816 ciptr->addrlen - sizeof (sockname->sun_family));
1824 TRANS(SocketUNIXCloseForCloning) (ciptr)
1826 XtransConnInfo ciptr;
1830 * Don't unlink path.
1835 PRMSG (2,"SocketUNIXCloseForCloning(%x,%d)\n",
1836 ciptr, ciptr->fd, 0);
1838 ret = close(ciptr->fd);
1843 #endif /* UNIXCONN */
1847 Xtransport TRANS(SocketTCPFuncs) = {
1848 /* Socket Interface */
1852 TRANS(SocketOpenCOTSClient),
1853 #endif /* TRANS_CLIENT */
1855 TRANS(SocketOpenCOTSServer),
1856 #endif /* TRANS_SERVER */
1858 TRANS(SocketOpenCLTSClient),
1859 #endif /* TRANS_CLIENT */
1861 TRANS(SocketOpenCLTSServer),
1862 #endif /* TRANS_SERVER */
1864 TRANS(SocketReopenCOTSServer),
1865 TRANS(SocketReopenCLTSServer),
1867 TRANS(SocketSetOption),
1869 TRANS(SocketINETCreateListener),
1870 NULL, /* ResetListener */
1871 TRANS(SocketINETAccept),
1872 #endif /* TRANS_SERVER */
1874 TRANS(SocketINETConnect),
1875 #endif /* TRANS_CLIENT */
1876 TRANS(SocketBytesReadable),
1880 TRANS(SocketWritev),
1881 TRANS(SocketDisconnect),
1882 TRANS(SocketINETClose),
1883 TRANS(SocketINETClose),
1886 Xtransport TRANS(SocketINETFuncs) = {
1887 /* Socket Interface */
1891 TRANS(SocketOpenCOTSClient),
1892 #endif /* TRANS_CLIENT */
1894 TRANS(SocketOpenCOTSServer),
1895 #endif /* TRANS_SERVER */
1897 TRANS(SocketOpenCLTSClient),
1898 #endif /* TRANS_CLIENT */
1900 TRANS(SocketOpenCLTSServer),
1901 #endif /* TRANS_SERVER */
1903 TRANS(SocketReopenCOTSServer),
1904 TRANS(SocketReopenCLTSServer),
1906 TRANS(SocketSetOption),
1908 TRANS(SocketINETCreateListener),
1909 NULL, /* ResetListener */
1910 TRANS(SocketINETAccept),
1911 #endif /* TRANS_SERVER */
1913 TRANS(SocketINETConnect),
1914 #endif /* TRANS_CLIENT */
1915 TRANS(SocketBytesReadable),
1919 TRANS(SocketWritev),
1920 TRANS(SocketDisconnect),
1921 TRANS(SocketINETClose),
1922 TRANS(SocketINETClose),
1925 #endif /* TCPCONN */
1928 #if !defined(LOCALCONN)
1929 Xtransport TRANS(SocketLocalFuncs) = {
1930 /* Socket Interface */
1934 TRANS(SocketOpenCOTSClient),
1935 #endif /* TRANS_CLIENT */
1937 TRANS(SocketOpenCOTSServer),
1938 #endif /* TRANS_SERVER */
1940 TRANS(SocketOpenCLTSClient),
1941 #endif /* TRANS_CLIENT */
1943 TRANS(SocketOpenCLTSServer),
1944 #endif /* TRANS_SERVER */
1946 TRANS(SocketReopenCOTSServer),
1947 TRANS(SocketReopenCLTSServer),
1949 TRANS(SocketSetOption),
1951 TRANS(SocketUNIXCreateListener),
1952 TRANS(SocketUNIXResetListener),
1953 TRANS(SocketUNIXAccept),
1954 #endif /* TRANS_SERVER */
1956 TRANS(SocketUNIXConnect),
1957 #endif /* TRANS_CLIENT */
1958 TRANS(SocketBytesReadable),
1962 TRANS(SocketWritev),
1963 TRANS(SocketDisconnect),
1964 TRANS(SocketUNIXClose),
1965 TRANS(SocketUNIXCloseForCloning),
1967 #endif /* !LOCALCONN */
1969 Xtransport TRANS(SocketUNIXFuncs) = {
1970 /* Socket Interface */
1972 #if !defined(LOCALCONN)
1978 TRANS(SocketOpenCOTSClient),
1979 #endif /* TRANS_CLIENT */
1981 TRANS(SocketOpenCOTSServer),
1982 #endif /* TRANS_SERVER */
1984 TRANS(SocketOpenCLTSClient),
1985 #endif /* TRANS_CLIENT */
1987 TRANS(SocketOpenCLTSServer),
1988 #endif /* TRANS_SERVER */
1990 TRANS(SocketReopenCOTSServer),
1991 TRANS(SocketReopenCLTSServer),
1993 TRANS(SocketSetOption),
1995 TRANS(SocketUNIXCreateListener),
1996 TRANS(SocketUNIXResetListener),
1997 TRANS(SocketUNIXAccept),
1998 #endif /* TRANS_SERVER */
2000 TRANS(SocketUNIXConnect),
2001 #endif /* TRANS_CLIENT */
2002 TRANS(SocketBytesReadable),
2006 TRANS(SocketWritev),
2007 TRANS(SocketDisconnect),
2008 TRANS(SocketUNIXClose),
2009 TRANS(SocketUNIXCloseForCloning),
2012 #endif /* UNIXCONN */