Xtranssock.c revision 81d6fa61
1af928962Smrg/*
2af928962Smrg * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
3af928962Smrg *
4af928962Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5af928962Smrg * copy of this software and associated documentation files (the "Software"),
6af928962Smrg * to deal in the Software without restriction, including without limitation
7af928962Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8af928962Smrg * and/or sell copies of the Software, and to permit persons to whom the
9af928962Smrg * Software is furnished to do so, subject to the following conditions:
10af928962Smrg *
11af928962Smrg * The above copyright notice and this permission notice (including the next
12af928962Smrg * paragraph) shall be included in all copies or substantial portions of the
13af928962Smrg * Software.
14af928962Smrg *
15af928962Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af928962Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af928962Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af928962Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19af928962Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20af928962Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21af928962Smrg * DEALINGS IN THE SOFTWARE.
22af928962Smrg */
2373143b9aSmrg/*
2473143b9aSmrg
2573143b9aSmrgCopyright 1993, 1994, 1998  The Open Group
2673143b9aSmrg
2773143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its
2873143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that
2973143b9aSmrgthe above copyright notice appear in all copies and that both that
3073143b9aSmrgcopyright notice and this permission notice appear in supporting
3173143b9aSmrgdocumentation.
3273143b9aSmrg
3373143b9aSmrgThe above copyright notice and this permission notice shall be included
3473143b9aSmrgin all copies or substantial portions of the Software.
3573143b9aSmrg
3673143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3773143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3873143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3973143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
4073143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4173143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4273143b9aSmrgOTHER DEALINGS IN THE SOFTWARE.
4373143b9aSmrg
4473143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall
4573143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or
4673143b9aSmrgother dealings in this Software without prior written authorization
4773143b9aSmrgfrom the copyright holders.
4873143b9aSmrg
4973143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
5073143b9aSmrg *
5173143b9aSmrg * All Rights Reserved
5273143b9aSmrg *
5373143b9aSmrg * Permission to use, copy, modify, and distribute this software and its
5473143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided
5573143b9aSmrg * that the above copyright notice appear in all copies and that both that
5673143b9aSmrg * copyright notice and this permission notice appear in supporting
5773143b9aSmrg * documentation, and that the name NCR not be used in advertising
5873143b9aSmrg * or publicity pertaining to distribution of the software without specific,
5973143b9aSmrg * written prior permission.  NCR makes no representations about the
6073143b9aSmrg * suitability of this software for any purpose.  It is provided "as is"
6173143b9aSmrg * without express or implied warranty.
6273143b9aSmrg *
6373143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
6473143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
6573143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
6673143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
6773143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
6873143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
6973143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7073143b9aSmrg */
7173143b9aSmrg
7273143b9aSmrg#include <ctype.h>
7373143b9aSmrg#ifdef XTHREADS
7473143b9aSmrg#include <X11/Xthreads.h>
7573143b9aSmrg#endif
7673143b9aSmrg
7773143b9aSmrg#ifndef WIN32
7873143b9aSmrg
7973143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
8073143b9aSmrg#include <sys/socket.h>
8173143b9aSmrg#include <netinet/in.h>
8273143b9aSmrg#include <arpa/inet.h>
8373143b9aSmrg#endif
8473143b9aSmrg
8573143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
8673143b9aSmrg#define X_INCLUDE_NETDB_H
8773143b9aSmrg#define XOS_USE_NO_LOCKING
8873143b9aSmrg#include <X11/Xos_r.h>
8973143b9aSmrg#endif
9073143b9aSmrg
9173143b9aSmrg#ifdef UNIXCONN
9273143b9aSmrg#ifndef X_NO_SYS_UN
9373143b9aSmrg#include <sys/un.h>
9473143b9aSmrg#endif
9573143b9aSmrg#include <sys/stat.h>
9673143b9aSmrg#endif
9773143b9aSmrg
9873143b9aSmrg
9973143b9aSmrg#ifndef NO_TCP_H
100fe567363Smrg#if defined(linux) || defined(__GLIBC__)
10173143b9aSmrg#include <sys/param.h>
10273143b9aSmrg#endif /* osf */
10373143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
10473143b9aSmrg#include <sys/param.h>
10573143b9aSmrg#include <machine/endian.h>
10673143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
10773143b9aSmrg#include <netinet/tcp.h>
10873143b9aSmrg#endif /* !NO_TCP_H */
10973143b9aSmrg
11073143b9aSmrg#include <sys/ioctl.h>
111e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
11273143b9aSmrg#include <sys/filio.h>
11373143b9aSmrg#endif
11473143b9aSmrg
11573143b9aSmrg#if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
11673143b9aSmrg#include <net/errno.h>
117fe567363Smrg#endif
11873143b9aSmrg
119fe567363Smrg#if defined(__i386__) && defined(SYSV)
12073143b9aSmrg#include <sys/stropts.h>
121fe567363Smrg#endif
12273143b9aSmrg
1238d4c0f7bSmrg#include <unistd.h>
1248d4c0f7bSmrg
12573143b9aSmrg#else /* !WIN32 */
12673143b9aSmrg
12773143b9aSmrg#include <X11/Xwinsock.h>
12873143b9aSmrg#include <X11/Xwindows.h>
12973143b9aSmrg#include <X11/Xw32defs.h>
13073143b9aSmrg#undef close
13173143b9aSmrg#define close closesocket
13273143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED
13373143b9aSmrg#define EADDRINUSE WSAEADDRINUSE
13473143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE
13573143b9aSmrg#undef EWOULDBLOCK
13673143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK
13773143b9aSmrg#define EINPROGRESS WSAEINPROGRESS
13873143b9aSmrg#undef EINTR
13973143b9aSmrg#define EINTR WSAEINTR
14073143b9aSmrg#define X_INCLUDE_NETDB_H
14173143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI
14273143b9aSmrg#include <X11/Xos_r.h>
14373143b9aSmrg#endif /* WIN32 */
14473143b9aSmrg
14573143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER)
14673143b9aSmrg#undef SO_DONTLINGER
14773143b9aSmrg#endif
14873143b9aSmrg
14973143b9aSmrg/* others don't need this */
15073143b9aSmrg#define SocketInitOnce() /**/
15173143b9aSmrg
15273143b9aSmrg#ifdef linux
15373143b9aSmrg#define HAVE_ABSTRACT_SOCKETS
15473143b9aSmrg#endif
15573143b9aSmrg
15673143b9aSmrg#define MIN_BACKLOG 128
15773143b9aSmrg#ifdef SOMAXCONN
15873143b9aSmrg#if SOMAXCONN > MIN_BACKLOG
15973143b9aSmrg#define BACKLOG SOMAXCONN
16073143b9aSmrg#endif
16173143b9aSmrg#endif
16273143b9aSmrg#ifndef BACKLOG
16373143b9aSmrg#define BACKLOG MIN_BACKLOG
16473143b9aSmrg#endif
16573143b9aSmrg
16673143b9aSmrg/*
16773143b9aSmrg * This is the Socket implementation of the X Transport service layer
16873143b9aSmrg *
16973143b9aSmrg * This file contains the implementation for both the UNIX and INET domains,
17073143b9aSmrg * and can be built for either one, or both.
17173143b9aSmrg *
17273143b9aSmrg */
17373143b9aSmrg
174fe567363Smrgtypedef struct _Sockettrans2dev {
175fe567363Smrg    const char	*transname;
17673143b9aSmrg    int		family;
17773143b9aSmrg    int		devcotsname;
17873143b9aSmrg    int		devcltsname;
17973143b9aSmrg    int		protocol;
18073143b9aSmrg} Sockettrans2dev;
18173143b9aSmrg
18273143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = {
18373143b9aSmrg#ifdef TCPCONN
18473143b9aSmrg    {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
18573143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6)
18673143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
18773143b9aSmrg#else /* IPv6 */
18873143b9aSmrg    {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
18973143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
19073143b9aSmrg    {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
19173143b9aSmrg#endif
19273143b9aSmrg#endif /* TCPCONN */
19373143b9aSmrg#ifdef UNIXCONN
19473143b9aSmrg    {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
19573143b9aSmrg#if !defined(LOCALCONN)
19673143b9aSmrg    {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
19773143b9aSmrg#endif /* !LOCALCONN */
19873143b9aSmrg#endif /* UNIXCONN */
19973143b9aSmrg};
20073143b9aSmrg
20173143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
20273143b9aSmrg
20373143b9aSmrg#ifdef TCPCONN
20473143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr);
20573143b9aSmrg#endif
20673143b9aSmrg
20773143b9aSmrg#ifdef UNIXCONN
20873143b9aSmrg
20973143b9aSmrg
21073143b9aSmrg#if defined(X11_t)
21173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
21273143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix"
21373143b9aSmrg#endif /* X11_t */
21473143b9aSmrg#if defined(XIM_t)
21573143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM"
21673143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix"
21773143b9aSmrg#endif /* XIM_t */
21873143b9aSmrg#if defined(FS_t) || defined(FONT_t)
21973143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs"
22073143b9aSmrg#define UNIX_DIR "/tmp/.font-unix"
22173143b9aSmrg#endif /* FS_t || FONT_t */
22273143b9aSmrg#if defined(ICE_t)
22373143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/"
22473143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix"
22573143b9aSmrg#endif /* ICE_t */
22673143b9aSmrg#if defined(TEST_t)
22773143b9aSmrg#define UNIX_PATH "/tmp/.Test-unix/test"
22873143b9aSmrg#define UNIX_DIR "/tmp/.Test-unix"
22973143b9aSmrg#endif
23073143b9aSmrg#if defined(LBXPROXY_t)
23173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
23273143b9aSmrg#define UNIX_DIR  "/tmp/.X11-unix"
23373143b9aSmrg#endif
23473143b9aSmrg
23573143b9aSmrg
23673143b9aSmrg#endif /* UNIXCONN */
23773143b9aSmrg
23873143b9aSmrg#define PORTBUFSIZE	32
23973143b9aSmrg
24073143b9aSmrg#ifndef MAXHOSTNAMELEN
24173143b9aSmrg#define MAXHOSTNAMELEN 255
24273143b9aSmrg#endif
24373143b9aSmrg
24473143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6))
24573143b9aSmrg# define SOCKLEN_T socklen_t
246e8a71cdfSmrg#elif defined(SVR4) || defined(__SVR4) || defined(__SCO__)
247fe567363Smrg# define SOCKLEN_T size_t
24873143b9aSmrg#else
24973143b9aSmrg# define SOCKLEN_T int
25073143b9aSmrg#endif
25173143b9aSmrg
25273143b9aSmrg/*
25373143b9aSmrg * These are some utility function used by the real interface function below.
25473143b9aSmrg */
25573143b9aSmrg
25673143b9aSmrgstatic int
257fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family)
25873143b9aSmrg
25973143b9aSmrg{
26073143b9aSmrg    int     i;
26173143b9aSmrg
262fe567363Smrg    prmsg (3,"SocketSelectFamily(%s)\n", family);
26373143b9aSmrg
26473143b9aSmrg    for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
26573143b9aSmrg    {
26673143b9aSmrg        if (!strcmp (family, Sockettrans2devtab[i].transname))
26773143b9aSmrg	    return i;
26873143b9aSmrg    }
26973143b9aSmrg
27073143b9aSmrg    return (first == -1 ? -2 : -1);
27173143b9aSmrg}
27273143b9aSmrg
27373143b9aSmrg
27473143b9aSmrg/*
27573143b9aSmrg * This function gets the local address of the socket and stores it in the
27673143b9aSmrg * XtransConnInfo structure for the connection.
27773143b9aSmrg */
27873143b9aSmrg
27973143b9aSmrgstatic int
28073143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
28173143b9aSmrg
28273143b9aSmrg{
28373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
28473143b9aSmrg    struct sockaddr_storage socknamev6;
285b53e5eeaSmrg#else
28673143b9aSmrg    struct sockaddr_in socknamev4;
287b53e5eeaSmrg#endif
28873143b9aSmrg    void *socknamePtr;
28973143b9aSmrg    SOCKLEN_T namelen;
29073143b9aSmrg
291fe567363Smrg    prmsg (3,"SocketINETGetAddr(%p)\n", ciptr);
29273143b9aSmrg
29373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
294b53e5eeaSmrg    namelen = sizeof(socknamev6);
295b53e5eeaSmrg    socknamePtr = &socknamev6;
296b53e5eeaSmrg#else
297b53e5eeaSmrg    namelen = sizeof(socknamev4);
298b53e5eeaSmrg    socknamePtr = &socknamev4;
29973143b9aSmrg#endif
30073143b9aSmrg
30173143b9aSmrg    bzero(socknamePtr, namelen);
302fe567363Smrg
30373143b9aSmrg    if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
30473143b9aSmrg		     (void *)&namelen) < 0)
30573143b9aSmrg    {
30673143b9aSmrg#ifdef WIN32
30773143b9aSmrg	errno = WSAGetLastError();
30873143b9aSmrg#endif
309fe567363Smrg	prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n",
310fe567363Smrg	    EGET());
31173143b9aSmrg	return -1;
31273143b9aSmrg    }
31373143b9aSmrg
31473143b9aSmrg    /*
31573143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
31673143b9aSmrg     */
31773143b9aSmrg
318fe567363Smrg    if ((ciptr->addr = malloc (namelen)) == NULL)
31973143b9aSmrg    {
320fe567363Smrg        prmsg (1,
321fe567363Smrg	    "SocketINETGetAddr: Can't allocate space for the addr\n");
32273143b9aSmrg        return -1;
32373143b9aSmrg    }
32473143b9aSmrg
32573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
326b53e5eeaSmrg    ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
327b53e5eeaSmrg#else
328b53e5eeaSmrg    ciptr->family = socknamev4.sin_family;
32973143b9aSmrg#endif
33073143b9aSmrg    ciptr->addrlen = namelen;
33173143b9aSmrg    memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
33273143b9aSmrg
33373143b9aSmrg    return 0;
33473143b9aSmrg}
33573143b9aSmrg
33673143b9aSmrg
33773143b9aSmrg/*
33873143b9aSmrg * This function gets the remote address of the socket and stores it in the
33973143b9aSmrg * XtransConnInfo structure for the connection.
34073143b9aSmrg */
34173143b9aSmrg
34273143b9aSmrgstatic int
34373143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
34473143b9aSmrg
34573143b9aSmrg{
34673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
34773143b9aSmrg    struct sockaddr_storage socknamev6;
34873143b9aSmrg#endif
34973143b9aSmrg    struct sockaddr_in 	socknamev4;
35073143b9aSmrg    void *socknamePtr;
35173143b9aSmrg    SOCKLEN_T namelen;
35273143b9aSmrg
35373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
354b53e5eeaSmrg    if (ciptr->family == AF_INET6)
35573143b9aSmrg    {
35673143b9aSmrg	namelen = sizeof(socknamev6);
35773143b9aSmrg	socknamePtr = &socknamev6;
35873143b9aSmrg    }
35973143b9aSmrg    else
36073143b9aSmrg#endif
36173143b9aSmrg    {
36273143b9aSmrg	namelen = sizeof(socknamev4);
36373143b9aSmrg	socknamePtr = &socknamev4;
36473143b9aSmrg    }
36573143b9aSmrg
36673143b9aSmrg    bzero(socknamePtr, namelen);
367fe567363Smrg
368fe567363Smrg    prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr);
36973143b9aSmrg
37073143b9aSmrg    if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
37173143b9aSmrg		     (void *)&namelen) < 0)
37273143b9aSmrg    {
37373143b9aSmrg#ifdef WIN32
37473143b9aSmrg	errno = WSAGetLastError();
37573143b9aSmrg#endif
376fe567363Smrg	prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
377fe567363Smrg	    EGET());
37873143b9aSmrg	return -1;
37973143b9aSmrg    }
38073143b9aSmrg
38173143b9aSmrg    /*
38273143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
38373143b9aSmrg     */
38473143b9aSmrg
385fe567363Smrg    if ((ciptr->peeraddr = malloc (namelen)) == NULL)
38673143b9aSmrg    {
387fe567363Smrg        prmsg (1,
388fe567363Smrg	   "SocketINETGetPeerAddr: Can't allocate space for the addr\n");
38973143b9aSmrg        return -1;
39073143b9aSmrg    }
39173143b9aSmrg
39273143b9aSmrg    ciptr->peeraddrlen = namelen;
39373143b9aSmrg    memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
39473143b9aSmrg
39573143b9aSmrg    return 0;
39673143b9aSmrg}
39773143b9aSmrg
39873143b9aSmrg
39973143b9aSmrgstatic XtransConnInfo
40073143b9aSmrgTRANS(SocketOpen) (int i, int type)
40173143b9aSmrg
40273143b9aSmrg{
40373143b9aSmrg    XtransConnInfo	ciptr;
40473143b9aSmrg
405fe567363Smrg    prmsg (3,"SocketOpen(%d,%d)\n", i, type);
40673143b9aSmrg
407fe567363Smrg    if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
40873143b9aSmrg    {
409fe567363Smrg	prmsg (1, "SocketOpen: malloc failed\n");
41073143b9aSmrg	return NULL;
41173143b9aSmrg    }
41273143b9aSmrg
41373143b9aSmrg    if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
41473143b9aSmrg	Sockettrans2devtab[i].protocol)) < 0
41573143b9aSmrg#ifndef WIN32
41673143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
4178d4c0f7bSmrg       || ciptr->fd >= sysconf(_SC_OPEN_MAX)
41873143b9aSmrg#endif
41973143b9aSmrg#endif
42073143b9aSmrg      ) {
42173143b9aSmrg#ifdef WIN32
42273143b9aSmrg	errno = WSAGetLastError();
42373143b9aSmrg#endif
424fe567363Smrg	prmsg (2, "SocketOpen: socket() failed for %s\n",
425fe567363Smrg	    Sockettrans2devtab[i].transname);
42673143b9aSmrg
427fe567363Smrg	free (ciptr);
42873143b9aSmrg	return NULL;
42973143b9aSmrg    }
43073143b9aSmrg
43173143b9aSmrg#ifdef TCP_NODELAY
43273143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
43373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
43473143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
43573143b9aSmrg#endif
43673143b9aSmrg    )
43773143b9aSmrg    {
43873143b9aSmrg	/*
43973143b9aSmrg	 * turn off TCP coalescence for INET sockets
44073143b9aSmrg	 */
44173143b9aSmrg
44273143b9aSmrg	int tmp = 1;
44373143b9aSmrg	setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
44473143b9aSmrg	    (char *) &tmp, sizeof (int));
44573143b9aSmrg    }
44673143b9aSmrg#endif
44773143b9aSmrg
4488a0d9095Smrg    /*
4498a0d9095Smrg     * Some systems provide a really small default buffer size for
4508a0d9095Smrg     * UNIX sockets.  Bump it up a bit such that large transfers don't
4518a0d9095Smrg     * proceed at glacial speed.
4528a0d9095Smrg     */
4538a0d9095Smrg#ifdef SO_SNDBUF
4548a0d9095Smrg    if (Sockettrans2devtab[i].family == AF_UNIX)
4558a0d9095Smrg    {
4568a0d9095Smrg	SOCKLEN_T len = sizeof (int);
4578a0d9095Smrg	int val;
4588a0d9095Smrg
4598a0d9095Smrg	if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF,
4608a0d9095Smrg	    (char *) &val, &len) == 0 && val < 64 * 1024)
4618a0d9095Smrg	{
4628a0d9095Smrg	    val = 64 * 1024;
4638a0d9095Smrg	    setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF,
4648a0d9095Smrg	        (char *) &val, sizeof (int));
4658a0d9095Smrg	}
4668a0d9095Smrg    }
4678a0d9095Smrg#endif
4688a0d9095Smrg
46973143b9aSmrg    return ciptr;
47073143b9aSmrg}
47173143b9aSmrg
47273143b9aSmrg
47373143b9aSmrg#ifdef TRANS_REOPEN
47473143b9aSmrg
47573143b9aSmrgstatic XtransConnInfo
4766a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port)
47773143b9aSmrg
47873143b9aSmrg{
47973143b9aSmrg    XtransConnInfo	ciptr;
48073143b9aSmrg    int portlen;
48173143b9aSmrg    struct sockaddr *addr;
482fe567363Smrg    size_t addrlen;
48373143b9aSmrg
484fe567363Smrg    prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
48573143b9aSmrg
48673143b9aSmrg    if (port == NULL) {
487fe567363Smrg      prmsg (1, "SocketReopen: port was null!\n");
48873143b9aSmrg      return NULL;
48973143b9aSmrg    }
49073143b9aSmrg
49173143b9aSmrg    portlen = strlen(port) + 1; // include space for trailing null
49273143b9aSmrg#ifdef SOCK_MAXADDRLEN
49373143b9aSmrg    if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
494fe567363Smrg      prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
49573143b9aSmrg      return NULL;
49673143b9aSmrg    }
49773143b9aSmrg    if (portlen < 14) portlen = 14;
49873143b9aSmrg#else
49973143b9aSmrg    if (portlen < 0 || portlen > 14) {
500fe567363Smrg      prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
50173143b9aSmrg      return NULL;
50273143b9aSmrg    }
50373143b9aSmrg#endif /*SOCK_MAXADDRLEN*/
50473143b9aSmrg
505fe567363Smrg    if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
50673143b9aSmrg    {
507fe567363Smrg	prmsg (1, "SocketReopen: malloc(ciptr) failed\n");
50873143b9aSmrg	return NULL;
50973143b9aSmrg    }
51073143b9aSmrg
51173143b9aSmrg    ciptr->fd = fd;
51273143b9aSmrg
513fe567363Smrg    addrlen = portlen + offsetof(struct sockaddr, sa_data);
514fe567363Smrg    if ((addr = calloc (1, addrlen)) == NULL) {
515fe567363Smrg	prmsg (1, "SocketReopen: malloc(addr) failed\n");
516fe567363Smrg	free (ciptr);
51773143b9aSmrg	return NULL;
51873143b9aSmrg    }
5198d4c0f7bSmrg    ciptr->addr = (char *) addr;
520fe567363Smrg    ciptr->addrlen = addrlen;
52173143b9aSmrg
522fe567363Smrg    if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) {
523fe567363Smrg	prmsg (1, "SocketReopen: malloc(portaddr) failed\n");
524fe567363Smrg	free (addr);
525fe567363Smrg	free (ciptr);
52673143b9aSmrg	return NULL;
52773143b9aSmrg    }
528fe567363Smrg    ciptr->peeraddrlen = addrlen;
52973143b9aSmrg
53073143b9aSmrg    /* Initialize ciptr structure as if it were a normally-opened unix socket */
53173143b9aSmrg    ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
53273143b9aSmrg#ifdef BSD44SOCKETS
533fe567363Smrg    addr->sa_len = addrlen;
53473143b9aSmrg#endif
53573143b9aSmrg    addr->sa_family = AF_UNIX;
53673143b9aSmrg#ifdef HAS_STRLCPY
53773143b9aSmrg    strlcpy(addr->sa_data, port, portlen);
53873143b9aSmrg#else
53973143b9aSmrg    strncpy(addr->sa_data, port, portlen);
54073143b9aSmrg#endif
54173143b9aSmrg    ciptr->family = AF_UNIX;
542fe567363Smrg    memcpy(ciptr->peeraddr, ciptr->addr, addrlen);
54373143b9aSmrg    ciptr->port = rindex(addr->sa_data, ':');
544e8a71cdfSmrg    if (ciptr->port == NULL) {
545e8a71cdfSmrg	if (is_numeric(addr->sa_data)) {
546e8a71cdfSmrg	    ciptr->port = addr->sa_data;
547e8a71cdfSmrg	}
548e8a71cdfSmrg    } else if (ciptr->port[0] == ':') {
549e8a71cdfSmrg	ciptr->port++;
550e8a71cdfSmrg    }
551e8a71cdfSmrg    /* port should now point to portnum or NULL */
55273143b9aSmrg    return ciptr;
55373143b9aSmrg}
55473143b9aSmrg
55573143b9aSmrg#endif /* TRANS_REOPEN */
55673143b9aSmrg
55773143b9aSmrg
55873143b9aSmrg/*
55973143b9aSmrg * These functions are the interface supplied in the Xtransport structure
56073143b9aSmrg */
56173143b9aSmrg
56273143b9aSmrg#ifdef TRANS_CLIENT
56373143b9aSmrg
56473143b9aSmrgstatic XtransConnInfo
565fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol,
566fe567363Smrg			   const char *host, const char *port, int previndex)
56773143b9aSmrg{
56873143b9aSmrg    XtransConnInfo	ciptr;
56973143b9aSmrg    int			i = previndex;
57073143b9aSmrg
571fe567363Smrg    prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
57273143b9aSmrg	protocol, host, port);
57373143b9aSmrg
57473143b9aSmrg    SocketInitOnce();
57573143b9aSmrg
57673143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
57773143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
578e8a71cdfSmrg		i, Sockettrans2devtab[i].devcotsname)) != NULL) {
579e8a71cdfSmrg	    /* Save the index for later use */
580e8a71cdfSmrg
581e8a71cdfSmrg	    ciptr->index = i;
58273143b9aSmrg	    break;
583e8a71cdfSmrg	}
58473143b9aSmrg    }
58573143b9aSmrg    if (i < 0) {
58673143b9aSmrg	if (i == -1)
587fe567363Smrg	    prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
588fe567363Smrg		   transname);
58973143b9aSmrg	else
590fe567363Smrg	    prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
591fe567363Smrg		   transname);
59273143b9aSmrg	return NULL;
59373143b9aSmrg    }
59473143b9aSmrg
59573143b9aSmrg    return ciptr;
59673143b9aSmrg}
59773143b9aSmrg
59873143b9aSmrgstatic XtransConnInfo
5996a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol,
6006a3641a6Ssnj			     const char *host, const char *port)
60173143b9aSmrg{
60273143b9aSmrg    return TRANS(SocketOpenCOTSClientBase)(
60373143b9aSmrg			thistrans->TransName, protocol, host, port, -1);
60473143b9aSmrg}
60573143b9aSmrg
60673143b9aSmrg
60773143b9aSmrg#endif /* TRANS_CLIENT */
60873143b9aSmrg
60973143b9aSmrg
61073143b9aSmrg#ifdef TRANS_SERVER
61173143b9aSmrg
61273143b9aSmrgstatic XtransConnInfo
6136a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol,
6146a3641a6Ssnj			     const char *host, const char *port)
61573143b9aSmrg
61673143b9aSmrg{
61773143b9aSmrg    XtransConnInfo	ciptr;
61873143b9aSmrg    int	i = -1;
61973143b9aSmrg
620fe567363Smrg    prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
62173143b9aSmrg
62273143b9aSmrg    SocketInitOnce();
62373143b9aSmrg
62473143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
62573143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
62673143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
62773143b9aSmrg	    break;
62873143b9aSmrg    }
62973143b9aSmrg    if (i < 0) {
63073143b9aSmrg	if (i == -1)
631fe567363Smrg	    prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
632fe567363Smrg		   thistrans->TransName);
63373143b9aSmrg	else
634fe567363Smrg	    prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
635fe567363Smrg		   thistrans->TransName);
63673143b9aSmrg	return NULL;
63773143b9aSmrg    }
63873143b9aSmrg
63973143b9aSmrg    /*
64073143b9aSmrg     * Using this prevents the bind() check for an existing server listening
64173143b9aSmrg     * on the same port, but it is required for other reasons.
64273143b9aSmrg     */
64373143b9aSmrg#ifdef SO_REUSEADDR
64473143b9aSmrg
64573143b9aSmrg    /*
64673143b9aSmrg     * SO_REUSEADDR only applied to AF_INET && AF_INET6
64773143b9aSmrg     */
64873143b9aSmrg
64973143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
65073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
65173143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
65273143b9aSmrg#endif
65373143b9aSmrg    )
65473143b9aSmrg    {
65573143b9aSmrg	int one = 1;
65673143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
65773143b9aSmrg		    (char *) &one, sizeof (int));
65873143b9aSmrg    }
65973143b9aSmrg#endif
66073143b9aSmrg#ifdef IPV6_V6ONLY
66173143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
66273143b9aSmrg    {
66373143b9aSmrg	int one = 1;
66473143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
66573143b9aSmrg    }
66673143b9aSmrg#endif
66773143b9aSmrg    /* Save the index for later use */
66873143b9aSmrg
66973143b9aSmrg    ciptr->index = i;
67073143b9aSmrg
67173143b9aSmrg    return ciptr;
67273143b9aSmrg}
67373143b9aSmrg
67473143b9aSmrg#endif /* TRANS_SERVER */
67573143b9aSmrg
67673143b9aSmrg
67773143b9aSmrg#ifdef TRANS_CLIENT
67873143b9aSmrg
67973143b9aSmrgstatic XtransConnInfo
6806a3641a6SsnjTRANS(SocketOpenCLTSClient) (Xtransport *thistrans, const char *protocol,
6816a3641a6Ssnj			     const char *host, const char *port)
68273143b9aSmrg
68373143b9aSmrg{
68473143b9aSmrg    XtransConnInfo	ciptr;
68573143b9aSmrg    int			i = -1;
68673143b9aSmrg
687fe567363Smrg    prmsg (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
68873143b9aSmrg
68973143b9aSmrg    SocketInitOnce();
69073143b9aSmrg
69173143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
69273143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
69373143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
69473143b9aSmrg	    break;
69573143b9aSmrg    }
69673143b9aSmrg    if (i < 0) {
69773143b9aSmrg	if (i == -1)
698fe567363Smrg	    prmsg (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
699fe567363Smrg		   thistrans->TransName);
70073143b9aSmrg	else
701fe567363Smrg	    prmsg (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
702fe567363Smrg		   thistrans->TransName);
70373143b9aSmrg	return NULL;
70473143b9aSmrg    }
70573143b9aSmrg
70673143b9aSmrg    /* Save the index for later use */
70773143b9aSmrg
70873143b9aSmrg    ciptr->index = i;
70973143b9aSmrg
71073143b9aSmrg    return ciptr;
71173143b9aSmrg}
71273143b9aSmrg
71373143b9aSmrg#endif /* TRANS_CLIENT */
71473143b9aSmrg
71573143b9aSmrg
71673143b9aSmrg#ifdef TRANS_SERVER
71773143b9aSmrg
71873143b9aSmrgstatic XtransConnInfo
7196a3641a6SsnjTRANS(SocketOpenCLTSServer) (Xtransport *thistrans, const char *protocol,
7206a3641a6Ssnj			     const char *host, const char *port)
72173143b9aSmrg
72273143b9aSmrg{
72373143b9aSmrg    XtransConnInfo	ciptr;
72473143b9aSmrg    int	i = -1;
72573143b9aSmrg
726fe567363Smrg    prmsg (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
72773143b9aSmrg
72873143b9aSmrg    SocketInitOnce();
72973143b9aSmrg
73073143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
73173143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
73273143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
73373143b9aSmrg	    break;
73473143b9aSmrg    }
73573143b9aSmrg    if (i < 0) {
73673143b9aSmrg	if (i == -1)
737fe567363Smrg	    prmsg (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
738fe567363Smrg		   thistrans->TransName);
73973143b9aSmrg	else
740fe567363Smrg	    prmsg (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
741fe567363Smrg		   thistrans->TransName);
74273143b9aSmrg	return NULL;
74373143b9aSmrg    }
74473143b9aSmrg
74573143b9aSmrg#ifdef IPV6_V6ONLY
74673143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
74773143b9aSmrg    {
74873143b9aSmrg	int one = 1;
74973143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
75073143b9aSmrg    }
75173143b9aSmrg#endif
75273143b9aSmrg    /* Save the index for later use */
75373143b9aSmrg
75473143b9aSmrg    ciptr->index = i;
75573143b9aSmrg
75673143b9aSmrg    return ciptr;
75773143b9aSmrg}
75873143b9aSmrg
75973143b9aSmrg#endif /* TRANS_SERVER */
76073143b9aSmrg
76173143b9aSmrg
76273143b9aSmrg#ifdef TRANS_REOPEN
76373143b9aSmrg
76473143b9aSmrgstatic XtransConnInfo
7656a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port)
76673143b9aSmrg
76773143b9aSmrg{
76873143b9aSmrg    XtransConnInfo	ciptr;
76973143b9aSmrg    int			i = -1;
77073143b9aSmrg
771fe567363Smrg    prmsg (2,
772fe567363Smrg	"SocketReopenCOTSServer(%d, %s)\n", fd, port);
77373143b9aSmrg
77473143b9aSmrg    SocketInitOnce();
77573143b9aSmrg
77673143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
77773143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
77873143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
77973143b9aSmrg	    break;
78073143b9aSmrg    }
78173143b9aSmrg    if (i < 0) {
78273143b9aSmrg	if (i == -1)
783fe567363Smrg	    prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
784fe567363Smrg		   thistrans->TransName);
78573143b9aSmrg	else
786fe567363Smrg	    prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
787fe567363Smrg		   thistrans->TransName);
78873143b9aSmrg	return NULL;
78973143b9aSmrg    }
79073143b9aSmrg
79173143b9aSmrg    /* Save the index for later use */
79273143b9aSmrg
79373143b9aSmrg    ciptr->index = i;
79473143b9aSmrg
79573143b9aSmrg    return ciptr;
79673143b9aSmrg}
79773143b9aSmrg
79873143b9aSmrgstatic XtransConnInfo
7996a3641a6SsnjTRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, const char *port)
80073143b9aSmrg
80173143b9aSmrg{
80273143b9aSmrg    XtransConnInfo	ciptr;
80373143b9aSmrg    int			i = -1;
80473143b9aSmrg
805fe567363Smrg    prmsg (2,
806fe567363Smrg	"SocketReopenCLTSServer(%d, %s)\n", fd, port);
80773143b9aSmrg
80873143b9aSmrg    SocketInitOnce();
80973143b9aSmrg
81073143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
81173143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
81273143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
81373143b9aSmrg	    break;
81473143b9aSmrg    }
81573143b9aSmrg    if (i < 0) {
81673143b9aSmrg	if (i == -1)
817fe567363Smrg	    prmsg (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
818fe567363Smrg		   thistrans->TransName);
81973143b9aSmrg	else
820fe567363Smrg	    prmsg (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
821fe567363Smrg		   thistrans->TransName);
82273143b9aSmrg	return NULL;
82373143b9aSmrg    }
82473143b9aSmrg
82573143b9aSmrg    /* Save the index for later use */
82673143b9aSmrg
82773143b9aSmrg    ciptr->index = i;
82873143b9aSmrg
82973143b9aSmrg    return ciptr;
83073143b9aSmrg}
83173143b9aSmrg
83273143b9aSmrg#endif /* TRANS_REOPEN */
83373143b9aSmrg
83473143b9aSmrg
83573143b9aSmrgstatic int
83673143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
83773143b9aSmrg
83873143b9aSmrg{
839fe567363Smrg    prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
84073143b9aSmrg
84173143b9aSmrg    return -1;
84273143b9aSmrg}
84373143b9aSmrg
84473143b9aSmrg#ifdef UNIXCONN
84573143b9aSmrgstatic int
84673143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract)
84773143b9aSmrg{
84873143b9aSmrg    struct sockaddr_un s;
84973143b9aSmrg    int maxlen = sizeof(s.sun_path) - 1;
85073143b9aSmrg    const char *at = "";
85173143b9aSmrg
85273143b9aSmrg    if (!port || !*port || !path)
85373143b9aSmrg	return -1;
85473143b9aSmrg
85573143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
85673143b9aSmrg    if (port[0] == '@')
85773143b9aSmrg	upath = "";
85873143b9aSmrg    else if (abstract)
85973143b9aSmrg	at = "@";
86073143b9aSmrg#endif
86173143b9aSmrg
86273143b9aSmrg    if (*port == '/') /* a full pathname */
86373143b9aSmrg	upath = "";
86473143b9aSmrg
86573143b9aSmrg    if (strlen(port) + strlen(upath) > maxlen)
86673143b9aSmrg	return -1;
867fe567363Smrg    snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port);
86873143b9aSmrg    return 0;
86973143b9aSmrg}
87073143b9aSmrg#endif
87173143b9aSmrg
87273143b9aSmrg#ifdef TRANS_SERVER
87373143b9aSmrg
87473143b9aSmrgstatic int
875fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr,
87673143b9aSmrg			     struct sockaddr *sockname,
87773143b9aSmrg			     int socknamelen, unsigned int flags)
87873143b9aSmrg
87973143b9aSmrg{
88073143b9aSmrg    SOCKLEN_T namelen = socknamelen;
88173143b9aSmrg    int	fd = ciptr->fd;
88273143b9aSmrg    int	retry;
88373143b9aSmrg
884fe567363Smrg    prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd);
88573143b9aSmrg
88673143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
88773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
88873143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
88973143b9aSmrg#endif
89073143b9aSmrg	)
89173143b9aSmrg	retry = 20;
89273143b9aSmrg    else
89373143b9aSmrg	retry = 0;
89473143b9aSmrg
89573143b9aSmrg    while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
89673143b9aSmrg    {
89773143b9aSmrg	if (errno == EADDRINUSE) {
89873143b9aSmrg	    if (flags & ADDR_IN_USE_ALLOWED)
89973143b9aSmrg		break;
90073143b9aSmrg	    else
90173143b9aSmrg		return TRANS_ADDR_IN_USE;
90273143b9aSmrg	}
903fe567363Smrg
90473143b9aSmrg	if (retry-- == 0) {
905fe567363Smrg	    prmsg (1, "SocketCreateListener: failed to bind listener\n");
90673143b9aSmrg	    close (fd);
90773143b9aSmrg	    return TRANS_CREATE_LISTENER_FAILED;
90873143b9aSmrg	}
90973143b9aSmrg#ifdef SO_REUSEADDR
91073143b9aSmrg	sleep (1);
91173143b9aSmrg#else
91273143b9aSmrg	sleep (10);
91373143b9aSmrg#endif /* SO_REUSEDADDR */
91473143b9aSmrg    }
91573143b9aSmrg
91673143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
91773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
91873143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
91973143b9aSmrg#endif
92073143b9aSmrg	) {
92173143b9aSmrg#ifdef SO_DONTLINGER
92273143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
92373143b9aSmrg#else
92473143b9aSmrg#ifdef SO_LINGER
92573143b9aSmrg    {
92673143b9aSmrg	static int linger[2] = { 0, 0 };
92773143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_LINGER,
92873143b9aSmrg		(char *) linger, sizeof (linger));
92973143b9aSmrg    }
93073143b9aSmrg#endif
93173143b9aSmrg#endif
93273143b9aSmrg}
93373143b9aSmrg
93473143b9aSmrg    if (listen (fd, BACKLOG) < 0)
93573143b9aSmrg    {
936fe567363Smrg	prmsg (1, "SocketCreateListener: listen() failed\n");
93773143b9aSmrg	close (fd);
93873143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
93973143b9aSmrg    }
940fe567363Smrg
94173143b9aSmrg    /* Set a flag to indicate that this connection is a listener */
94273143b9aSmrg
94373143b9aSmrg    ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
94473143b9aSmrg
94573143b9aSmrg    return 0;
94673143b9aSmrg}
94773143b9aSmrg
94873143b9aSmrg#ifdef TCPCONN
94973143b9aSmrgstatic int
9506a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port,
9516a3641a6Ssnj                                 unsigned int flags)
95273143b9aSmrg
95373143b9aSmrg{
95473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
95573143b9aSmrg    struct sockaddr_storage sockname;
95673143b9aSmrg#else
95773143b9aSmrg    struct sockaddr_in	    sockname;
95873143b9aSmrg#endif
95973143b9aSmrg    unsigned short	    sport;
96073143b9aSmrg    SOCKLEN_T	namelen = sizeof(sockname);
96173143b9aSmrg    int		status;
96273143b9aSmrg    long	tmpport;
96373143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
96473143b9aSmrg    _Xgetservbynameparams sparams;
96573143b9aSmrg#endif
96673143b9aSmrg    struct servent *servp;
96773143b9aSmrg
96873143b9aSmrg#ifdef X11_t
96973143b9aSmrg    char	portbuf[PORTBUFSIZE];
97073143b9aSmrg#endif
971fe567363Smrg
972fe567363Smrg    prmsg (2, "SocketINETCreateListener(%s)\n", port);
97373143b9aSmrg
97473143b9aSmrg#ifdef X11_t
97573143b9aSmrg    /*
97673143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
97773143b9aSmrg     * to handle it here, than try and come up with a transport independent
97873143b9aSmrg     * representation that can be passed in and resolved the usual way.
97973143b9aSmrg     *
98073143b9aSmrg     * The port that is passed here is really a string containing the idisplay
98173143b9aSmrg     * from ConnectDisplay().
98273143b9aSmrg     */
98373143b9aSmrg
98473143b9aSmrg    if (is_numeric (port))
98573143b9aSmrg    {
98673143b9aSmrg	/* fixup the server port address */
98773143b9aSmrg	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
988fe567363Smrg	snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
98973143b9aSmrg	port = portbuf;
99073143b9aSmrg    }
99173143b9aSmrg#endif
99273143b9aSmrg
99373143b9aSmrg    if (port && *port)
99473143b9aSmrg    {
99573143b9aSmrg	/* Check to see if the port string is just a number (handles X11) */
99673143b9aSmrg
99773143b9aSmrg	if (!is_numeric (port))
99873143b9aSmrg	{
99973143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
100073143b9aSmrg	    {
1001fe567363Smrg		prmsg (1,
100273143b9aSmrg	     "SocketINETCreateListener: Unable to get service for %s\n",
1003fe567363Smrg		      port);
100473143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
100573143b9aSmrg	    }
100673143b9aSmrg	    /* we trust getservbyname to return a valid number */
100773143b9aSmrg	    sport = servp->s_port;
100873143b9aSmrg	}
100973143b9aSmrg	else
101073143b9aSmrg	{
101173143b9aSmrg	    tmpport = strtol (port, (char**)NULL, 10);
1012fe567363Smrg	    /*
101373143b9aSmrg	     * check that somehow the port address isn't negative or in
101473143b9aSmrg	     * the range of reserved port addresses. This can happen and
1015fe567363Smrg	     * be very bad if the server is suid-root and the user does
1016fe567363Smrg	     * something (dumb) like `X :60049`.
101773143b9aSmrg	     */
101873143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
101973143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
102073143b9aSmrg
102173143b9aSmrg	    sport = (unsigned short) tmpport;
102273143b9aSmrg	}
102373143b9aSmrg    }
102473143b9aSmrg    else
102573143b9aSmrg	sport = 0;
102673143b9aSmrg
102773143b9aSmrg    bzero(&sockname, sizeof(sockname));
102873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
102973143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
103073143b9aSmrg	namelen = sizeof (struct sockaddr_in);
103173143b9aSmrg#ifdef BSD44SOCKETS
103273143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_len = namelen;
103373143b9aSmrg#endif
103473143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
103573143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
103673143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
103773143b9aSmrg    } else {
103873143b9aSmrg	namelen = sizeof (struct sockaddr_in6);
103973143b9aSmrg#ifdef SIN6_LEN
104073143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
104173143b9aSmrg#endif
104273143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
104373143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
104473143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
104573143b9aSmrg    }
104673143b9aSmrg#else
104773143b9aSmrg#ifdef BSD44SOCKETS
104873143b9aSmrg    sockname.sin_len = sizeof (sockname);
104973143b9aSmrg#endif
105073143b9aSmrg    sockname.sin_family = AF_INET;
105173143b9aSmrg    sockname.sin_port = htons (sport);
105273143b9aSmrg    sockname.sin_addr.s_addr = htonl (INADDR_ANY);
105373143b9aSmrg#endif
105473143b9aSmrg
105573143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
105673143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
105773143b9aSmrg    {
1058fe567363Smrg	prmsg (1,
1059fe567363Smrg    "SocketINETCreateListener: ...SocketCreateListener() failed\n");
106073143b9aSmrg	return status;
106173143b9aSmrg    }
106273143b9aSmrg
106373143b9aSmrg    if (TRANS(SocketINETGetAddr) (ciptr) < 0)
106473143b9aSmrg    {
1065fe567363Smrg	prmsg (1,
1066fe567363Smrg       "SocketINETCreateListener: ...SocketINETGetAddr() failed\n");
106773143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
106873143b9aSmrg    }
106973143b9aSmrg
107073143b9aSmrg    return 0;
107173143b9aSmrg}
107273143b9aSmrg
107373143b9aSmrg#endif /* TCPCONN */
107473143b9aSmrg
107573143b9aSmrg
107673143b9aSmrg#ifdef UNIXCONN
107773143b9aSmrg
107873143b9aSmrgstatic int
10796a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port,
108073143b9aSmrg				 unsigned int flags)
108173143b9aSmrg
108273143b9aSmrg{
108373143b9aSmrg    struct sockaddr_un	sockname;
108473143b9aSmrg    int			namelen;
108573143b9aSmrg    int			oldUmask;
108673143b9aSmrg    int			status;
108773143b9aSmrg    unsigned int	mode;
108873143b9aSmrg    char		tmpport[108];
108973143b9aSmrg
109073143b9aSmrg    int			abstract = 0;
109173143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
109273143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
109373143b9aSmrg#endif
109473143b9aSmrg
1095fe567363Smrg    prmsg (2, "SocketUNIXCreateListener(%s)\n",
1096fe567363Smrg	port ? port : "NULL");
109773143b9aSmrg
109873143b9aSmrg    /* Make sure the directory is created */
109973143b9aSmrg
110073143b9aSmrg    oldUmask = umask (0);
110173143b9aSmrg
110273143b9aSmrg#ifdef UNIX_DIR
110373143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
110473143b9aSmrg    mode = 01777;
110573143b9aSmrg#else
110673143b9aSmrg    mode = 0777;
110773143b9aSmrg#endif
11088d4c0f7bSmrg    if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
1109fe567363Smrg	prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
1110fe567363Smrg	       UNIX_DIR, errno);
111173143b9aSmrg	(void) umask (oldUmask);
111273143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
111373143b9aSmrg    }
111473143b9aSmrg#endif
111573143b9aSmrg
111673143b9aSmrg    memset(&sockname, 0, sizeof(sockname));
111773143b9aSmrg    sockname.sun_family = AF_UNIX;
111873143b9aSmrg
111973143b9aSmrg    if (!(port && *port)) {
112073143b9aSmrg	snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
112173143b9aSmrg	port = tmpport;
112273143b9aSmrg    }
112373143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1124fe567363Smrg	prmsg (1, "SocketUNIXCreateListener: path too long\n");
112573143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
112673143b9aSmrg    }
112773143b9aSmrg
1128fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
112973143b9aSmrg    sockname.sun_len = strlen(sockname.sun_path);
113073143b9aSmrg#endif
113173143b9aSmrg
113273143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
113373143b9aSmrg    namelen = SUN_LEN(&sockname);
113473143b9aSmrg#else
113573143b9aSmrg    namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
113673143b9aSmrg#endif
113773143b9aSmrg
113873143b9aSmrg    if (abstract) {
113973143b9aSmrg	sockname.sun_path[0] = '\0';
114073143b9aSmrg	namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
114173143b9aSmrg    }
114273143b9aSmrg    else
114373143b9aSmrg	unlink (sockname.sun_path);
114473143b9aSmrg
114573143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
114673143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
114773143b9aSmrg    {
1148fe567363Smrg	prmsg (1,
1149fe567363Smrg    "SocketUNIXCreateListener: ...SocketCreateListener() failed\n");
115073143b9aSmrg	(void) umask (oldUmask);
115173143b9aSmrg	return status;
115273143b9aSmrg    }
115373143b9aSmrg
115473143b9aSmrg    /*
115573143b9aSmrg     * Now that the listener is esablished, create the addr info for
115673143b9aSmrg     * this connection. getpeername() doesn't work for UNIX Domain Sockets
115773143b9aSmrg     * on some systems (hpux at least), so we will just do it manually, instead
115873143b9aSmrg     * of calling something like TRANS(SocketUNIXGetAddr).
115973143b9aSmrg     */
116073143b9aSmrg
116173143b9aSmrg    namelen = sizeof (sockname); /* this will always make it the same size */
116273143b9aSmrg
1163fe567363Smrg    if ((ciptr->addr = malloc (namelen)) == NULL)
116473143b9aSmrg    {
1165fe567363Smrg        prmsg (1,
1166fe567363Smrg        "SocketUNIXCreateListener: Can't allocate space for the addr\n");
116773143b9aSmrg	(void) umask (oldUmask);
116873143b9aSmrg        return TRANS_CREATE_LISTENER_FAILED;
116973143b9aSmrg    }
117073143b9aSmrg
117173143b9aSmrg    if (abstract)
117273143b9aSmrg	sockname.sun_path[0] = '@';
117373143b9aSmrg
117473143b9aSmrg    ciptr->family = sockname.sun_family;
117573143b9aSmrg    ciptr->addrlen = namelen;
117673143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
117773143b9aSmrg
117873143b9aSmrg    (void) umask (oldUmask);
117973143b9aSmrg
118073143b9aSmrg    return 0;
118173143b9aSmrg}
118273143b9aSmrg
118373143b9aSmrg
118473143b9aSmrgstatic int
118573143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
118673143b9aSmrg
118773143b9aSmrg{
118873143b9aSmrg    /*
118973143b9aSmrg     * See if the unix domain socket has disappeared.  If it has, recreate it.
119073143b9aSmrg     */
119173143b9aSmrg
119273143b9aSmrg    struct sockaddr_un 	*unsock = (struct sockaddr_un *) ciptr->addr;
119373143b9aSmrg    struct stat		statb;
119473143b9aSmrg    int 		status = TRANS_RESET_NOOP;
119573143b9aSmrg    unsigned int	mode;
119673143b9aSmrg    int abstract = 0;
119773143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
119873143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
119973143b9aSmrg#endif
120073143b9aSmrg
1201fe567363Smrg    prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd);
120273143b9aSmrg
120373143b9aSmrg    if (!abstract && (
120473143b9aSmrg	stat (unsock->sun_path, &statb) == -1 ||
120573143b9aSmrg        ((statb.st_mode & S_IFMT) !=
1206e8a71cdfSmrg#if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
120773143b9aSmrg	  		S_IFIFO
120873143b9aSmrg#else
120973143b9aSmrg			S_IFSOCK
121073143b9aSmrg#endif
121173143b9aSmrg				)))
121273143b9aSmrg    {
121373143b9aSmrg	int oldUmask = umask (0);
121473143b9aSmrg
121573143b9aSmrg#ifdef UNIX_DIR
121673143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
121773143b9aSmrg	mode = 01777;
121873143b9aSmrg#else
121973143b9aSmrg	mode = 0777;
122073143b9aSmrg#endif
122173143b9aSmrg        if (trans_mkdir(UNIX_DIR, mode) == -1) {
1222fe567363Smrg            prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
1223fe567363Smrg	    UNIX_DIR, errno);
122473143b9aSmrg	    (void) umask (oldUmask);
122573143b9aSmrg	    return TRANS_RESET_FAILURE;
122673143b9aSmrg        }
122773143b9aSmrg#endif
122873143b9aSmrg
122973143b9aSmrg	close (ciptr->fd);
123073143b9aSmrg	unlink (unsock->sun_path);
123173143b9aSmrg
123273143b9aSmrg	if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
123373143b9aSmrg	{
123473143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
123573143b9aSmrg	    (void) umask (oldUmask);
123673143b9aSmrg	    return TRANS_RESET_FAILURE;
123773143b9aSmrg	}
123873143b9aSmrg
123973143b9aSmrg	if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
124073143b9aSmrg	{
124173143b9aSmrg	    close (ciptr->fd);
124273143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
124373143b9aSmrg	    return TRANS_RESET_FAILURE;
124473143b9aSmrg	}
124573143b9aSmrg
124673143b9aSmrg	if (listen (ciptr->fd, BACKLOG) < 0)
124773143b9aSmrg	{
124873143b9aSmrg	    close (ciptr->fd);
124973143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
125073143b9aSmrg	    (void) umask (oldUmask);
125173143b9aSmrg	    return TRANS_RESET_FAILURE;
125273143b9aSmrg	}
125373143b9aSmrg
125473143b9aSmrg	umask (oldUmask);
125573143b9aSmrg
125673143b9aSmrg	status = TRANS_RESET_NEW_FD;
125773143b9aSmrg    }
125873143b9aSmrg
125973143b9aSmrg    return status;
126073143b9aSmrg}
126173143b9aSmrg
126273143b9aSmrg#endif /* UNIXCONN */
126373143b9aSmrg
126473143b9aSmrg
126573143b9aSmrg#ifdef TCPCONN
126673143b9aSmrg
126773143b9aSmrgstatic XtransConnInfo
126873143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
126973143b9aSmrg
127073143b9aSmrg{
127173143b9aSmrg    XtransConnInfo	newciptr;
127273143b9aSmrg    struct sockaddr_in	sockname;
127373143b9aSmrg    SOCKLEN_T		namelen = sizeof(sockname);
127473143b9aSmrg
1275fe567363Smrg    prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd);
127673143b9aSmrg
1277fe567363Smrg    if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
127873143b9aSmrg    {
1279fe567363Smrg	prmsg (1, "SocketINETAccept: malloc failed\n");
128073143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
128173143b9aSmrg	return NULL;
128273143b9aSmrg    }
128373143b9aSmrg
128473143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
128573143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
128673143b9aSmrg    {
128773143b9aSmrg#ifdef WIN32
128873143b9aSmrg	errno = WSAGetLastError();
128973143b9aSmrg#endif
1290fe567363Smrg	prmsg (1, "SocketINETAccept: accept() failed\n");
1291fe567363Smrg	free (newciptr);
129273143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
129373143b9aSmrg	return NULL;
129473143b9aSmrg    }
129573143b9aSmrg
129673143b9aSmrg#ifdef TCP_NODELAY
129773143b9aSmrg    {
129873143b9aSmrg	/*
129973143b9aSmrg	 * turn off TCP coalescence for INET sockets
130073143b9aSmrg	 */
130173143b9aSmrg
130273143b9aSmrg	int tmp = 1;
130373143b9aSmrg	setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
130473143b9aSmrg	    (char *) &tmp, sizeof (int));
130573143b9aSmrg    }
130673143b9aSmrg#endif
130773143b9aSmrg
130873143b9aSmrg    /*
1309fe567363Smrg     * Get this address again because the transport may give a more
131073143b9aSmrg     * specific address now that a connection is established.
131173143b9aSmrg     */
131273143b9aSmrg
131373143b9aSmrg    if (TRANS(SocketINETGetAddr) (newciptr) < 0)
131473143b9aSmrg    {
1315fe567363Smrg	prmsg (1,
1316fe567363Smrg	    "SocketINETAccept: ...SocketINETGetAddr() failed:\n");
131773143b9aSmrg	close (newciptr->fd);
1318fe567363Smrg	free (newciptr);
131973143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
132073143b9aSmrg        return NULL;
132173143b9aSmrg    }
132273143b9aSmrg
132373143b9aSmrg    if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
132473143b9aSmrg    {
1325fe567363Smrg	prmsg (1,
1326fe567363Smrg	  "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n");
132773143b9aSmrg	close (newciptr->fd);
1328fe567363Smrg	if (newciptr->addr) free (newciptr->addr);
1329fe567363Smrg	free (newciptr);
133073143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
133173143b9aSmrg        return NULL;
133273143b9aSmrg    }
133373143b9aSmrg
133473143b9aSmrg    *status = 0;
133573143b9aSmrg
133673143b9aSmrg    return newciptr;
133773143b9aSmrg}
133873143b9aSmrg
133973143b9aSmrg#endif /* TCPCONN */
134073143b9aSmrg
134173143b9aSmrg
134273143b9aSmrg#ifdef UNIXCONN
134373143b9aSmrgstatic XtransConnInfo
134473143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
134573143b9aSmrg
134673143b9aSmrg{
134773143b9aSmrg    XtransConnInfo	newciptr;
134873143b9aSmrg    struct sockaddr_un	sockname;
134973143b9aSmrg    SOCKLEN_T 		namelen = sizeof sockname;
135073143b9aSmrg
1351fe567363Smrg    prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd);
135273143b9aSmrg
1353fe567363Smrg    if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
135473143b9aSmrg    {
1355fe567363Smrg	prmsg (1, "SocketUNIXAccept: malloc() failed\n");
135673143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
135773143b9aSmrg	return NULL;
135873143b9aSmrg    }
135973143b9aSmrg
136073143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
136173143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
136273143b9aSmrg    {
1363fe567363Smrg	prmsg (1, "SocketUNIXAccept: accept() failed\n");
1364fe567363Smrg	free (newciptr);
136573143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
136673143b9aSmrg	return NULL;
136773143b9aSmrg    }
136873143b9aSmrg
136973143b9aSmrg	ciptr->addrlen = namelen;
137073143b9aSmrg    /*
137173143b9aSmrg     * Get the socket name and the peer name from the listener socket,
137273143b9aSmrg     * since this is unix domain.
137373143b9aSmrg     */
137473143b9aSmrg
1375fe567363Smrg    if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL)
137673143b9aSmrg    {
1377fe567363Smrg        prmsg (1,
1378fe567363Smrg        "SocketUNIXAccept: Can't allocate space for the addr\n");
137973143b9aSmrg	close (newciptr->fd);
1380fe567363Smrg	free (newciptr);
138173143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
138273143b9aSmrg        return NULL;
138373143b9aSmrg    }
138473143b9aSmrg
138573143b9aSmrg    /*
138673143b9aSmrg     * if the socket is abstract, we already modified the address to have a
138773143b9aSmrg     * @ instead of the initial NUL, so no need to do that again here.
138873143b9aSmrg     */
138973143b9aSmrg
139073143b9aSmrg    newciptr->addrlen = ciptr->addrlen;
139173143b9aSmrg    memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
139273143b9aSmrg
1393fe567363Smrg    if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL)
139473143b9aSmrg    {
1395fe567363Smrg        prmsg (1,
1396fe567363Smrg	      "SocketUNIXAccept: Can't allocate space for the addr\n");
139773143b9aSmrg	close (newciptr->fd);
1398fe567363Smrg	if (newciptr->addr) free (newciptr->addr);
1399fe567363Smrg	free (newciptr);
140073143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
140173143b9aSmrg        return NULL;
140273143b9aSmrg    }
1403fe567363Smrg
140473143b9aSmrg    newciptr->peeraddrlen = ciptr->addrlen;
140573143b9aSmrg    memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
140673143b9aSmrg
140773143b9aSmrg    newciptr->family = AF_UNIX;
140873143b9aSmrg
140973143b9aSmrg    *status = 0;
141073143b9aSmrg
141173143b9aSmrg    return newciptr;
141273143b9aSmrg}
141373143b9aSmrg
141473143b9aSmrg#endif /* UNIXCONN */
141573143b9aSmrg
141673143b9aSmrg#endif /* TRANS_SERVER */
141773143b9aSmrg
141873143b9aSmrg
141973143b9aSmrg#ifdef TRANS_CLIENT
142073143b9aSmrg
142173143b9aSmrg#ifdef TCPCONN
142273143b9aSmrg
142373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
142473143b9aSmrgstruct addrlist {
142573143b9aSmrg    struct addrinfo *	addr;
1426fe567363Smrg    struct addrinfo *	firstaddr;
142773143b9aSmrg    char 		port[PORTBUFSIZE];
142873143b9aSmrg    char 		host[MAXHOSTNAMELEN];
142973143b9aSmrg};
143073143b9aSmrgstatic struct addrlist  *addrlist = NULL;
143173143b9aSmrg#endif
143273143b9aSmrg
143373143b9aSmrg
143473143b9aSmrgstatic int
14356a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr,
14366a3641a6Ssnj                          const char *host, const char *port)
143773143b9aSmrg
143873143b9aSmrg{
143973143b9aSmrg    struct sockaddr *	socketaddr = NULL;
144073143b9aSmrg    int			socketaddrlen = 0;
144173143b9aSmrg    int			res;
144273143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
144373143b9aSmrg    struct addrinfo 	hints;
144473143b9aSmrg    char		ntopbuf[INET6_ADDRSTRLEN];
144573143b9aSmrg    int			resetonce = 0;
1446fe567363Smrg#else
144773143b9aSmrg    struct sockaddr_in	sockname;
1448fe567363Smrg    struct hostent	*hostp;
1449fe567363Smrg    struct servent	*servp;
1450fe567363Smrg    unsigned long 	tmpaddr;
1451fe567363Smrg#endif
145273143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
145373143b9aSmrg    _Xgethostbynameparams hparams;
145473143b9aSmrg    _Xgetservbynameparams sparams;
145573143b9aSmrg#endif
145673143b9aSmrg#ifdef X11_t
145773143b9aSmrg    char	portbuf[PORTBUFSIZE];
145873143b9aSmrg#endif
145973143b9aSmrg
146073143b9aSmrg    char 		hostnamebuf[256];		/* tmp space */
146173143b9aSmrg
1462fe567363Smrg    prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
146373143b9aSmrg
146473143b9aSmrg    if (!host)
146573143b9aSmrg    {
146673143b9aSmrg	hostnamebuf[0] = '\0';
146773143b9aSmrg	(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
146873143b9aSmrg	host = hostnamebuf;
146973143b9aSmrg    }
147073143b9aSmrg
147173143b9aSmrg#ifdef X11_t
147273143b9aSmrg    /*
147373143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
147473143b9aSmrg     * to handle it here, than try and come up with a transport independent
147573143b9aSmrg     * representation that can be passed in and resolved the usual way.
147673143b9aSmrg     *
147773143b9aSmrg     * The port that is passed here is really a string containing the idisplay
147873143b9aSmrg     * from ConnectDisplay().
147973143b9aSmrg     */
148073143b9aSmrg
148173143b9aSmrg    if (is_numeric (port))
148273143b9aSmrg    {
1483fe567363Smrg	long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1484fe567363Smrg	snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
148573143b9aSmrg	port = portbuf;
148673143b9aSmrg    }
148773143b9aSmrg#endif
148873143b9aSmrg
148973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1490b53e5eeaSmrg    {
149173143b9aSmrg	if (addrlist != NULL) {
149273143b9aSmrg	    if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
149373143b9aSmrg		if (addrlist->firstaddr)
149473143b9aSmrg		    freeaddrinfo(addrlist->firstaddr);
149573143b9aSmrg		addrlist->firstaddr = NULL;
149673143b9aSmrg	    }
149773143b9aSmrg	} else {
149873143b9aSmrg	    addrlist = malloc(sizeof(struct addrlist));
149973143b9aSmrg	    addrlist->firstaddr = NULL;
150073143b9aSmrg	}
150173143b9aSmrg
150273143b9aSmrg	if (addrlist->firstaddr == NULL) {
150373143b9aSmrg	    strncpy(addrlist->port, port, sizeof(addrlist->port));
150473143b9aSmrg	    addrlist->port[sizeof(addrlist->port) - 1] = '\0';
150573143b9aSmrg	    strncpy(addrlist->host, host, sizeof(addrlist->host));
150673143b9aSmrg	    addrlist->host[sizeof(addrlist->host) - 1] = '\0';
150773143b9aSmrg
150873143b9aSmrg	    bzero(&hints,sizeof(hints));
150973143b9aSmrg	    hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
151073143b9aSmrg
151173143b9aSmrg	    res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
151273143b9aSmrg	    if (res != 0) {
1513fe567363Smrg		prmsg (1, "SocketINETConnect() can't get address "
151473143b9aSmrg			"for %s:%s: %s\n", host, port, gai_strerror(res));
151573143b9aSmrg		ESET(EINVAL);
151673143b9aSmrg		return TRANS_CONNECT_FAILED;
151773143b9aSmrg	    }
151873143b9aSmrg	    for (res = 0, addrlist->addr = addrlist->firstaddr;
151973143b9aSmrg		 addrlist->addr ; res++) {
152073143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
152173143b9aSmrg	    }
1522fe567363Smrg	    prmsg(4,"Got New Address list with %d addresses\n", res);
152373143b9aSmrg	    res = 0;
152473143b9aSmrg	    addrlist->addr = NULL;
152573143b9aSmrg	}
152673143b9aSmrg
152773143b9aSmrg	while (socketaddr == NULL) {
152873143b9aSmrg	    if (addrlist->addr == NULL) {
1529fe567363Smrg		if (resetonce) {
153073143b9aSmrg		    /* Already checked entire list - no usable addresses */
1531fe567363Smrg		    prmsg (1, "SocketINETConnect() no usable address "
1532fe567363Smrg			   "for %s:%s\n", host, port);
153373143b9aSmrg		    return TRANS_CONNECT_FAILED;
153473143b9aSmrg		} else {
153573143b9aSmrg		    /* Go back to beginning of list */
153673143b9aSmrg		    resetonce = 1;
153773143b9aSmrg		    addrlist->addr = addrlist->firstaddr;
153873143b9aSmrg		}
1539fe567363Smrg	    }
154073143b9aSmrg
154173143b9aSmrg	    socketaddr = addrlist->addr->ai_addr;
154273143b9aSmrg	    socketaddrlen = addrlist->addr->ai_addrlen;
154373143b9aSmrg
154473143b9aSmrg	    if (addrlist->addr->ai_family == AF_INET) {
154573143b9aSmrg		struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
154673143b9aSmrg
1547fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n",
154873143b9aSmrg			inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
1549fe567363Smrg			ntopbuf,sizeof(ntopbuf)));
155073143b9aSmrg
1551fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n",
1552fe567363Smrg			ntohs(sin->sin_port));
155373143b9aSmrg
155473143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
155573143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
155673143b9aSmrg				"tcp") == 0) {
155773143b9aSmrg			XtransConnInfo newciptr;
155873143b9aSmrg
155973143b9aSmrg			/*
156073143b9aSmrg			 * Our socket is an IPv6 socket, but the address is
156173143b9aSmrg			 * IPv4.  Close it and get an IPv4 socket.  This is
156273143b9aSmrg			 * needed for IPv4 connections to work on platforms
156373143b9aSmrg			 * that don't allow IPv4 over IPv6 sockets.
156473143b9aSmrg			 */
156573143b9aSmrg			TRANS(SocketINETClose)(ciptr);
156673143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
156773143b9aSmrg					"tcp", "tcp", host, port, ciptr->index);
156873143b9aSmrg			if (newciptr)
156973143b9aSmrg			    ciptr->fd = newciptr->fd;
157073143b9aSmrg			if (!newciptr ||
157173143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
157273143b9aSmrg				AF_INET) {
157373143b9aSmrg			    socketaddr = NULL;
1574fe567363Smrg			    prmsg (4,"SocketINETConnect() Cannot get IPv4 "
1575fe567363Smrg					" socketfor IPv4 address\n");
157673143b9aSmrg			}
157773143b9aSmrg			if (newciptr)
1578fe567363Smrg			    free(newciptr);
157973143b9aSmrg		    } else {
158073143b9aSmrg			socketaddr = NULL;
1581fe567363Smrg			prmsg (4,"SocketINETConnect Skipping IPv4 address\n");
158273143b9aSmrg		    }
158373143b9aSmrg		}
158473143b9aSmrg	    } else if (addrlist->addr->ai_family == AF_INET6) {
158573143b9aSmrg		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
1586fe567363Smrg
1587fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
158873143b9aSmrg			inet_ntop(addrlist->addr->ai_family,
1589fe567363Smrg				  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)));
1590fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n",
1591fe567363Smrg			ntohs(sin6->sin6_port));
159273143b9aSmrg
159373143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
159473143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
159573143b9aSmrg				"tcp") == 0) {
159673143b9aSmrg			XtransConnInfo newciptr;
159773143b9aSmrg
159873143b9aSmrg			/*
159973143b9aSmrg			 * Close the IPv4 socket and try to open an IPv6 socket.
160073143b9aSmrg			 */
160173143b9aSmrg			TRANS(SocketINETClose)(ciptr);
160273143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
160373143b9aSmrg					"tcp", "tcp", host, port, -1);
160473143b9aSmrg			if (newciptr)
160573143b9aSmrg			    ciptr->fd = newciptr->fd;
160673143b9aSmrg			if (!newciptr ||
160773143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
160873143b9aSmrg					AF_INET6) {
160973143b9aSmrg			    socketaddr = NULL;
1610fe567363Smrg			    prmsg (4,"SocketINETConnect() Cannot get IPv6 "
1611fe567363Smrg				   "socket for IPv6 address\n");
161273143b9aSmrg			}
161373143b9aSmrg			if (newciptr)
1614fe567363Smrg			    free(newciptr);
161573143b9aSmrg		    }
161673143b9aSmrg		    else
161773143b9aSmrg		    {
161873143b9aSmrg			socketaddr = NULL;
1619fe567363Smrg			prmsg (4,"SocketINETConnect() Skipping IPv6 address\n");
162073143b9aSmrg		    }
162173143b9aSmrg		}
162273143b9aSmrg	    } else {
162373143b9aSmrg		socketaddr = NULL; /* Unsupported address type */
162473143b9aSmrg	    }
162573143b9aSmrg	    if (socketaddr == NULL) {
162673143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
162773143b9aSmrg	    }
1628fe567363Smrg	}
1629b53e5eeaSmrg    }
1630b53e5eeaSmrg#else
163173143b9aSmrg    {
163273143b9aSmrg	/*
163373143b9aSmrg	 * Build the socket name.
163473143b9aSmrg	 */
163573143b9aSmrg
163673143b9aSmrg#ifdef BSD44SOCKETS
163773143b9aSmrg	sockname.sin_len = sizeof (struct sockaddr_in);
163873143b9aSmrg#endif
163973143b9aSmrg	sockname.sin_family = AF_INET;
164073143b9aSmrg
164173143b9aSmrg	/*
164273143b9aSmrg	 * fill in sin_addr
164373143b9aSmrg	 */
164473143b9aSmrg
164573143b9aSmrg#ifndef INADDR_NONE
164673143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff)
164773143b9aSmrg#endif
164873143b9aSmrg
164973143b9aSmrg	/* check for ww.xx.yy.zz host string */
165073143b9aSmrg
165173143b9aSmrg	if (isascii (host[0]) && isdigit (host[0])) {
165273143b9aSmrg	    tmpaddr = inet_addr (host); /* returns network byte order */
165373143b9aSmrg	} else {
165473143b9aSmrg	    tmpaddr = INADDR_NONE;
165573143b9aSmrg	}
165673143b9aSmrg
165781d6fa61Srin	prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr);
165873143b9aSmrg
165973143b9aSmrg	if (tmpaddr == INADDR_NONE) {
166073143b9aSmrg	    if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
1661fe567363Smrg		prmsg (1,"SocketINETConnect: Can't get address for %s\n",
1662fe567363Smrg			host);
166373143b9aSmrg		ESET(EINVAL);
166473143b9aSmrg		return TRANS_CONNECT_FAILED;
166573143b9aSmrg	    }
166673143b9aSmrg	    if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
1667fe567363Smrg		prmsg (1,"SocketINETConnect: not INET host%s\n", host);
166873143b9aSmrg		ESET(EPROTOTYPE);
166973143b9aSmrg		return TRANS_CONNECT_FAILED;
167073143b9aSmrg	    }
1671fe567363Smrg
167273143b9aSmrg	    memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
167373143b9aSmrg		    sizeof (sockname.sin_addr));
167473143b9aSmrg
167573143b9aSmrg	} else {
167673143b9aSmrg	    sockname.sin_addr.s_addr = tmpaddr;
167773143b9aSmrg        }
167873143b9aSmrg
167973143b9aSmrg	/*
168073143b9aSmrg	 * fill in sin_port
168173143b9aSmrg	 */
168273143b9aSmrg
168373143b9aSmrg	/* Check for number in the port string */
168473143b9aSmrg
168573143b9aSmrg	if (!is_numeric (port)) {
168673143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
1687fe567363Smrg		prmsg (1,"SocketINETConnect: can't get service for %s\n",
1688fe567363Smrg			port);
168973143b9aSmrg		return TRANS_CONNECT_FAILED;
169073143b9aSmrg	    }
169173143b9aSmrg	    sockname.sin_port = htons (servp->s_port);
169273143b9aSmrg	} else {
1693fe567363Smrg	    long tmpport = strtol (port, (char**)NULL, 10);
169473143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
169573143b9aSmrg		return TRANS_CONNECT_FAILED;
169673143b9aSmrg	    sockname.sin_port = htons (((unsigned short) tmpport));
169773143b9aSmrg	}
169873143b9aSmrg
1699fe567363Smrg	prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n",
1700fe567363Smrg		ntohs(sockname.sin_port));
170173143b9aSmrg	socketaddr = (struct sockaddr *) &sockname;
170273143b9aSmrg	socketaddrlen = sizeof(sockname);
170373143b9aSmrg    }
1704b53e5eeaSmrg#endif
170573143b9aSmrg
170673143b9aSmrg    /*
170773143b9aSmrg     * Turn on socket keepalive so the client process will eventually
170873143b9aSmrg     * be notified with a SIGPIPE signal if the display server fails
170973143b9aSmrg     * to respond to a periodic transmission of messages
171073143b9aSmrg     * on the connected socket.
171173143b9aSmrg     * This is useful to avoid hung application processes when the
171273143b9aSmrg     * processes are not spawned from the xdm session and
171373143b9aSmrg     * the display server terminates abnormally.
171473143b9aSmrg     * (Someone turned off the power switch.)
171573143b9aSmrg     */
171673143b9aSmrg
171773143b9aSmrg    {
171873143b9aSmrg	int tmp = 1;
171973143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
172073143b9aSmrg		(char *) &tmp, sizeof (int));
172173143b9aSmrg    }
172273143b9aSmrg
172373143b9aSmrg    /*
172473143b9aSmrg     * Do the connect()
172573143b9aSmrg     */
172673143b9aSmrg
172773143b9aSmrg    if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
172873143b9aSmrg    {
172973143b9aSmrg#ifdef WIN32
173073143b9aSmrg	int olderrno = WSAGetLastError();
173173143b9aSmrg#else
173273143b9aSmrg	int olderrno = errno;
173373143b9aSmrg#endif
173473143b9aSmrg
173573143b9aSmrg	/*
173673143b9aSmrg	 * If the error was ECONNREFUSED, the server may be overloaded
173773143b9aSmrg	 * and we should try again.
173873143b9aSmrg	 *
173973143b9aSmrg	 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
174073143b9aSmrg	 * was non-blocking and we should poll using select
174173143b9aSmrg	 *
174273143b9aSmrg	 * If the error was EINTR, the connect was interrupted and we
174373143b9aSmrg	 * should try again.
174473143b9aSmrg	 *
174573143b9aSmrg	 * If multiple addresses are found for a host then we should
174673143b9aSmrg	 * try to connect again with a different address for a larger
174773143b9aSmrg	 * number of errors that made us quit before, since those
174873143b9aSmrg	 * could be caused by trying to use an IPv6 address to contact
174973143b9aSmrg	 * a machine with an IPv4-only server or other reasons that
1750fe567363Smrg	 * only affect one of a set of addresses.
175173143b9aSmrg	 */
175273143b9aSmrg
175373143b9aSmrg	if (olderrno == ECONNREFUSED || olderrno == EINTR
175473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1755b53e5eeaSmrg	  || (((addrlist->addr->ai_next != NULL) ||
175673143b9aSmrg	        (addrlist->addr != addrlist->firstaddr)) &&
175773143b9aSmrg               (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
175873143b9aSmrg		 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
175973143b9aSmrg#if defined(EHOSTDOWN)
176073143b9aSmrg		   || olderrno == EHOSTDOWN
176173143b9aSmrg#endif
176273143b9aSmrg	       ))
176373143b9aSmrg#endif
176473143b9aSmrg	    )
176573143b9aSmrg	    res = TRANS_TRY_CONNECT_AGAIN;
176673143b9aSmrg	else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
176773143b9aSmrg	    res = TRANS_IN_PROGRESS;
176873143b9aSmrg	else
176973143b9aSmrg	{
1770fe567363Smrg	    prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n",
1771fe567363Smrg		   olderrno);
177273143b9aSmrg
1773fe567363Smrg	    res = TRANS_CONNECT_FAILED;
177473143b9aSmrg	}
177573143b9aSmrg    } else {
177673143b9aSmrg	res = 0;
1777fe567363Smrg
177873143b9aSmrg
177973143b9aSmrg	/*
178073143b9aSmrg	 * Sync up the address fields of ciptr.
178173143b9aSmrg	 */
1782fe567363Smrg
178373143b9aSmrg	if (TRANS(SocketINETGetAddr) (ciptr) < 0)
178473143b9aSmrg	{
1785fe567363Smrg	    prmsg (1,
1786fe567363Smrg	     "SocketINETConnect: ...SocketINETGetAddr() failed:\n");
178773143b9aSmrg	    res = TRANS_CONNECT_FAILED;
178873143b9aSmrg	}
178973143b9aSmrg
179073143b9aSmrg	else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
179173143b9aSmrg	{
1792fe567363Smrg	    prmsg (1,
1793fe567363Smrg	      "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n");
179473143b9aSmrg	    res = TRANS_CONNECT_FAILED;
179573143b9aSmrg	}
179673143b9aSmrg    }
179773143b9aSmrg
179873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1799b53e5eeaSmrg   if (res != 0) {
180073143b9aSmrg	addrlist->addr = addrlist->addr->ai_next;
180173143b9aSmrg   }
180273143b9aSmrg#endif
180373143b9aSmrg
180473143b9aSmrg    return res;
180573143b9aSmrg}
180673143b9aSmrg
180773143b9aSmrg#endif /* TCPCONN */
180873143b9aSmrg
180973143b9aSmrg
181073143b9aSmrg
181173143b9aSmrg#ifdef UNIXCONN
181273143b9aSmrg
181373143b9aSmrg/*
181473143b9aSmrg * Make sure 'host' is really local.
181573143b9aSmrg */
181673143b9aSmrg
181773143b9aSmrgstatic int
18186a3641a6SsnjUnixHostReallyLocal (const char *host)
181973143b9aSmrg
182073143b9aSmrg{
182173143b9aSmrg    char hostnamebuf[256];
182273143b9aSmrg
182373143b9aSmrg    TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
182473143b9aSmrg
182573143b9aSmrg    if (strcmp (hostnamebuf, host) == 0)
182673143b9aSmrg    {
182773143b9aSmrg	return (1);
1828b53e5eeaSmrg    } else {
182973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
183073143b9aSmrg	struct addrinfo *localhostaddr;
183173143b9aSmrg	struct addrinfo *otherhostaddr;
183273143b9aSmrg	struct addrinfo *i, *j;
183373143b9aSmrg	int equiv = 0;
183473143b9aSmrg
183573143b9aSmrg	if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
183673143b9aSmrg	    return 0;
183773143b9aSmrg	if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
183873143b9aSmrg	    freeaddrinfo(localhostaddr);
183973143b9aSmrg	    return 0;
184073143b9aSmrg	}
184173143b9aSmrg
184273143b9aSmrg	for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
184373143b9aSmrg	    for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
184473143b9aSmrg		if (i->ai_family == j->ai_family) {
184573143b9aSmrg		    if (i->ai_family == AF_INET) {
1846fe567363Smrg			struct sockaddr_in *sinA
184773143b9aSmrg			  = (struct sockaddr_in *) i->ai_addr;
184873143b9aSmrg			struct sockaddr_in *sinB
184973143b9aSmrg			  = (struct sockaddr_in *) j->ai_addr;
185073143b9aSmrg			struct in_addr *A = &sinA->sin_addr;
185173143b9aSmrg			struct in_addr *B = &sinB->sin_addr;
185273143b9aSmrg
185373143b9aSmrg			if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
185473143b9aSmrg			    equiv = 1;
185573143b9aSmrg			}
185673143b9aSmrg		    } else if (i->ai_family == AF_INET6) {
1857fe567363Smrg			struct sockaddr_in6 *sinA
185873143b9aSmrg			  = (struct sockaddr_in6 *) i->ai_addr;
1859fe567363Smrg			struct sockaddr_in6 *sinB
186073143b9aSmrg			  = (struct sockaddr_in6 *) j->ai_addr;
186173143b9aSmrg			struct in6_addr *A = &sinA->sin6_addr;
186273143b9aSmrg			struct in6_addr *B = &sinB->sin6_addr;
186373143b9aSmrg
186473143b9aSmrg			if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
186573143b9aSmrg			    equiv = 1;
186673143b9aSmrg			}
186773143b9aSmrg		    }
186873143b9aSmrg		}
186973143b9aSmrg	    }
187073143b9aSmrg	}
1871fe567363Smrg
187273143b9aSmrg	freeaddrinfo(localhostaddr);
187373143b9aSmrg	freeaddrinfo(otherhostaddr);
187473143b9aSmrg	return equiv;
1875b53e5eeaSmrg#else
187673143b9aSmrg	/*
187773143b9aSmrg	 * A host may have more than one network address.  If any of the
187873143b9aSmrg	 * network addresses of 'host' (specified to the connect call)
187973143b9aSmrg	 * match any of the network addresses of 'hostname' (determined
188073143b9aSmrg	 * by TRANS(GetHostname)), then the two hostnames are equivalent,
188173143b9aSmrg	 * and we know that 'host' is really a local host.
188273143b9aSmrg	 */
188373143b9aSmrg	char specified_local_addr_list[10][4];
188473143b9aSmrg	int scount, equiv, i, j;
188573143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
188673143b9aSmrg	_Xgethostbynameparams hparams;
188773143b9aSmrg#endif
188873143b9aSmrg	struct hostent *hostp;
188973143b9aSmrg
189073143b9aSmrg	if ((hostp = _XGethostbyname (host,hparams)) == NULL)
189173143b9aSmrg	    return (0);
189273143b9aSmrg
189373143b9aSmrg	scount = 0;
189473143b9aSmrg	while (hostp->h_addr_list[scount] && scount <= 8)
189573143b9aSmrg	{
189673143b9aSmrg	    /*
189773143b9aSmrg	     * The 2nd call to gethostname() overrides the data
189873143b9aSmrg	     * from the 1st call, so we must save the address list.
189973143b9aSmrg	     */
190073143b9aSmrg
1901fe567363Smrg	    specified_local_addr_list[scount][0] =
190273143b9aSmrg				hostp->h_addr_list[scount][0];
1903fe567363Smrg	    specified_local_addr_list[scount][1] =
190473143b9aSmrg				hostp->h_addr_list[scount][1];
1905fe567363Smrg	    specified_local_addr_list[scount][2] =
190673143b9aSmrg				hostp->h_addr_list[scount][2];
1907fe567363Smrg	    specified_local_addr_list[scount][3] =
190873143b9aSmrg				hostp->h_addr_list[scount][3];
190973143b9aSmrg	    scount++;
191073143b9aSmrg	}
191173143b9aSmrg	if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
191273143b9aSmrg	    return (0);
191373143b9aSmrg
191473143b9aSmrg	equiv = 0;
191573143b9aSmrg	i = 0;
191673143b9aSmrg
191773143b9aSmrg	while (i < scount && !equiv)
191873143b9aSmrg	{
191973143b9aSmrg	    j = 0;
192073143b9aSmrg
192173143b9aSmrg	    while (hostp->h_addr_list[j])
192273143b9aSmrg	    {
1923fe567363Smrg		if ((specified_local_addr_list[i][0] ==
192473143b9aSmrg					hostp->h_addr_list[j][0]) &&
1925fe567363Smrg		    (specified_local_addr_list[i][1] ==
192673143b9aSmrg					hostp->h_addr_list[j][1]) &&
1927fe567363Smrg		    (specified_local_addr_list[i][2] ==
192873143b9aSmrg					hostp->h_addr_list[j][2]) &&
1929fe567363Smrg		    (specified_local_addr_list[i][3] ==
193073143b9aSmrg					hostp->h_addr_list[j][3]))
193173143b9aSmrg		{
193273143b9aSmrg		    /* They're equal, so we're done */
1933fe567363Smrg
193473143b9aSmrg		    equiv = 1;
193573143b9aSmrg		    break;
193673143b9aSmrg		}
193773143b9aSmrg
193873143b9aSmrg		j++;
193973143b9aSmrg	    }
194073143b9aSmrg
194173143b9aSmrg	    i++;
194273143b9aSmrg	}
194373143b9aSmrg	return (equiv);
1944b53e5eeaSmrg#endif
194573143b9aSmrg    }
194673143b9aSmrg}
194773143b9aSmrg
194873143b9aSmrgstatic int
19496a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr,
19506a3641a6Ssnj                          const char *host, const char *port)
195173143b9aSmrg
195273143b9aSmrg{
195373143b9aSmrg    struct sockaddr_un	sockname;
195473143b9aSmrg    SOCKLEN_T		namelen;
195573143b9aSmrg
195673143b9aSmrg
195773143b9aSmrg    int abstract = 0;
195873143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
195973143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
196073143b9aSmrg#endif
196173143b9aSmrg
1962fe567363Smrg    prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1963fe567363Smrg
196473143b9aSmrg    /*
196573143b9aSmrg     * Make sure 'host' is really local.  If not, we return failure.
196673143b9aSmrg     * The reason we make this check is because a process may advertise
196773143b9aSmrg     * a "local" network ID for which it can accept connections, but if
196873143b9aSmrg     * a process on a remote machine tries to connect to this network ID,
196973143b9aSmrg     * we know for sure it will fail.
197073143b9aSmrg     */
197173143b9aSmrg
197273143b9aSmrg    if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
197373143b9aSmrg    {
1974fe567363Smrg	prmsg (1,
197573143b9aSmrg	   "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1976fe567363Smrg	       host);
197773143b9aSmrg	return TRANS_CONNECT_FAILED;
197873143b9aSmrg    }
197973143b9aSmrg
198073143b9aSmrg
198173143b9aSmrg    /*
198273143b9aSmrg     * Check the port.
198373143b9aSmrg     */
198473143b9aSmrg
198573143b9aSmrg    if (!port || !*port)
198673143b9aSmrg    {
1987fe567363Smrg	prmsg (1,"SocketUNIXConnect: Missing port specification\n");
198873143b9aSmrg	return TRANS_CONNECT_FAILED;
198973143b9aSmrg    }
199073143b9aSmrg
199173143b9aSmrg    /*
199273143b9aSmrg     * Build the socket name.
199373143b9aSmrg     */
1994fe567363Smrg
199573143b9aSmrg    sockname.sun_family = AF_UNIX;
199673143b9aSmrg
199773143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1998fe567363Smrg	prmsg (1, "SocketUNIXConnect: path too long\n");
199973143b9aSmrg	return TRANS_CONNECT_FAILED;
200073143b9aSmrg    }
200173143b9aSmrg
2002fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
200373143b9aSmrg    sockname.sun_len = strlen (sockname.sun_path);
200473143b9aSmrg#endif
200573143b9aSmrg
200673143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
200773143b9aSmrg    namelen = SUN_LEN (&sockname);
200873143b9aSmrg#else
200973143b9aSmrg    namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
201073143b9aSmrg#endif
201173143b9aSmrg
201273143b9aSmrg
201373143b9aSmrg
201473143b9aSmrg    /*
201573143b9aSmrg     * Adjust the socket path if using abstract sockets.
201673143b9aSmrg     * Done here because otherwise all the strlen() calls above would fail.
201773143b9aSmrg     */
201873143b9aSmrg
201973143b9aSmrg    if (abstract) {
202073143b9aSmrg	sockname.sun_path[0] = '\0';
202173143b9aSmrg    }
202273143b9aSmrg
202373143b9aSmrg    /*
202473143b9aSmrg     * Do the connect()
202573143b9aSmrg     */
202673143b9aSmrg
202773143b9aSmrg    if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
202873143b9aSmrg    {
202973143b9aSmrg	int olderrno = errno;
203073143b9aSmrg	int connected = 0;
2031fe567363Smrg
203273143b9aSmrg	if (!connected)
203373143b9aSmrg	{
203473143b9aSmrg	    errno = olderrno;
2035fe567363Smrg
203673143b9aSmrg	    /*
203773143b9aSmrg	     * If the error was ENOENT, the server may be starting up; we used
203873143b9aSmrg	     * to suggest to try again in this case with
203973143b9aSmrg	     * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
204073143b9aSmrg	     * processes still referencing stale sockets in their environment.
204173143b9aSmrg	     * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
204273143b9aSmrg	     * is suggested that higher level stacks handle retries on their
204373143b9aSmrg	     * level when they face a slow starting server.
204473143b9aSmrg	     *
204573143b9aSmrg	     * If the error was EWOULDBLOCK or EINPROGRESS then the socket
204673143b9aSmrg	     * was non-blocking and we should poll using select
204773143b9aSmrg	     *
204873143b9aSmrg	     * If the error was EINTR, the connect was interrupted and we
204973143b9aSmrg	     * should try again.
205073143b9aSmrg	     */
205173143b9aSmrg
205273143b9aSmrg	    if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
205373143b9aSmrg		return TRANS_IN_PROGRESS;
205473143b9aSmrg	    else if (olderrno == EINTR)
205573143b9aSmrg		return TRANS_TRY_CONNECT_AGAIN;
20568d4c0f7bSmrg	    else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
205773143b9aSmrg		/* If opening as abstract socket failed, try again normally */
205873143b9aSmrg		if (abstract) {
205973143b9aSmrg		    ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
206073143b9aSmrg		    return TRANS_TRY_CONNECT_AGAIN;
206173143b9aSmrg		} else {
206273143b9aSmrg		    return TRANS_CONNECT_FAILED;
206373143b9aSmrg		}
206473143b9aSmrg	    } else {
2065fe567363Smrg		prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
2066fe567363Smrg		       EGET());
206773143b9aSmrg
206873143b9aSmrg		return TRANS_CONNECT_FAILED;
206973143b9aSmrg	    }
207073143b9aSmrg	}
207173143b9aSmrg    }
207273143b9aSmrg
207373143b9aSmrg    /*
207473143b9aSmrg     * Get the socket name and the peer name from the connect socket,
207573143b9aSmrg     * since this is unix domain.
207673143b9aSmrg     */
207773143b9aSmrg
2078fe567363Smrg    if ((ciptr->addr = malloc(namelen)) == NULL ||
2079fe567363Smrg       (ciptr->peeraddr = malloc(namelen)) == NULL)
208073143b9aSmrg    {
2081fe567363Smrg        prmsg (1,
2082fe567363Smrg	"SocketUNIXCreateListener: Can't allocate space for the addr\n");
208373143b9aSmrg        return TRANS_CONNECT_FAILED;
208473143b9aSmrg    }
208573143b9aSmrg
208673143b9aSmrg    if (abstract)
208773143b9aSmrg	sockname.sun_path[0] = '@';
208873143b9aSmrg
208973143b9aSmrg    ciptr->family = AF_UNIX;
209073143b9aSmrg    ciptr->addrlen = namelen;
209173143b9aSmrg    ciptr->peeraddrlen = namelen;
209273143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
209373143b9aSmrg    memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
209473143b9aSmrg
209573143b9aSmrg    return 0;
209673143b9aSmrg}
209773143b9aSmrg
209873143b9aSmrg#endif /* UNIXCONN */
209973143b9aSmrg
210073143b9aSmrg#endif /* TRANS_CLIENT */
210173143b9aSmrg
210273143b9aSmrg
210373143b9aSmrgstatic int
210473143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
210573143b9aSmrg
210673143b9aSmrg{
2107fe567363Smrg    prmsg (2,"SocketBytesReadable(%p,%d,%p)\n",
210873143b9aSmrg	ciptr, ciptr->fd, pend);
210973143b9aSmrg#ifdef WIN32
211073143b9aSmrg    {
211173143b9aSmrg	int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
211273143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
211373143b9aSmrg	return ret;
211473143b9aSmrg    }
211573143b9aSmrg#else
2116fe567363Smrg#if defined(__i386__) && defined(SYSV) && !defined(SCO325)
211773143b9aSmrg    return ioctl (ciptr->fd, I_NREAD, (char *) pend);
211873143b9aSmrg#else
211973143b9aSmrg    return ioctl (ciptr->fd, FIONREAD, (char *) pend);
212073143b9aSmrg#endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
212173143b9aSmrg#endif /* WIN32 */
212273143b9aSmrg}
212373143b9aSmrg
212475ebec6dSmrg#if XTRANS_SEND_FDS
212575ebec6dSmrg
212675ebec6dSmrgstatic void
212775ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close)
212875ebec6dSmrg{
212975ebec6dSmrg    struct _XtransConnFd *cf, *new;
213075ebec6dSmrg
213175ebec6dSmrg    new = malloc (sizeof (struct _XtransConnFd));
213275ebec6dSmrg    if (!new) {
213375ebec6dSmrg        /* XXX mark connection as broken */
213475ebec6dSmrg        close(fd);
213575ebec6dSmrg        return;
213675ebec6dSmrg    }
213775ebec6dSmrg    new->next = 0;
213875ebec6dSmrg    new->fd = fd;
213975ebec6dSmrg    new->do_close = do_close;
214075ebec6dSmrg    /* search to end of list */
214175ebec6dSmrg    for (; (cf = *prev); prev = &(cf->next));
214275ebec6dSmrg    *prev = new;
214375ebec6dSmrg}
214473143b9aSmrg
214573143b9aSmrgstatic int
214675ebec6dSmrgremoveFd(struct _XtransConnFd **prev)
214775ebec6dSmrg{
214875ebec6dSmrg    struct _XtransConnFd *cf;
214975ebec6dSmrg    int fd;
215075ebec6dSmrg
215175ebec6dSmrg    if ((cf = *prev)) {
215275ebec6dSmrg        *prev = cf->next;
215375ebec6dSmrg        fd = cf->fd;
215475ebec6dSmrg        free(cf);
215575ebec6dSmrg    } else
215675ebec6dSmrg        fd = -1;
215775ebec6dSmrg    return fd;
215875ebec6dSmrg}
215973143b9aSmrg
216075ebec6dSmrgstatic void
216175ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close)
216273143b9aSmrg{
216375ebec6dSmrg    struct _XtransConnFd *cf, *next;
216473143b9aSmrg
216575ebec6dSmrg    for (cf = *prev; cf != upto; cf = next) {
216675ebec6dSmrg        next = cf->next;
216775ebec6dSmrg        if (do_close || cf->do_close)
216875ebec6dSmrg            close(cf->fd);
216975ebec6dSmrg        free(cf);
217073143b9aSmrg    }
217175ebec6dSmrg    *prev = upto;
217273143b9aSmrg}
217373143b9aSmrg
217475ebec6dSmrgstatic void
217575ebec6dSmrgcleanupFds(XtransConnInfo ciptr)
217675ebec6dSmrg{
217775ebec6dSmrg    /* Clean up the send list but don't close the fds */
217875ebec6dSmrg    discardFd(&ciptr->send_fds, NULL, 0);
217975ebec6dSmrg    /* Clean up the recv list and *do* close the fds */
218075ebec6dSmrg    discardFd(&ciptr->recv_fds, NULL, 1);
218175ebec6dSmrg}
218273143b9aSmrg
218373143b9aSmrgstatic int
218475ebec6dSmrgnFd(struct _XtransConnFd **prev)
218575ebec6dSmrg{
218675ebec6dSmrg    struct _XtransConnFd *cf;
218775ebec6dSmrg    int n = 0;
218875ebec6dSmrg
218975ebec6dSmrg    for (cf = *prev; cf; cf = cf->next)
219075ebec6dSmrg        n++;
219175ebec6dSmrg    return n;
219275ebec6dSmrg}
219373143b9aSmrg
219475ebec6dSmrgstatic int
219575ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr)
219673143b9aSmrg{
219775ebec6dSmrg    prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd);
219875ebec6dSmrg    return removeFd(&ciptr->recv_fds);
219975ebec6dSmrg}
220075ebec6dSmrg
220175ebec6dSmrgstatic int
220275ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close)
220375ebec6dSmrg{
220475ebec6dSmrg    appendFd(&ciptr->send_fds, fd, do_close);
220575ebec6dSmrg    return 0;
220675ebec6dSmrg}
220775ebec6dSmrg
220875ebec6dSmrgstatic int
220975ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr)
221075ebec6dSmrg{
221175ebec6dSmrg    errno = EINVAL;
221275ebec6dSmrg    return -1;
221375ebec6dSmrg}
221475ebec6dSmrg
221575ebec6dSmrgstatic int
221675ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
221775ebec6dSmrg{
221875ebec6dSmrg    errno = EINVAL;
221975ebec6dSmrg    return -1;
222075ebec6dSmrg}
222175ebec6dSmrg
222275ebec6dSmrg#define MAX_FDS		128
222375ebec6dSmrg
222475ebec6dSmrgunion fd_pass {
222575ebec6dSmrg	struct cmsghdr	cmsghdr;
222675ebec6dSmrg	char		buf[CMSG_SPACE(MAX_FDS * sizeof(int))];
222775ebec6dSmrg};
222875ebec6dSmrg
222975ebec6dSmrg#endif /* XTRANS_SEND_FDS */
223075ebec6dSmrg
223175ebec6dSmrgstatic int
223275ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
223375ebec6dSmrg
223475ebec6dSmrg{
223575ebec6dSmrg    prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
223673143b9aSmrg
2237fe567363Smrg#if defined(WIN32)
223873143b9aSmrg    {
223975ebec6dSmrg	int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
224073143b9aSmrg#ifdef WIN32
224173143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
224273143b9aSmrg#endif
224373143b9aSmrg	return ret;
224473143b9aSmrg    }
224573143b9aSmrg#else
224675ebec6dSmrg#if XTRANS_SEND_FDS
224775ebec6dSmrg    {
224875ebec6dSmrg        struct iovec    iov = {
224975ebec6dSmrg            .iov_base = buf,
225075ebec6dSmrg            .iov_len = size
225175ebec6dSmrg        };
225275ebec6dSmrg        union fd_pass   cmsgbuf;
225375ebec6dSmrg        struct msghdr   msg = {
225475ebec6dSmrg            .msg_name = NULL,
225575ebec6dSmrg            .msg_namelen = 0,
225675ebec6dSmrg            .msg_iov = &iov,
225775ebec6dSmrg            .msg_iovlen = 1,
225875ebec6dSmrg            .msg_control = cmsgbuf.buf,
225975ebec6dSmrg            .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
226075ebec6dSmrg        };
226175ebec6dSmrg
226275ebec6dSmrg        size = recvmsg(ciptr->fd, &msg, 0);
226375ebec6dSmrg        if (size >= 0) {
226475ebec6dSmrg            struct cmsghdr *hdr;
226575ebec6dSmrg
226675ebec6dSmrg            for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
226775ebec6dSmrg                if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
226875ebec6dSmrg                    int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
226975ebec6dSmrg                    int i;
227075ebec6dSmrg                    int *fd = (int *) CMSG_DATA(hdr);
227175ebec6dSmrg
227275ebec6dSmrg                    for (i = 0; i < nfd; i++)
227375ebec6dSmrg                        appendFd(&ciptr->recv_fds, fd[i], 0);
227475ebec6dSmrg                }
227575ebec6dSmrg            }
227675ebec6dSmrg        }
227775ebec6dSmrg        return size;
227875ebec6dSmrg    }
227975ebec6dSmrg#else
228075ebec6dSmrg    return read(ciptr->fd, buf, size);
228175ebec6dSmrg#endif /* XTRANS_SEND_FDS */
228273143b9aSmrg#endif /* WIN32 */
228373143b9aSmrg}
228473143b9aSmrg
228573143b9aSmrgstatic int
228673143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
228773143b9aSmrg
228873143b9aSmrg{
2289fe567363Smrg    prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
229073143b9aSmrg
229175ebec6dSmrg#if XTRANS_SEND_FDS
229275ebec6dSmrg    {
229375ebec6dSmrg        union fd_pass   cmsgbuf;
229475ebec6dSmrg        struct msghdr   msg = {
229575ebec6dSmrg            .msg_name = NULL,
229675ebec6dSmrg            .msg_namelen = 0,
229775ebec6dSmrg            .msg_iov = buf,
229875ebec6dSmrg            .msg_iovlen = size,
229975ebec6dSmrg            .msg_control = cmsgbuf.buf,
230075ebec6dSmrg            .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int))
230175ebec6dSmrg        };
230275ebec6dSmrg
230375ebec6dSmrg        size = recvmsg(ciptr->fd, &msg, 0);
230475ebec6dSmrg        if (size >= 0) {
230575ebec6dSmrg            struct cmsghdr *hdr;
230675ebec6dSmrg
230775ebec6dSmrg            for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
230875ebec6dSmrg                if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
230975ebec6dSmrg                    int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
231075ebec6dSmrg                    int i;
231175ebec6dSmrg                    int *fd = (int *) CMSG_DATA(hdr);
231275ebec6dSmrg
231375ebec6dSmrg                    for (i = 0; i < nfd; i++)
231475ebec6dSmrg                        appendFd(&ciptr->recv_fds, fd[i], 0);
231575ebec6dSmrg                }
231675ebec6dSmrg            }
231775ebec6dSmrg        }
231875ebec6dSmrg        return size;
231975ebec6dSmrg    }
232075ebec6dSmrg#else
232173143b9aSmrg    return READV (ciptr, buf, size);
232275ebec6dSmrg#endif
232373143b9aSmrg}
232473143b9aSmrg
232573143b9aSmrg
232673143b9aSmrgstatic int
232773143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
232873143b9aSmrg
232973143b9aSmrg{
2330fe567363Smrg    prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
233173143b9aSmrg
233275ebec6dSmrg#if XTRANS_SEND_FDS
233375ebec6dSmrg    if (ciptr->send_fds)
233475ebec6dSmrg    {
233575ebec6dSmrg        union fd_pass           cmsgbuf;
233675ebec6dSmrg        int                     nfd = nFd(&ciptr->send_fds);
233775ebec6dSmrg        struct _XtransConnFd    *cf = ciptr->send_fds;
233875ebec6dSmrg        struct msghdr           msg = {
233975ebec6dSmrg            .msg_name = NULL,
234075ebec6dSmrg            .msg_namelen = 0,
234175ebec6dSmrg            .msg_iov = buf,
234275ebec6dSmrg            .msg_iovlen = size,
234375ebec6dSmrg            .msg_control = cmsgbuf.buf,
234475ebec6dSmrg            .msg_controllen = CMSG_LEN(nfd * sizeof(int))
234575ebec6dSmrg        };
234675ebec6dSmrg        struct cmsghdr          *hdr = CMSG_FIRSTHDR(&msg);
234775ebec6dSmrg        int                     i;
234875ebec6dSmrg        int                     *fds;
234975ebec6dSmrg
235075ebec6dSmrg        hdr->cmsg_len = msg.msg_controllen;
235175ebec6dSmrg        hdr->cmsg_level = SOL_SOCKET;
235275ebec6dSmrg        hdr->cmsg_type = SCM_RIGHTS;
235375ebec6dSmrg
235475ebec6dSmrg        fds = (int *) CMSG_DATA(hdr);
235575ebec6dSmrg        /* Set up fds */
235675ebec6dSmrg        for (i = 0; i < nfd; i++) {
235775ebec6dSmrg            fds[i] = cf->fd;
235875ebec6dSmrg            cf = cf->next;
235975ebec6dSmrg        }
236075ebec6dSmrg
236175ebec6dSmrg        i = sendmsg(ciptr->fd, &msg, 0);
236275ebec6dSmrg        if (i > 0)
236375ebec6dSmrg            discardFd(&ciptr->send_fds, cf, 0);
236475ebec6dSmrg        return i;
236575ebec6dSmrg    }
236675ebec6dSmrg#endif
236773143b9aSmrg    return WRITEV (ciptr, buf, size);
236873143b9aSmrg}
236973143b9aSmrg
237073143b9aSmrg
237175ebec6dSmrgstatic int
237275ebec6dSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
237375ebec6dSmrg
237475ebec6dSmrg{
237575ebec6dSmrg    prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
237675ebec6dSmrg
237775ebec6dSmrg#if defined(WIN32)
237875ebec6dSmrg    {
237975ebec6dSmrg	int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
238075ebec6dSmrg#ifdef WIN32
238175ebec6dSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
238275ebec6dSmrg#endif
238375ebec6dSmrg	return ret;
238475ebec6dSmrg    }
238575ebec6dSmrg#else
238675ebec6dSmrg#if XTRANS_SEND_FDS
238775ebec6dSmrg    if (ciptr->send_fds)
238875ebec6dSmrg    {
238975ebec6dSmrg        struct iovec            iov;
239075ebec6dSmrg
239175ebec6dSmrg        iov.iov_base = buf;
239275ebec6dSmrg        iov.iov_len = size;
239375ebec6dSmrg        return TRANS(SocketWritev)(ciptr, &iov, 1);
239475ebec6dSmrg    }
239575ebec6dSmrg#endif /* XTRANS_SEND_FDS */
239675ebec6dSmrg    return write (ciptr->fd, buf, size);
239775ebec6dSmrg#endif /* WIN32 */
239875ebec6dSmrg}
239975ebec6dSmrg
240073143b9aSmrgstatic int
240173143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr)
240273143b9aSmrg
240373143b9aSmrg{
2404fe567363Smrg    prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd);
240573143b9aSmrg
240673143b9aSmrg#ifdef WIN32
2407fe567363Smrg    {
240873143b9aSmrg	int ret = shutdown (ciptr->fd, 2);
240973143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
241073143b9aSmrg	return ret;
241173143b9aSmrg    }
241273143b9aSmrg#else
241373143b9aSmrg    return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
241473143b9aSmrg#endif
241573143b9aSmrg}
241673143b9aSmrg
241773143b9aSmrg
241873143b9aSmrg#ifdef TCPCONN
241973143b9aSmrgstatic int
242073143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr)
242173143b9aSmrg
242273143b9aSmrg{
2423fe567363Smrg    prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd);
242473143b9aSmrg
242573143b9aSmrg#ifdef WIN32
242673143b9aSmrg    {
242773143b9aSmrg	int ret = close (ciptr->fd);
242873143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
242973143b9aSmrg	return ret;
243073143b9aSmrg    }
243173143b9aSmrg#else
243273143b9aSmrg    return close (ciptr->fd);
243373143b9aSmrg#endif
243473143b9aSmrg}
243573143b9aSmrg
243673143b9aSmrg#endif /* TCPCONN */
243773143b9aSmrg
243873143b9aSmrg
243973143b9aSmrg#ifdef UNIXCONN
244073143b9aSmrgstatic int
244173143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr)
244273143b9aSmrg{
244373143b9aSmrg    /*
244473143b9aSmrg     * If this is the server side, then once the socket is closed,
244573143b9aSmrg     * it must be unlinked to completely close it
244673143b9aSmrg     */
244773143b9aSmrg
244873143b9aSmrg    struct sockaddr_un	*sockname = (struct sockaddr_un *) ciptr->addr;
244973143b9aSmrg    int ret;
245073143b9aSmrg
2451fe567363Smrg    prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd);
245273143b9aSmrg
245375ebec6dSmrg#if XTRANS_SEND_FDS
245475ebec6dSmrg    cleanupFds(ciptr);
245575ebec6dSmrg#endif
245673143b9aSmrg    ret = close(ciptr->fd);
245773143b9aSmrg
245873143b9aSmrg    if (ciptr->flags
245973143b9aSmrg       && sockname
246073143b9aSmrg       && sockname->sun_family == AF_UNIX
246173143b9aSmrg       && sockname->sun_path[0])
246273143b9aSmrg    {
246373143b9aSmrg	if (!(ciptr->flags & TRANS_NOUNLINK
246473143b9aSmrg	    || ciptr->transptr->flags & TRANS_ABSTRACT))
246573143b9aSmrg		unlink (sockname->sun_path);
246673143b9aSmrg    }
246773143b9aSmrg
246873143b9aSmrg    return ret;
246973143b9aSmrg}
247073143b9aSmrg
247173143b9aSmrgstatic int
247273143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
247373143b9aSmrg
247473143b9aSmrg{
247573143b9aSmrg    /*
247673143b9aSmrg     * Don't unlink path.
247773143b9aSmrg     */
247873143b9aSmrg
247973143b9aSmrg    int ret;
248073143b9aSmrg
2481fe567363Smrg    prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n",
2482fe567363Smrg	ciptr, ciptr->fd);
248373143b9aSmrg
248475ebec6dSmrg#if XTRANS_SEND_FDS
248575ebec6dSmrg    cleanupFds(ciptr);
248675ebec6dSmrg#endif
248773143b9aSmrg    ret = close(ciptr->fd);
248873143b9aSmrg
248973143b9aSmrg    return ret;
249073143b9aSmrg}
249173143b9aSmrg
249273143b9aSmrg#endif /* UNIXCONN */
249373143b9aSmrg
249473143b9aSmrg
249573143b9aSmrg#ifdef TCPCONN
249673143b9aSmrg# ifdef TRANS_SERVER
2497fe567363Smrgstatic const char* tcp_nolisten[] = {
249873143b9aSmrg	"inet",
249973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
250073143b9aSmrg	"inet6",
250173143b9aSmrg#endif
250273143b9aSmrg	NULL
250373143b9aSmrg};
250473143b9aSmrg# endif
250573143b9aSmrg
250673143b9aSmrgXtransport	TRANS(SocketTCPFuncs) = {
250773143b9aSmrg	/* Socket Interface */
250873143b9aSmrg	"tcp",
250973143b9aSmrg        TRANS_ALIAS,
251073143b9aSmrg#ifdef TRANS_CLIENT
251173143b9aSmrg	TRANS(SocketOpenCOTSClient),
251273143b9aSmrg#endif /* TRANS_CLIENT */
251373143b9aSmrg#ifdef TRANS_SERVER
251473143b9aSmrg	tcp_nolisten,
251573143b9aSmrg	TRANS(SocketOpenCOTSServer),
251673143b9aSmrg#endif /* TRANS_SERVER */
251773143b9aSmrg#ifdef TRANS_CLIENT
251873143b9aSmrg	TRANS(SocketOpenCLTSClient),
251973143b9aSmrg#endif /* TRANS_CLIENT */
252073143b9aSmrg#ifdef TRANS_SERVER
252173143b9aSmrg	TRANS(SocketOpenCLTSServer),
252273143b9aSmrg#endif /* TRANS_SERVER */
252373143b9aSmrg#ifdef TRANS_REOPEN
252473143b9aSmrg	TRANS(SocketReopenCOTSServer),
252573143b9aSmrg	TRANS(SocketReopenCLTSServer),
252673143b9aSmrg#endif
252773143b9aSmrg	TRANS(SocketSetOption),
252873143b9aSmrg#ifdef TRANS_SERVER
252973143b9aSmrg	TRANS(SocketINETCreateListener),
253073143b9aSmrg	NULL,		       			/* ResetListener */
253173143b9aSmrg	TRANS(SocketINETAccept),
253273143b9aSmrg#endif /* TRANS_SERVER */
253373143b9aSmrg#ifdef TRANS_CLIENT
253473143b9aSmrg	TRANS(SocketINETConnect),
253573143b9aSmrg#endif /* TRANS_CLIENT */
253673143b9aSmrg	TRANS(SocketBytesReadable),
253773143b9aSmrg	TRANS(SocketRead),
253873143b9aSmrg	TRANS(SocketWrite),
253973143b9aSmrg	TRANS(SocketReadv),
254073143b9aSmrg	TRANS(SocketWritev),
254175ebec6dSmrg#if XTRANS_SEND_FDS
254275ebec6dSmrg        TRANS(SocketSendFdInvalid),
254375ebec6dSmrg        TRANS(SocketRecvFdInvalid),
254475ebec6dSmrg#endif
254573143b9aSmrg	TRANS(SocketDisconnect),
254673143b9aSmrg	TRANS(SocketINETClose),
254773143b9aSmrg	TRANS(SocketINETClose),
254873143b9aSmrg	};
254973143b9aSmrg
255073143b9aSmrgXtransport	TRANS(SocketINETFuncs) = {
255173143b9aSmrg	/* Socket Interface */
255273143b9aSmrg	"inet",
255373143b9aSmrg	0,
255473143b9aSmrg#ifdef TRANS_CLIENT
255573143b9aSmrg	TRANS(SocketOpenCOTSClient),
255673143b9aSmrg#endif /* TRANS_CLIENT */
255773143b9aSmrg#ifdef TRANS_SERVER
255873143b9aSmrg	NULL,
255973143b9aSmrg	TRANS(SocketOpenCOTSServer),
256073143b9aSmrg#endif /* TRANS_SERVER */
256173143b9aSmrg#ifdef TRANS_CLIENT
256273143b9aSmrg	TRANS(SocketOpenCLTSClient),
256373143b9aSmrg#endif /* TRANS_CLIENT */
256473143b9aSmrg#ifdef TRANS_SERVER
256573143b9aSmrg	TRANS(SocketOpenCLTSServer),
256673143b9aSmrg#endif /* TRANS_SERVER */
256773143b9aSmrg#ifdef TRANS_REOPEN
256873143b9aSmrg	TRANS(SocketReopenCOTSServer),
256973143b9aSmrg	TRANS(SocketReopenCLTSServer),
257073143b9aSmrg#endif
257173143b9aSmrg	TRANS(SocketSetOption),
257273143b9aSmrg#ifdef TRANS_SERVER
257373143b9aSmrg	TRANS(SocketINETCreateListener),
257473143b9aSmrg	NULL,		       			/* ResetListener */
257573143b9aSmrg	TRANS(SocketINETAccept),
257673143b9aSmrg#endif /* TRANS_SERVER */
257773143b9aSmrg#ifdef TRANS_CLIENT
257873143b9aSmrg	TRANS(SocketINETConnect),
257973143b9aSmrg#endif /* TRANS_CLIENT */
258073143b9aSmrg	TRANS(SocketBytesReadable),
258173143b9aSmrg	TRANS(SocketRead),
258273143b9aSmrg	TRANS(SocketWrite),
258373143b9aSmrg	TRANS(SocketReadv),
258473143b9aSmrg	TRANS(SocketWritev),
258575ebec6dSmrg#if XTRANS_SEND_FDS
258675ebec6dSmrg        TRANS(SocketSendFdInvalid),
258775ebec6dSmrg        TRANS(SocketRecvFdInvalid),
258875ebec6dSmrg#endif
258973143b9aSmrg	TRANS(SocketDisconnect),
259073143b9aSmrg	TRANS(SocketINETClose),
259173143b9aSmrg	TRANS(SocketINETClose),
259273143b9aSmrg	};
259373143b9aSmrg
259473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
259573143b9aSmrgXtransport     TRANS(SocketINET6Funcs) = {
259673143b9aSmrg	/* Socket Interface */
259773143b9aSmrg	"inet6",
259873143b9aSmrg	0,
259973143b9aSmrg#ifdef TRANS_CLIENT
260073143b9aSmrg	TRANS(SocketOpenCOTSClient),
260173143b9aSmrg#endif /* TRANS_CLIENT */
260273143b9aSmrg#ifdef TRANS_SERVER
260373143b9aSmrg	NULL,
260473143b9aSmrg	TRANS(SocketOpenCOTSServer),
260573143b9aSmrg#endif /* TRANS_SERVER */
260673143b9aSmrg#ifdef TRANS_CLIENT
260773143b9aSmrg	TRANS(SocketOpenCLTSClient),
260873143b9aSmrg#endif /* TRANS_CLIENT */
260973143b9aSmrg#ifdef TRANS_SERVER
261073143b9aSmrg	TRANS(SocketOpenCLTSServer),
261173143b9aSmrg#endif /* TRANS_SERVER */
261273143b9aSmrg#ifdef TRANS_REOPEN
261373143b9aSmrg	TRANS(SocketReopenCOTSServer),
261473143b9aSmrg	TRANS(SocketReopenCLTSServer),
261573143b9aSmrg#endif
261673143b9aSmrg	TRANS(SocketSetOption),
261773143b9aSmrg#ifdef TRANS_SERVER
261873143b9aSmrg	TRANS(SocketINETCreateListener),
261973143b9aSmrg	NULL,					/* ResetListener */
262073143b9aSmrg	TRANS(SocketINETAccept),
262173143b9aSmrg#endif /* TRANS_SERVER */
262273143b9aSmrg#ifdef TRANS_CLIENT
262373143b9aSmrg	TRANS(SocketINETConnect),
262473143b9aSmrg#endif /* TRANS_CLIENT */
262573143b9aSmrg	TRANS(SocketBytesReadable),
262673143b9aSmrg	TRANS(SocketRead),
262773143b9aSmrg	TRANS(SocketWrite),
262873143b9aSmrg	TRANS(SocketReadv),
262973143b9aSmrg	TRANS(SocketWritev),
263075ebec6dSmrg#if XTRANS_SEND_FDS
263175ebec6dSmrg        TRANS(SocketSendFdInvalid),
263275ebec6dSmrg        TRANS(SocketRecvFdInvalid),
263375ebec6dSmrg#endif
263473143b9aSmrg	TRANS(SocketDisconnect),
263573143b9aSmrg	TRANS(SocketINETClose),
263673143b9aSmrg	TRANS(SocketINETClose),
263773143b9aSmrg	};
263873143b9aSmrg#endif /* IPv6 */
263973143b9aSmrg#endif /* TCPCONN */
264073143b9aSmrg
264173143b9aSmrg#ifdef UNIXCONN
264273143b9aSmrg#if !defined(LOCALCONN)
264373143b9aSmrgXtransport	TRANS(SocketLocalFuncs) = {
264473143b9aSmrg	/* Socket Interface */
264573143b9aSmrg	"local",
264673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
264773143b9aSmrg	TRANS_ABSTRACT,
264873143b9aSmrg#else
264973143b9aSmrg	0,
265073143b9aSmrg#endif
265173143b9aSmrg#ifdef TRANS_CLIENT
265273143b9aSmrg	TRANS(SocketOpenCOTSClient),
265373143b9aSmrg#endif /* TRANS_CLIENT */
265473143b9aSmrg#ifdef TRANS_SERVER
265573143b9aSmrg	NULL,
265673143b9aSmrg	TRANS(SocketOpenCOTSServer),
265773143b9aSmrg#endif /* TRANS_SERVER */
265873143b9aSmrg#ifdef TRANS_CLIENT
265973143b9aSmrg	TRANS(SocketOpenCLTSClient),
266073143b9aSmrg#endif /* TRANS_CLIENT */
266173143b9aSmrg#ifdef TRANS_SERVER
266273143b9aSmrg	TRANS(SocketOpenCLTSServer),
266373143b9aSmrg#endif /* TRANS_SERVER */
266473143b9aSmrg#ifdef TRANS_REOPEN
266573143b9aSmrg	TRANS(SocketReopenCOTSServer),
266673143b9aSmrg	TRANS(SocketReopenCLTSServer),
266773143b9aSmrg#endif
266873143b9aSmrg	TRANS(SocketSetOption),
266973143b9aSmrg#ifdef TRANS_SERVER
267073143b9aSmrg	TRANS(SocketUNIXCreateListener),
267173143b9aSmrg	TRANS(SocketUNIXResetListener),
267273143b9aSmrg	TRANS(SocketUNIXAccept),
267373143b9aSmrg#endif /* TRANS_SERVER */
267473143b9aSmrg#ifdef TRANS_CLIENT
267573143b9aSmrg	TRANS(SocketUNIXConnect),
267673143b9aSmrg#endif /* TRANS_CLIENT */
267773143b9aSmrg	TRANS(SocketBytesReadable),
267873143b9aSmrg	TRANS(SocketRead),
267973143b9aSmrg	TRANS(SocketWrite),
268073143b9aSmrg	TRANS(SocketReadv),
268173143b9aSmrg	TRANS(SocketWritev),
268275ebec6dSmrg#if XTRANS_SEND_FDS
268375ebec6dSmrg        TRANS(SocketSendFd),
268475ebec6dSmrg        TRANS(SocketRecvFd),
268575ebec6dSmrg#endif
268673143b9aSmrg	TRANS(SocketDisconnect),
268773143b9aSmrg	TRANS(SocketUNIXClose),
268873143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
268973143b9aSmrg	};
269073143b9aSmrg#endif /* !LOCALCONN */
269173143b9aSmrg# ifdef TRANS_SERVER
269273143b9aSmrg#  if !defined(LOCALCONN)
269375ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL };
269473143b9aSmrg#  endif
269573143b9aSmrg# endif
2696fe567363Smrg
269773143b9aSmrgXtransport	TRANS(SocketUNIXFuncs) = {
269873143b9aSmrg	/* Socket Interface */
269973143b9aSmrg	"unix",
270073143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
270173143b9aSmrg        TRANS_ALIAS,
270273143b9aSmrg#else
270373143b9aSmrg	0,
270473143b9aSmrg#endif
270573143b9aSmrg#ifdef TRANS_CLIENT
270673143b9aSmrg	TRANS(SocketOpenCOTSClient),
270773143b9aSmrg#endif /* TRANS_CLIENT */
270873143b9aSmrg#ifdef TRANS_SERVER
270973143b9aSmrg#if !defined(LOCALCONN)
271073143b9aSmrg	unix_nolisten,
271173143b9aSmrg#else
271273143b9aSmrg	NULL,
271373143b9aSmrg#endif
271473143b9aSmrg	TRANS(SocketOpenCOTSServer),
271573143b9aSmrg#endif /* TRANS_SERVER */
271673143b9aSmrg#ifdef TRANS_CLIENT
271773143b9aSmrg	TRANS(SocketOpenCLTSClient),
271873143b9aSmrg#endif /* TRANS_CLIENT */
271973143b9aSmrg#ifdef TRANS_SERVER
272073143b9aSmrg	TRANS(SocketOpenCLTSServer),
272173143b9aSmrg#endif /* TRANS_SERVER */
272273143b9aSmrg#ifdef TRANS_REOPEN
272373143b9aSmrg	TRANS(SocketReopenCOTSServer),
272473143b9aSmrg	TRANS(SocketReopenCLTSServer),
272573143b9aSmrg#endif
272673143b9aSmrg	TRANS(SocketSetOption),
272773143b9aSmrg#ifdef TRANS_SERVER
272873143b9aSmrg	TRANS(SocketUNIXCreateListener),
272973143b9aSmrg	TRANS(SocketUNIXResetListener),
273073143b9aSmrg	TRANS(SocketUNIXAccept),
273173143b9aSmrg#endif /* TRANS_SERVER */
273273143b9aSmrg#ifdef TRANS_CLIENT
273373143b9aSmrg	TRANS(SocketUNIXConnect),
273473143b9aSmrg#endif /* TRANS_CLIENT */
273573143b9aSmrg	TRANS(SocketBytesReadable),
273673143b9aSmrg	TRANS(SocketRead),
273773143b9aSmrg	TRANS(SocketWrite),
273873143b9aSmrg	TRANS(SocketReadv),
273973143b9aSmrg	TRANS(SocketWritev),
274075ebec6dSmrg#if XTRANS_SEND_FDS
274175ebec6dSmrg        TRANS(SocketSendFd),
274275ebec6dSmrg        TRANS(SocketRecvFd),
274375ebec6dSmrg#endif
274473143b9aSmrg	TRANS(SocketDisconnect),
274573143b9aSmrg	TRANS(SocketUNIXClose),
274673143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
274773143b9aSmrg	};
274873143b9aSmrg
274973143b9aSmrg#endif /* UNIXCONN */
2750