Xtranssock.c revision 8d4c0f7b
173143b9aSmrg/*
273143b9aSmrg
373143b9aSmrgCopyright 1993, 1994, 1998  The Open Group
473143b9aSmrgCopyright 2002 Sun Microsystems, Inc.  All rights reserved.
573143b9aSmrg
673143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its
773143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that
873143b9aSmrgthe above copyright notice appear in all copies and that both that
973143b9aSmrgcopyright notice and this permission notice appear in supporting
1073143b9aSmrgdocumentation.
1173143b9aSmrg
1273143b9aSmrgThe above copyright notice and this permission notice shall be included
1373143b9aSmrgin all copies or substantial portions of the Software.
1473143b9aSmrg
1573143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1673143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1773143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1873143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1973143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2073143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2173143b9aSmrgOTHER DEALINGS IN THE SOFTWARE.
2273143b9aSmrg
2373143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall
2473143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or
2573143b9aSmrgother dealings in this Software without prior written authorization
2673143b9aSmrgfrom the copyright holders.
2773143b9aSmrg
2873143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
2973143b9aSmrg *
3073143b9aSmrg * All Rights Reserved
3173143b9aSmrg *
3273143b9aSmrg * Permission to use, copy, modify, and distribute this software and its
3373143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided
3473143b9aSmrg * that the above copyright notice appear in all copies and that both that
3573143b9aSmrg * copyright notice and this permission notice appear in supporting
3673143b9aSmrg * documentation, and that the name NCR not be used in advertising
3773143b9aSmrg * or publicity pertaining to distribution of the software without specific,
3873143b9aSmrg * written prior permission.  NCR makes no representations about the
3973143b9aSmrg * suitability of this software for any purpose.  It is provided "as is"
4073143b9aSmrg * without express or implied warranty.
4173143b9aSmrg *
4273143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
4373143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
4473143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
4573143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
4673143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4773143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
4873143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4973143b9aSmrg */
5073143b9aSmrg
5173143b9aSmrg#include <ctype.h>
5273143b9aSmrg#ifdef XTHREADS
5373143b9aSmrg#include <X11/Xthreads.h>
5473143b9aSmrg#endif
5573143b9aSmrg
5673143b9aSmrg#ifndef WIN32
5773143b9aSmrg
5873143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
5973143b9aSmrg#include <sys/socket.h>
6073143b9aSmrg#include <netinet/in.h>
6173143b9aSmrg#include <arpa/inet.h>
6273143b9aSmrg#endif
6373143b9aSmrg
6473143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
6573143b9aSmrg#define X_INCLUDE_NETDB_H
6673143b9aSmrg#define XOS_USE_NO_LOCKING
6773143b9aSmrg#include <X11/Xos_r.h>
6873143b9aSmrg#endif
6973143b9aSmrg
7073143b9aSmrg#ifdef UNIXCONN
7173143b9aSmrg#ifndef X_NO_SYS_UN
7273143b9aSmrg#include <sys/un.h>
7373143b9aSmrg#endif
7473143b9aSmrg#include <sys/stat.h>
7573143b9aSmrg#endif
7673143b9aSmrg
7773143b9aSmrg
7873143b9aSmrg#ifndef NO_TCP_H
798d4c0f7bSmrg#if defined(linux) || defined(__GLIBC__)
8073143b9aSmrg#include <sys/param.h>
8173143b9aSmrg#endif /* osf */
8273143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
8373143b9aSmrg#include <sys/param.h>
8473143b9aSmrg#include <machine/endian.h>
8573143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
8673143b9aSmrg#include <netinet/tcp.h>
8773143b9aSmrg#endif /* !NO_TCP_H */
8873143b9aSmrg
8973143b9aSmrg#include <sys/ioctl.h>
908d4c0f7bSmrg#if defined(SVR4)
9173143b9aSmrg#include <sys/filio.h>
9273143b9aSmrg#endif
9373143b9aSmrg
9473143b9aSmrg#if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
9573143b9aSmrg#include <net/errno.h>
9673143b9aSmrg#endif
9773143b9aSmrg
988d4c0f7bSmrg#if defined(__i386__) && defined(SYSV)
9973143b9aSmrg#include <sys/stropts.h>
10073143b9aSmrg#endif
10173143b9aSmrg
1028d4c0f7bSmrg#include <unistd.h>
1038d4c0f7bSmrg
10473143b9aSmrg#else /* !WIN32 */
10573143b9aSmrg
10673143b9aSmrg#include <X11/Xwinsock.h>
10773143b9aSmrg#include <X11/Xwindows.h>
10873143b9aSmrg#include <X11/Xw32defs.h>
10973143b9aSmrg#undef close
11073143b9aSmrg#define close closesocket
11173143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED
11273143b9aSmrg#define EADDRINUSE WSAEADDRINUSE
11373143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE
11473143b9aSmrg#undef EWOULDBLOCK
11573143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK
11673143b9aSmrg#define EINPROGRESS WSAEINPROGRESS
11773143b9aSmrg#undef EINTR
11873143b9aSmrg#define EINTR WSAEINTR
11973143b9aSmrg#define X_INCLUDE_NETDB_H
12073143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI
12173143b9aSmrg#include <X11/Xos_r.h>
12273143b9aSmrg#endif /* WIN32 */
12373143b9aSmrg
12473143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER)
12573143b9aSmrg#undef SO_DONTLINGER
12673143b9aSmrg#endif
12773143b9aSmrg
12873143b9aSmrg/* others don't need this */
12973143b9aSmrg#define SocketInitOnce() /**/
13073143b9aSmrg
13173143b9aSmrg#ifdef linux
13273143b9aSmrg#define HAVE_ABSTRACT_SOCKETS
13373143b9aSmrg#endif
13473143b9aSmrg
13573143b9aSmrg#define MIN_BACKLOG 128
13673143b9aSmrg#ifdef SOMAXCONN
13773143b9aSmrg#if SOMAXCONN > MIN_BACKLOG
13873143b9aSmrg#define BACKLOG SOMAXCONN
13973143b9aSmrg#endif
14073143b9aSmrg#endif
14173143b9aSmrg#ifndef BACKLOG
14273143b9aSmrg#define BACKLOG MIN_BACKLOG
14373143b9aSmrg#endif
14473143b9aSmrg
14573143b9aSmrg/*
14673143b9aSmrg * This is the Socket implementation of the X Transport service layer
14773143b9aSmrg *
14873143b9aSmrg * This file contains the implementation for both the UNIX and INET domains,
14973143b9aSmrg * and can be built for either one, or both.
15073143b9aSmrg *
15173143b9aSmrg */
15273143b9aSmrg
15373143b9aSmrgtypedef struct _Sockettrans2dev {
15473143b9aSmrg    char	*transname;
15573143b9aSmrg    int		family;
15673143b9aSmrg    int		devcotsname;
15773143b9aSmrg    int		devcltsname;
15873143b9aSmrg    int		protocol;
15973143b9aSmrg} Sockettrans2dev;
16073143b9aSmrg
16173143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = {
16273143b9aSmrg#ifdef TCPCONN
16373143b9aSmrg    {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
16473143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6)
16573143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
16673143b9aSmrg#else /* IPv6 */
16773143b9aSmrg    {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
16873143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
16973143b9aSmrg    {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
17073143b9aSmrg#endif
17173143b9aSmrg#endif /* TCPCONN */
17273143b9aSmrg#ifdef UNIXCONN
17373143b9aSmrg    {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
17473143b9aSmrg#if !defined(LOCALCONN)
17573143b9aSmrg    {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
17673143b9aSmrg#endif /* !LOCALCONN */
17773143b9aSmrg#endif /* UNIXCONN */
17873143b9aSmrg};
17973143b9aSmrg
18073143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
18173143b9aSmrg
18273143b9aSmrg#ifdef TCPCONN
18373143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr);
18473143b9aSmrg#endif
18573143b9aSmrg
18673143b9aSmrg#ifdef UNIXCONN
18773143b9aSmrg
18873143b9aSmrg
18973143b9aSmrg#if defined(X11_t)
19073143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
19173143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix"
19273143b9aSmrg#endif /* X11_t */
19373143b9aSmrg#if defined(XIM_t)
19473143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM"
19573143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix"
19673143b9aSmrg#endif /* XIM_t */
19773143b9aSmrg#if defined(FS_t) || defined(FONT_t)
19873143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs"
19973143b9aSmrg#define UNIX_DIR "/tmp/.font-unix"
20073143b9aSmrg#endif /* FS_t || FONT_t */
20173143b9aSmrg#if defined(ICE_t)
20273143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/"
20373143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix"
20473143b9aSmrg#endif /* ICE_t */
20573143b9aSmrg#if defined(TEST_t)
20673143b9aSmrg#define UNIX_PATH "/tmp/.Test-unix/test"
20773143b9aSmrg#define UNIX_DIR "/tmp/.Test-unix"
20873143b9aSmrg#endif
20973143b9aSmrg#if defined(LBXPROXY_t)
21073143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
21173143b9aSmrg#define UNIX_DIR  "/tmp/.X11-unix"
21273143b9aSmrg#endif
21373143b9aSmrg
21473143b9aSmrg
21573143b9aSmrg#endif /* UNIXCONN */
21673143b9aSmrg
21773143b9aSmrg#define PORTBUFSIZE	32
21873143b9aSmrg
21973143b9aSmrg#ifndef MAXHOSTNAMELEN
22073143b9aSmrg#define MAXHOSTNAMELEN 255
22173143b9aSmrg#endif
22273143b9aSmrg
22373143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6))
22473143b9aSmrg# define SOCKLEN_T socklen_t
22573143b9aSmrg#elif defined(SVR4) || defined(__SCO__)
22673143b9aSmrg# define SOCKLEN_T size_t
22773143b9aSmrg#else
22873143b9aSmrg# define SOCKLEN_T int
22973143b9aSmrg#endif
23073143b9aSmrg
23173143b9aSmrg/*
23273143b9aSmrg * This provides compatibility for apps linked against system libraries
23373143b9aSmrg * that don't have IPv6 support.
23473143b9aSmrg */
23573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
23673143b9aSmrgstatic const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
23773143b9aSmrg#pragma weak in6addr_any = local_in6addr_any
23873143b9aSmrg#ifndef __USLC__
23973143b9aSmrg#pragma weak getaddrinfo
24073143b9aSmrg#endif
24173143b9aSmrgstatic int haveIPv6 = 1;
24273143b9aSmrg#endif
24373143b9aSmrg
24473143b9aSmrg/*
24573143b9aSmrg * These are some utility function used by the real interface function below.
24673143b9aSmrg */
24773143b9aSmrg
24873143b9aSmrgstatic int
24973143b9aSmrgTRANS(SocketSelectFamily) (int first, char *family)
25073143b9aSmrg
25173143b9aSmrg{
25273143b9aSmrg    int     i;
25373143b9aSmrg
25473143b9aSmrg    PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
25573143b9aSmrg
25673143b9aSmrg    for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
25773143b9aSmrg    {
25873143b9aSmrg        if (!strcmp (family, Sockettrans2devtab[i].transname))
25973143b9aSmrg	    return i;
26073143b9aSmrg    }
26173143b9aSmrg
26273143b9aSmrg    return (first == -1 ? -2 : -1);
26373143b9aSmrg}
26473143b9aSmrg
26573143b9aSmrg
26673143b9aSmrg/*
26773143b9aSmrg * This function gets the local address of the socket and stores it in the
26873143b9aSmrg * XtransConnInfo structure for the connection.
26973143b9aSmrg */
27073143b9aSmrg
27173143b9aSmrgstatic int
27273143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
27373143b9aSmrg
27473143b9aSmrg{
27573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
27673143b9aSmrg    struct sockaddr_storage socknamev6;
27773143b9aSmrg#endif
27873143b9aSmrg    struct sockaddr_in socknamev4;
27973143b9aSmrg    void *socknamePtr;
28073143b9aSmrg    SOCKLEN_T namelen;
28173143b9aSmrg
28273143b9aSmrg    PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
28373143b9aSmrg
28473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
28573143b9aSmrg    if (haveIPv6)
28673143b9aSmrg    {
28773143b9aSmrg	namelen = sizeof(socknamev6);
28873143b9aSmrg	socknamePtr = &socknamev6;
28973143b9aSmrg    }
29073143b9aSmrg    else
29173143b9aSmrg#endif
29273143b9aSmrg    {
29373143b9aSmrg	namelen = sizeof(socknamev4);
29473143b9aSmrg	socknamePtr = &socknamev4;
29573143b9aSmrg    }
29673143b9aSmrg
29773143b9aSmrg    bzero(socknamePtr, namelen);
29873143b9aSmrg
29973143b9aSmrg    if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
30073143b9aSmrg		     (void *)&namelen) < 0)
30173143b9aSmrg    {
30273143b9aSmrg#ifdef WIN32
30373143b9aSmrg	errno = WSAGetLastError();
30473143b9aSmrg#endif
30573143b9aSmrg	PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
30673143b9aSmrg	    EGET(),0, 0);
30773143b9aSmrg	return -1;
30873143b9aSmrg    }
30973143b9aSmrg
31073143b9aSmrg    /*
31173143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
31273143b9aSmrg     */
31373143b9aSmrg
31473143b9aSmrg    if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
31573143b9aSmrg    {
31673143b9aSmrg        PRMSG (1,
31773143b9aSmrg	    "SocketINETGetAddr: Can't allocate space for the addr\n",
31873143b9aSmrg	    0, 0, 0);
31973143b9aSmrg        return -1;
32073143b9aSmrg    }
32173143b9aSmrg
32273143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
32373143b9aSmrg    if (haveIPv6)
32473143b9aSmrg    {
32573143b9aSmrg	ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
32673143b9aSmrg    }
32773143b9aSmrg    else
32873143b9aSmrg#endif
32973143b9aSmrg    {
33073143b9aSmrg	ciptr->family = socknamev4.sin_family;
33173143b9aSmrg    }
33273143b9aSmrg    ciptr->addrlen = namelen;
33373143b9aSmrg    memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
33473143b9aSmrg
33573143b9aSmrg    return 0;
33673143b9aSmrg}
33773143b9aSmrg
33873143b9aSmrg
33973143b9aSmrg/*
34073143b9aSmrg * This function gets the remote address of the socket and stores it in the
34173143b9aSmrg * XtransConnInfo structure for the connection.
34273143b9aSmrg */
34373143b9aSmrg
34473143b9aSmrgstatic int
34573143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
34673143b9aSmrg
34773143b9aSmrg{
34873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
34973143b9aSmrg    struct sockaddr_storage socknamev6;
35073143b9aSmrg#endif
35173143b9aSmrg    struct sockaddr_in 	socknamev4;
35273143b9aSmrg    void *socknamePtr;
35373143b9aSmrg    SOCKLEN_T namelen;
35473143b9aSmrg
35573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
35673143b9aSmrg    if (haveIPv6 && ciptr->family == AF_INET6)
35773143b9aSmrg    {
35873143b9aSmrg	namelen = sizeof(socknamev6);
35973143b9aSmrg	socknamePtr = &socknamev6;
36073143b9aSmrg    }
36173143b9aSmrg    else
36273143b9aSmrg#endif
36373143b9aSmrg    {
36473143b9aSmrg	namelen = sizeof(socknamev4);
36573143b9aSmrg	socknamePtr = &socknamev4;
36673143b9aSmrg    }
36773143b9aSmrg
36873143b9aSmrg    bzero(socknamePtr, namelen);
36973143b9aSmrg
37073143b9aSmrg    PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
37173143b9aSmrg
37273143b9aSmrg    if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
37373143b9aSmrg		     (void *)&namelen) < 0)
37473143b9aSmrg    {
37573143b9aSmrg#ifdef WIN32
37673143b9aSmrg	errno = WSAGetLastError();
37773143b9aSmrg#endif
37873143b9aSmrg	PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
37973143b9aSmrg	    EGET(), 0, 0);
38073143b9aSmrg	return -1;
38173143b9aSmrg    }
38273143b9aSmrg
38373143b9aSmrg    /*
38473143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
38573143b9aSmrg     */
38673143b9aSmrg
38773143b9aSmrg    if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
38873143b9aSmrg    {
38973143b9aSmrg        PRMSG (1,
39073143b9aSmrg	   "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
39173143b9aSmrg	   0, 0, 0);
39273143b9aSmrg        return -1;
39373143b9aSmrg    }
39473143b9aSmrg
39573143b9aSmrg    ciptr->peeraddrlen = namelen;
39673143b9aSmrg    memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
39773143b9aSmrg
39873143b9aSmrg    return 0;
39973143b9aSmrg}
40073143b9aSmrg
40173143b9aSmrg
40273143b9aSmrgstatic XtransConnInfo
40373143b9aSmrgTRANS(SocketOpen) (int i, int type)
40473143b9aSmrg
40573143b9aSmrg{
40673143b9aSmrg    XtransConnInfo	ciptr;
40773143b9aSmrg
40873143b9aSmrg    PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
40973143b9aSmrg
41073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
41173143b9aSmrg    if (getaddrinfo == NULL)
41273143b9aSmrg	haveIPv6 = 0;
41373143b9aSmrg
41473143b9aSmrg    if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
41573143b9aSmrg	return NULL;
41673143b9aSmrg#endif
41773143b9aSmrg
41873143b9aSmrg    if ((ciptr = (XtransConnInfo) xcalloc (
41973143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
42073143b9aSmrg    {
42173143b9aSmrg	PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
42273143b9aSmrg	return NULL;
42373143b9aSmrg    }
42473143b9aSmrg
42573143b9aSmrg    if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
42673143b9aSmrg	Sockettrans2devtab[i].protocol)) < 0
42773143b9aSmrg#ifndef WIN32
42873143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
4298d4c0f7bSmrg       || ciptr->fd >= sysconf(_SC_OPEN_MAX)
43073143b9aSmrg#endif
43173143b9aSmrg#endif
43273143b9aSmrg      ) {
43373143b9aSmrg#ifdef WIN32
43473143b9aSmrg	errno = WSAGetLastError();
43573143b9aSmrg#endif
43673143b9aSmrg	PRMSG (2, "SocketOpen: socket() failed for %s\n",
43773143b9aSmrg	    Sockettrans2devtab[i].transname, 0, 0);
43873143b9aSmrg
43973143b9aSmrg	xfree ((char *) ciptr);
44073143b9aSmrg	return NULL;
44173143b9aSmrg    }
44273143b9aSmrg
44373143b9aSmrg#ifdef TCP_NODELAY
44473143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
44573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
44673143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
44773143b9aSmrg#endif
44873143b9aSmrg    )
44973143b9aSmrg    {
45073143b9aSmrg	/*
45173143b9aSmrg	 * turn off TCP coalescence for INET sockets
45273143b9aSmrg	 */
45373143b9aSmrg
45473143b9aSmrg	int tmp = 1;
45573143b9aSmrg	setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
45673143b9aSmrg	    (char *) &tmp, sizeof (int));
45773143b9aSmrg    }
45873143b9aSmrg#endif
45973143b9aSmrg
46073143b9aSmrg    return ciptr;
46173143b9aSmrg}
46273143b9aSmrg
46373143b9aSmrg
46473143b9aSmrg#ifdef TRANS_REOPEN
46573143b9aSmrg
46673143b9aSmrgstatic XtransConnInfo
46773143b9aSmrgTRANS(SocketReopen) (int i, int type, int fd, char *port)
46873143b9aSmrg
46973143b9aSmrg{
47073143b9aSmrg    XtransConnInfo	ciptr;
47173143b9aSmrg    int portlen;
47273143b9aSmrg    struct sockaddr *addr;
47373143b9aSmrg
47473143b9aSmrg    PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
47573143b9aSmrg
47673143b9aSmrg    if (port == NULL) {
47773143b9aSmrg      PRMSG (1, "SocketReopen: port was null!\n", 0, 0, 0);
47873143b9aSmrg      return NULL;
47973143b9aSmrg    }
48073143b9aSmrg
48173143b9aSmrg    portlen = strlen(port) + 1; // include space for trailing null
48273143b9aSmrg#ifdef SOCK_MAXADDRLEN
48373143b9aSmrg    if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
48473143b9aSmrg      PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0);
48573143b9aSmrg      return NULL;
48673143b9aSmrg    }
48773143b9aSmrg    if (portlen < 14) portlen = 14;
48873143b9aSmrg#else
48973143b9aSmrg    if (portlen < 0 || portlen > 14) {
49073143b9aSmrg      PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0);
49173143b9aSmrg      return NULL;
49273143b9aSmrg    }
49373143b9aSmrg#endif /*SOCK_MAXADDRLEN*/
49473143b9aSmrg
49573143b9aSmrg    if ((ciptr = (XtransConnInfo) xcalloc (
49673143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
49773143b9aSmrg    {
49873143b9aSmrg	PRMSG (1, "SocketReopen: malloc(ciptr) failed\n", 0, 0, 0);
49973143b9aSmrg	return NULL;
50073143b9aSmrg    }
50173143b9aSmrg
50273143b9aSmrg    ciptr->fd = fd;
50373143b9aSmrg
50473143b9aSmrg    if ((addr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) {
50573143b9aSmrg	PRMSG (1, "SocketReopen: malloc(addr) failed\n", 0, 0, 0);
50673143b9aSmrg	return NULL;
50773143b9aSmrg    }
5088d4c0f7bSmrg    ciptr->addr = (char *) addr;
50973143b9aSmrg    ciptr->addrlen = portlen + 2;
51073143b9aSmrg
5118d4c0f7bSmrg    if ((ciptr->peeraddr = (char *) xcalloc (1, portlen + 2)) == NULL) {
51273143b9aSmrg	PRMSG (1, "SocketReopen: malloc(portaddr) failed\n", 0, 0, 0);
51373143b9aSmrg	return NULL;
51473143b9aSmrg    }
51573143b9aSmrg    ciptr->peeraddrlen = portlen + 2;
51673143b9aSmrg
51773143b9aSmrg    /* Initialize ciptr structure as if it were a normally-opened unix socket */
51873143b9aSmrg    ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
51973143b9aSmrg#ifdef BSD44SOCKETS
52073143b9aSmrg    addr->sa_len = portlen + 1;
52173143b9aSmrg#endif
52273143b9aSmrg    addr->sa_family = AF_UNIX;
52373143b9aSmrg#ifdef HAS_STRLCPY
52473143b9aSmrg    strlcpy(addr->sa_data, port, portlen);
52573143b9aSmrg#else
52673143b9aSmrg    strncpy(addr->sa_data, port, portlen);
52773143b9aSmrg#endif
52873143b9aSmrg    ciptr->family = AF_UNIX;
52973143b9aSmrg    memcpy(ciptr->peeraddr, ciptr->addr, sizeof(struct sockaddr));
53073143b9aSmrg    ciptr->port = rindex(addr->sa_data, ':');
53173143b9aSmrg    if (ciptr->port[0] == ':') ciptr->port++; /* port should now point to portnum or NULL */
53273143b9aSmrg    return ciptr;
53373143b9aSmrg}
53473143b9aSmrg
53573143b9aSmrg#endif /* TRANS_REOPEN */
53673143b9aSmrg
53773143b9aSmrg
53873143b9aSmrg/*
53973143b9aSmrg * These functions are the interface supplied in the Xtransport structure
54073143b9aSmrg */
54173143b9aSmrg
54273143b9aSmrg#ifdef TRANS_CLIENT
54373143b9aSmrg
54473143b9aSmrgstatic XtransConnInfo
54573143b9aSmrgTRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
54673143b9aSmrg				char *host, char *port, int previndex)
54773143b9aSmrg{
54873143b9aSmrg    XtransConnInfo	ciptr;
54973143b9aSmrg    int			i = previndex;
55073143b9aSmrg
55173143b9aSmrg    PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
55273143b9aSmrg	protocol, host, port);
55373143b9aSmrg
55473143b9aSmrg    SocketInitOnce();
55573143b9aSmrg
55673143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
55773143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
55873143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
55973143b9aSmrg	    break;
56073143b9aSmrg    }
56173143b9aSmrg    if (i < 0) {
56273143b9aSmrg	if (i == -1)
56373143b9aSmrg	    PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
56473143b9aSmrg		   transname, 0, 0);
56573143b9aSmrg	else
56673143b9aSmrg	    PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
56773143b9aSmrg		   transname, 0, 0);
56873143b9aSmrg	return NULL;
56973143b9aSmrg    }
57073143b9aSmrg
57173143b9aSmrg    /* Save the index for later use */
57273143b9aSmrg
57373143b9aSmrg    ciptr->index = i;
57473143b9aSmrg
57573143b9aSmrg    return ciptr;
57673143b9aSmrg}
57773143b9aSmrg
57873143b9aSmrgstatic XtransConnInfo
57973143b9aSmrgTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
58073143b9aSmrg			     char *host, char *port)
58173143b9aSmrg{
58273143b9aSmrg    return TRANS(SocketOpenCOTSClientBase)(
58373143b9aSmrg			thistrans->TransName, protocol, host, port, -1);
58473143b9aSmrg}
58573143b9aSmrg
58673143b9aSmrg
58773143b9aSmrg#endif /* TRANS_CLIENT */
58873143b9aSmrg
58973143b9aSmrg
59073143b9aSmrg#ifdef TRANS_SERVER
59173143b9aSmrg
59273143b9aSmrgstatic XtransConnInfo
59373143b9aSmrgTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
59473143b9aSmrg			     char *host, char *port)
59573143b9aSmrg
59673143b9aSmrg{
59773143b9aSmrg    XtransConnInfo	ciptr;
59873143b9aSmrg    int	i = -1;
59973143b9aSmrg
60073143b9aSmrg    PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
60173143b9aSmrg
60273143b9aSmrg    SocketInitOnce();
60373143b9aSmrg
60473143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
60573143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
60673143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
60773143b9aSmrg	    break;
60873143b9aSmrg    }
60973143b9aSmrg    if (i < 0) {
61073143b9aSmrg	if (i == -1)
61173143b9aSmrg	    PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
61273143b9aSmrg		   thistrans->TransName, 0, 0);
61373143b9aSmrg	else
61473143b9aSmrg	    PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
61573143b9aSmrg		   thistrans->TransName, 0, 0);
61673143b9aSmrg	return NULL;
61773143b9aSmrg    }
61873143b9aSmrg
61973143b9aSmrg    /*
62073143b9aSmrg     * Using this prevents the bind() check for an existing server listening
62173143b9aSmrg     * on the same port, but it is required for other reasons.
62273143b9aSmrg     */
62373143b9aSmrg#ifdef SO_REUSEADDR
62473143b9aSmrg
62573143b9aSmrg    /*
62673143b9aSmrg     * SO_REUSEADDR only applied to AF_INET && AF_INET6
62773143b9aSmrg     */
62873143b9aSmrg
62973143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
63073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
63173143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
63273143b9aSmrg#endif
63373143b9aSmrg    )
63473143b9aSmrg    {
63573143b9aSmrg	int one = 1;
63673143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
63773143b9aSmrg		    (char *) &one, sizeof (int));
63873143b9aSmrg    }
63973143b9aSmrg#endif
64073143b9aSmrg#ifdef IPV6_V6ONLY
64173143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
64273143b9aSmrg    {
64373143b9aSmrg	int one = 1;
64473143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
64573143b9aSmrg    }
64673143b9aSmrg#endif
64773143b9aSmrg    /* Save the index for later use */
64873143b9aSmrg
64973143b9aSmrg    ciptr->index = i;
65073143b9aSmrg
65173143b9aSmrg    return ciptr;
65273143b9aSmrg}
65373143b9aSmrg
65473143b9aSmrg#endif /* TRANS_SERVER */
65573143b9aSmrg
65673143b9aSmrg
65773143b9aSmrg#ifdef TRANS_CLIENT
65873143b9aSmrg
65973143b9aSmrgstatic XtransConnInfo
66073143b9aSmrgTRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
66173143b9aSmrg			     char *host, char *port)
66273143b9aSmrg
66373143b9aSmrg{
66473143b9aSmrg    XtransConnInfo	ciptr;
66573143b9aSmrg    int			i = -1;
66673143b9aSmrg
66773143b9aSmrg    PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
66873143b9aSmrg
66973143b9aSmrg    SocketInitOnce();
67073143b9aSmrg
67173143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
67273143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
67373143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
67473143b9aSmrg	    break;
67573143b9aSmrg    }
67673143b9aSmrg    if (i < 0) {
67773143b9aSmrg	if (i == -1)
67873143b9aSmrg	    PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
67973143b9aSmrg		   thistrans->TransName, 0, 0);
68073143b9aSmrg	else
68173143b9aSmrg	    PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
68273143b9aSmrg		   thistrans->TransName, 0, 0);
68373143b9aSmrg	return NULL;
68473143b9aSmrg    }
68573143b9aSmrg
68673143b9aSmrg    /* Save the index for later use */
68773143b9aSmrg
68873143b9aSmrg    ciptr->index = i;
68973143b9aSmrg
69073143b9aSmrg    return ciptr;
69173143b9aSmrg}
69273143b9aSmrg
69373143b9aSmrg#endif /* TRANS_CLIENT */
69473143b9aSmrg
69573143b9aSmrg
69673143b9aSmrg#ifdef TRANS_SERVER
69773143b9aSmrg
69873143b9aSmrgstatic XtransConnInfo
69973143b9aSmrgTRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
70073143b9aSmrg			     char *host, char *port)
70173143b9aSmrg
70273143b9aSmrg{
70373143b9aSmrg    XtransConnInfo	ciptr;
70473143b9aSmrg    int	i = -1;
70573143b9aSmrg
70673143b9aSmrg    PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
70773143b9aSmrg
70873143b9aSmrg    SocketInitOnce();
70973143b9aSmrg
71073143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
71173143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
71273143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
71373143b9aSmrg	    break;
71473143b9aSmrg    }
71573143b9aSmrg    if (i < 0) {
71673143b9aSmrg	if (i == -1)
71773143b9aSmrg	    PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
71873143b9aSmrg		   thistrans->TransName, 0, 0);
71973143b9aSmrg	else
72073143b9aSmrg	    PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
72173143b9aSmrg		   thistrans->TransName, 0, 0);
72273143b9aSmrg	return NULL;
72373143b9aSmrg    }
72473143b9aSmrg
72573143b9aSmrg#ifdef IPV6_V6ONLY
72673143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
72773143b9aSmrg    {
72873143b9aSmrg	int one = 1;
72973143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
73073143b9aSmrg    }
73173143b9aSmrg#endif
73273143b9aSmrg    /* Save the index for later use */
73373143b9aSmrg
73473143b9aSmrg    ciptr->index = i;
73573143b9aSmrg
73673143b9aSmrg    return ciptr;
73773143b9aSmrg}
73873143b9aSmrg
73973143b9aSmrg#endif /* TRANS_SERVER */
74073143b9aSmrg
74173143b9aSmrg
74273143b9aSmrg#ifdef TRANS_REOPEN
74373143b9aSmrg
74473143b9aSmrgstatic XtransConnInfo
74573143b9aSmrgTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
74673143b9aSmrg
74773143b9aSmrg{
74873143b9aSmrg    XtransConnInfo	ciptr;
74973143b9aSmrg    int			i = -1;
75073143b9aSmrg
75173143b9aSmrg    PRMSG (2,
75273143b9aSmrg	"SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
75373143b9aSmrg
75473143b9aSmrg    SocketInitOnce();
75573143b9aSmrg
75673143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
75773143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
75873143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
75973143b9aSmrg	    break;
76073143b9aSmrg    }
76173143b9aSmrg    if (i < 0) {
76273143b9aSmrg	if (i == -1)
76373143b9aSmrg	    PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
76473143b9aSmrg		   thistrans->TransName, 0, 0);
76573143b9aSmrg	else
76673143b9aSmrg	    PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
76773143b9aSmrg		   thistrans->TransName, 0, 0);
76873143b9aSmrg	return NULL;
76973143b9aSmrg    }
77073143b9aSmrg
77173143b9aSmrg    /* Save the index for later use */
77273143b9aSmrg
77373143b9aSmrg    ciptr->index = i;
77473143b9aSmrg
77573143b9aSmrg    return ciptr;
77673143b9aSmrg}
77773143b9aSmrg
77873143b9aSmrgstatic XtransConnInfo
77973143b9aSmrgTRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
78073143b9aSmrg
78173143b9aSmrg{
78273143b9aSmrg    XtransConnInfo	ciptr;
78373143b9aSmrg    int			i = -1;
78473143b9aSmrg
78573143b9aSmrg    PRMSG (2,
78673143b9aSmrg	"SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
78773143b9aSmrg
78873143b9aSmrg    SocketInitOnce();
78973143b9aSmrg
79073143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
79173143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
79273143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
79373143b9aSmrg	    break;
79473143b9aSmrg    }
79573143b9aSmrg    if (i < 0) {
79673143b9aSmrg	if (i == -1)
79773143b9aSmrg	    PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
79873143b9aSmrg		   thistrans->TransName, 0, 0);
79973143b9aSmrg	else
80073143b9aSmrg	    PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
80173143b9aSmrg		   thistrans->TransName, 0, 0);
80273143b9aSmrg	return NULL;
80373143b9aSmrg    }
80473143b9aSmrg
80573143b9aSmrg    /* Save the index for later use */
80673143b9aSmrg
80773143b9aSmrg    ciptr->index = i;
80873143b9aSmrg
80973143b9aSmrg    return ciptr;
81073143b9aSmrg}
81173143b9aSmrg
81273143b9aSmrg#endif /* TRANS_REOPEN */
81373143b9aSmrg
81473143b9aSmrg
81573143b9aSmrgstatic int
81673143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
81773143b9aSmrg
81873143b9aSmrg{
81973143b9aSmrg    PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
82073143b9aSmrg
82173143b9aSmrg    return -1;
82273143b9aSmrg}
82373143b9aSmrg
82473143b9aSmrg#ifdef UNIXCONN
82573143b9aSmrgstatic int
82673143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract)
82773143b9aSmrg{
82873143b9aSmrg    struct sockaddr_un s;
82973143b9aSmrg    int maxlen = sizeof(s.sun_path) - 1;
83073143b9aSmrg    const char *at = "";
83173143b9aSmrg
83273143b9aSmrg    if (!port || !*port || !path)
83373143b9aSmrg	return -1;
83473143b9aSmrg
83573143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
83673143b9aSmrg    if (port[0] == '@')
83773143b9aSmrg	upath = "";
83873143b9aSmrg    else if (abstract)
83973143b9aSmrg	at = "@";
84073143b9aSmrg#endif
84173143b9aSmrg
84273143b9aSmrg    if (*port == '/') /* a full pathname */
84373143b9aSmrg	upath = "";
84473143b9aSmrg
84573143b9aSmrg    if (strlen(port) + strlen(upath) > maxlen)
84673143b9aSmrg	return -1;
84773143b9aSmrg    sprintf(path, "%s%s%s", at, upath, port);
84873143b9aSmrg    return 0;
84973143b9aSmrg}
85073143b9aSmrg#endif
85173143b9aSmrg
85273143b9aSmrg#ifdef TRANS_SERVER
85373143b9aSmrg
85473143b9aSmrgstatic int
85573143b9aSmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr,
85673143b9aSmrg			     struct sockaddr *sockname,
85773143b9aSmrg			     int socknamelen, unsigned int flags)
85873143b9aSmrg
85973143b9aSmrg{
86073143b9aSmrg    SOCKLEN_T namelen = socknamelen;
86173143b9aSmrg    int	fd = ciptr->fd;
86273143b9aSmrg    int	retry;
86373143b9aSmrg
86473143b9aSmrg    PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
86573143b9aSmrg
86673143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
86773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
86873143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
86973143b9aSmrg#endif
87073143b9aSmrg	)
87173143b9aSmrg	retry = 20;
87273143b9aSmrg    else
87373143b9aSmrg	retry = 0;
87473143b9aSmrg
87573143b9aSmrg    while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
87673143b9aSmrg    {
87773143b9aSmrg	if (errno == EADDRINUSE) {
87873143b9aSmrg	    if (flags & ADDR_IN_USE_ALLOWED)
87973143b9aSmrg		break;
88073143b9aSmrg	    else
88173143b9aSmrg		return TRANS_ADDR_IN_USE;
88273143b9aSmrg	}
88373143b9aSmrg
88473143b9aSmrg	if (retry-- == 0) {
88573143b9aSmrg	    PRMSG (1, "SocketCreateListener: failed to bind listener\n",
88673143b9aSmrg		0, 0, 0);
88773143b9aSmrg	    close (fd);
88873143b9aSmrg	    return TRANS_CREATE_LISTENER_FAILED;
88973143b9aSmrg	}
89073143b9aSmrg#ifdef SO_REUSEADDR
89173143b9aSmrg	sleep (1);
89273143b9aSmrg#else
89373143b9aSmrg	sleep (10);
89473143b9aSmrg#endif /* SO_REUSEDADDR */
89573143b9aSmrg    }
89673143b9aSmrg
89773143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
89873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
89973143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
90073143b9aSmrg#endif
90173143b9aSmrg	) {
90273143b9aSmrg#ifdef SO_DONTLINGER
90373143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
90473143b9aSmrg#else
90573143b9aSmrg#ifdef SO_LINGER
90673143b9aSmrg    {
90773143b9aSmrg	static int linger[2] = { 0, 0 };
90873143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_LINGER,
90973143b9aSmrg		(char *) linger, sizeof (linger));
91073143b9aSmrg    }
91173143b9aSmrg#endif
91273143b9aSmrg#endif
91373143b9aSmrg}
91473143b9aSmrg
91573143b9aSmrg    if (listen (fd, BACKLOG) < 0)
91673143b9aSmrg    {
91773143b9aSmrg	PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
91873143b9aSmrg	close (fd);
91973143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
92073143b9aSmrg    }
92173143b9aSmrg
92273143b9aSmrg    /* Set a flag to indicate that this connection is a listener */
92373143b9aSmrg
92473143b9aSmrg    ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
92573143b9aSmrg
92673143b9aSmrg    return 0;
92773143b9aSmrg}
92873143b9aSmrg
92973143b9aSmrg#ifdef TCPCONN
93073143b9aSmrgstatic int
93173143b9aSmrgTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
93273143b9aSmrg
93373143b9aSmrg{
93473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
93573143b9aSmrg    struct sockaddr_storage sockname;
93673143b9aSmrg#else
93773143b9aSmrg    struct sockaddr_in	    sockname;
93873143b9aSmrg#endif
93973143b9aSmrg    unsigned short	    sport;
94073143b9aSmrg    SOCKLEN_T	namelen = sizeof(sockname);
94173143b9aSmrg    int		status;
94273143b9aSmrg    long	tmpport;
94373143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
94473143b9aSmrg    _Xgetservbynameparams sparams;
94573143b9aSmrg#endif
94673143b9aSmrg    struct servent *servp;
94773143b9aSmrg
94873143b9aSmrg#ifdef X11_t
94973143b9aSmrg    char	portbuf[PORTBUFSIZE];
95073143b9aSmrg#endif
95173143b9aSmrg
95273143b9aSmrg    PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
95373143b9aSmrg
95473143b9aSmrg#ifdef X11_t
95573143b9aSmrg    /*
95673143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
95773143b9aSmrg     * to handle it here, than try and come up with a transport independent
95873143b9aSmrg     * representation that can be passed in and resolved the usual way.
95973143b9aSmrg     *
96073143b9aSmrg     * The port that is passed here is really a string containing the idisplay
96173143b9aSmrg     * from ConnectDisplay().
96273143b9aSmrg     */
96373143b9aSmrg
96473143b9aSmrg    if (is_numeric (port))
96573143b9aSmrg    {
96673143b9aSmrg	/* fixup the server port address */
96773143b9aSmrg	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
96873143b9aSmrg	sprintf (portbuf,"%lu", tmpport);
96973143b9aSmrg	port = portbuf;
97073143b9aSmrg    }
97173143b9aSmrg#endif
97273143b9aSmrg
97373143b9aSmrg    if (port && *port)
97473143b9aSmrg    {
97573143b9aSmrg	/* Check to see if the port string is just a number (handles X11) */
97673143b9aSmrg
97773143b9aSmrg	if (!is_numeric (port))
97873143b9aSmrg	{
97973143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
98073143b9aSmrg	    {
98173143b9aSmrg		PRMSG (1,
98273143b9aSmrg	     "SocketINETCreateListener: Unable to get service for %s\n",
98373143b9aSmrg		      port, 0, 0);
98473143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
98573143b9aSmrg	    }
98673143b9aSmrg	    /* we trust getservbyname to return a valid number */
98773143b9aSmrg	    sport = servp->s_port;
98873143b9aSmrg	}
98973143b9aSmrg	else
99073143b9aSmrg	{
99173143b9aSmrg	    tmpport = strtol (port, (char**)NULL, 10);
99273143b9aSmrg	    /*
99373143b9aSmrg	     * check that somehow the port address isn't negative or in
99473143b9aSmrg	     * the range of reserved port addresses. This can happen and
99573143b9aSmrg	     * be very bad if the server is suid-root and the user does
99673143b9aSmrg	     * something (dumb) like `X :60049`.
99773143b9aSmrg	     */
99873143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
99973143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
100073143b9aSmrg
100173143b9aSmrg	    sport = (unsigned short) tmpport;
100273143b9aSmrg	}
100373143b9aSmrg    }
100473143b9aSmrg    else
100573143b9aSmrg	sport = 0;
100673143b9aSmrg
100773143b9aSmrg    bzero(&sockname, sizeof(sockname));
100873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
100973143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
101073143b9aSmrg	namelen = sizeof (struct sockaddr_in);
101173143b9aSmrg#ifdef BSD44SOCKETS
101273143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_len = namelen;
101373143b9aSmrg#endif
101473143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
101573143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
101673143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
101773143b9aSmrg    } else {
101873143b9aSmrg	namelen = sizeof (struct sockaddr_in6);
101973143b9aSmrg#ifdef SIN6_LEN
102073143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
102173143b9aSmrg#endif
102273143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
102373143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
102473143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
102573143b9aSmrg    }
102673143b9aSmrg#else
102773143b9aSmrg#ifdef BSD44SOCKETS
102873143b9aSmrg    sockname.sin_len = sizeof (sockname);
102973143b9aSmrg#endif
103073143b9aSmrg    sockname.sin_family = AF_INET;
103173143b9aSmrg    sockname.sin_port = htons (sport);
103273143b9aSmrg    sockname.sin_addr.s_addr = htonl (INADDR_ANY);
103373143b9aSmrg#endif
103473143b9aSmrg
103573143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
103673143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
103773143b9aSmrg    {
103873143b9aSmrg	PRMSG (1,
103973143b9aSmrg    "SocketINETCreateListener: ...SocketCreateListener() failed\n",
104073143b9aSmrg	    0, 0, 0);
104173143b9aSmrg	return status;
104273143b9aSmrg    }
104373143b9aSmrg
104473143b9aSmrg    if (TRANS(SocketINETGetAddr) (ciptr) < 0)
104573143b9aSmrg    {
104673143b9aSmrg	PRMSG (1,
104773143b9aSmrg       "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
104873143b9aSmrg	    0, 0, 0);
104973143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
105073143b9aSmrg    }
105173143b9aSmrg
105273143b9aSmrg    return 0;
105373143b9aSmrg}
105473143b9aSmrg
105573143b9aSmrg#endif /* TCPCONN */
105673143b9aSmrg
105773143b9aSmrg
105873143b9aSmrg#ifdef UNIXCONN
105973143b9aSmrg
106073143b9aSmrgstatic int
106173143b9aSmrgTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
106273143b9aSmrg				 unsigned int flags)
106373143b9aSmrg
106473143b9aSmrg{
106573143b9aSmrg    struct sockaddr_un	sockname;
106673143b9aSmrg    int			namelen;
106773143b9aSmrg    int			oldUmask;
106873143b9aSmrg    int			status;
106973143b9aSmrg    unsigned int	mode;
107073143b9aSmrg    char		tmpport[108];
107173143b9aSmrg
107273143b9aSmrg    int			abstract = 0;
107373143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
107473143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
107573143b9aSmrg#endif
107673143b9aSmrg
107773143b9aSmrg    PRMSG (2, "SocketUNIXCreateListener(%s)\n",
107873143b9aSmrg	port ? port : "NULL", 0, 0);
107973143b9aSmrg
108073143b9aSmrg    /* Make sure the directory is created */
108173143b9aSmrg
108273143b9aSmrg    oldUmask = umask (0);
108373143b9aSmrg
108473143b9aSmrg#ifdef UNIX_DIR
108573143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
108673143b9aSmrg    mode = 01777;
108773143b9aSmrg#else
108873143b9aSmrg    mode = 0777;
108973143b9aSmrg#endif
10908d4c0f7bSmrg    if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
109173143b9aSmrg	PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
109273143b9aSmrg	       UNIX_DIR, errno, 0);
109373143b9aSmrg	(void) umask (oldUmask);
109473143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
109573143b9aSmrg    }
109673143b9aSmrg#endif
109773143b9aSmrg
109873143b9aSmrg    memset(&sockname, 0, sizeof(sockname));
109973143b9aSmrg    sockname.sun_family = AF_UNIX;
110073143b9aSmrg
110173143b9aSmrg    if (!(port && *port)) {
110273143b9aSmrg	snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
110373143b9aSmrg	port = tmpport;
110473143b9aSmrg    }
110573143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
110673143b9aSmrg	PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
110773143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
110873143b9aSmrg    }
110973143b9aSmrg
11108d4c0f7bSmrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
111173143b9aSmrg    sockname.sun_len = strlen(sockname.sun_path);
111273143b9aSmrg#endif
111373143b9aSmrg
111473143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
111573143b9aSmrg    namelen = SUN_LEN(&sockname);
111673143b9aSmrg#else
111773143b9aSmrg    namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
111873143b9aSmrg#endif
111973143b9aSmrg
112073143b9aSmrg    if (abstract) {
112173143b9aSmrg	sockname.sun_path[0] = '\0';
112273143b9aSmrg	namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
112373143b9aSmrg    }
112473143b9aSmrg    else
112573143b9aSmrg	unlink (sockname.sun_path);
112673143b9aSmrg
112773143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
112873143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
112973143b9aSmrg    {
113073143b9aSmrg	PRMSG (1,
113173143b9aSmrg    "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
113273143b9aSmrg	    0, 0, 0);
113373143b9aSmrg	(void) umask (oldUmask);
113473143b9aSmrg	return status;
113573143b9aSmrg    }
113673143b9aSmrg
113773143b9aSmrg    /*
113873143b9aSmrg     * Now that the listener is esablished, create the addr info for
113973143b9aSmrg     * this connection. getpeername() doesn't work for UNIX Domain Sockets
114073143b9aSmrg     * on some systems (hpux at least), so we will just do it manually, instead
114173143b9aSmrg     * of calling something like TRANS(SocketUNIXGetAddr).
114273143b9aSmrg     */
114373143b9aSmrg
114473143b9aSmrg    namelen = sizeof (sockname); /* this will always make it the same size */
114573143b9aSmrg
114673143b9aSmrg    if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
114773143b9aSmrg    {
114873143b9aSmrg        PRMSG (1,
114973143b9aSmrg        "SocketUNIXCreateListener: Can't allocate space for the addr\n",
115073143b9aSmrg	    0, 0, 0);
115173143b9aSmrg	(void) umask (oldUmask);
115273143b9aSmrg        return TRANS_CREATE_LISTENER_FAILED;
115373143b9aSmrg    }
115473143b9aSmrg
115573143b9aSmrg    if (abstract)
115673143b9aSmrg	sockname.sun_path[0] = '@';
115773143b9aSmrg
115873143b9aSmrg    ciptr->family = sockname.sun_family;
115973143b9aSmrg    ciptr->addrlen = namelen;
116073143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
116173143b9aSmrg
116273143b9aSmrg    (void) umask (oldUmask);
116373143b9aSmrg
116473143b9aSmrg    return 0;
116573143b9aSmrg}
116673143b9aSmrg
116773143b9aSmrg
116873143b9aSmrgstatic int
116973143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
117073143b9aSmrg
117173143b9aSmrg{
117273143b9aSmrg    /*
117373143b9aSmrg     * See if the unix domain socket has disappeared.  If it has, recreate it.
117473143b9aSmrg     */
117573143b9aSmrg
117673143b9aSmrg    struct sockaddr_un 	*unsock = (struct sockaddr_un *) ciptr->addr;
117773143b9aSmrg    struct stat		statb;
117873143b9aSmrg    int 		status = TRANS_RESET_NOOP;
117973143b9aSmrg    unsigned int	mode;
118073143b9aSmrg    int abstract = 0;
118173143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
118273143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
118373143b9aSmrg#endif
118473143b9aSmrg
118573143b9aSmrg    PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
118673143b9aSmrg
118773143b9aSmrg    if (!abstract && (
118873143b9aSmrg	stat (unsock->sun_path, &statb) == -1 ||
118973143b9aSmrg        ((statb.st_mode & S_IFMT) !=
119073143b9aSmrg#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
119173143b9aSmrg	  		S_IFIFO
119273143b9aSmrg#else
119373143b9aSmrg			S_IFSOCK
119473143b9aSmrg#endif
119573143b9aSmrg				)))
119673143b9aSmrg    {
119773143b9aSmrg	int oldUmask = umask (0);
119873143b9aSmrg
119973143b9aSmrg#ifdef UNIX_DIR
120073143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
120173143b9aSmrg	mode = 01777;
120273143b9aSmrg#else
120373143b9aSmrg	mode = 0777;
120473143b9aSmrg#endif
120573143b9aSmrg        if (trans_mkdir(UNIX_DIR, mode) == -1) {
120673143b9aSmrg            PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
120773143b9aSmrg	    UNIX_DIR, errno, 0);
120873143b9aSmrg	    (void) umask (oldUmask);
120973143b9aSmrg	    return TRANS_RESET_FAILURE;
121073143b9aSmrg        }
121173143b9aSmrg#endif
121273143b9aSmrg
121373143b9aSmrg	close (ciptr->fd);
121473143b9aSmrg	unlink (unsock->sun_path);
121573143b9aSmrg
121673143b9aSmrg	if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
121773143b9aSmrg	{
121873143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
121973143b9aSmrg	    (void) umask (oldUmask);
122073143b9aSmrg	    return TRANS_RESET_FAILURE;
122173143b9aSmrg	}
122273143b9aSmrg
122373143b9aSmrg	if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
122473143b9aSmrg	{
122573143b9aSmrg	    close (ciptr->fd);
122673143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
122773143b9aSmrg	    return TRANS_RESET_FAILURE;
122873143b9aSmrg	}
122973143b9aSmrg
123073143b9aSmrg	if (listen (ciptr->fd, BACKLOG) < 0)
123173143b9aSmrg	{
123273143b9aSmrg	    close (ciptr->fd);
123373143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
123473143b9aSmrg	    (void) umask (oldUmask);
123573143b9aSmrg	    return TRANS_RESET_FAILURE;
123673143b9aSmrg	}
123773143b9aSmrg
123873143b9aSmrg	umask (oldUmask);
123973143b9aSmrg
124073143b9aSmrg	status = TRANS_RESET_NEW_FD;
124173143b9aSmrg    }
124273143b9aSmrg
124373143b9aSmrg    return status;
124473143b9aSmrg}
124573143b9aSmrg
124673143b9aSmrg#endif /* UNIXCONN */
124773143b9aSmrg
124873143b9aSmrg
124973143b9aSmrg#ifdef TCPCONN
125073143b9aSmrg
125173143b9aSmrgstatic XtransConnInfo
125273143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
125373143b9aSmrg
125473143b9aSmrg{
125573143b9aSmrg    XtransConnInfo	newciptr;
125673143b9aSmrg    struct sockaddr_in	sockname;
125773143b9aSmrg    SOCKLEN_T		namelen = sizeof(sockname);
125873143b9aSmrg
125973143b9aSmrg    PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
126073143b9aSmrg
126173143b9aSmrg    if ((newciptr = (XtransConnInfo) xcalloc (
126273143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
126373143b9aSmrg    {
126473143b9aSmrg	PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
126573143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
126673143b9aSmrg	return NULL;
126773143b9aSmrg    }
126873143b9aSmrg
126973143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
127073143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
127173143b9aSmrg    {
127273143b9aSmrg#ifdef WIN32
127373143b9aSmrg	errno = WSAGetLastError();
127473143b9aSmrg#endif
127573143b9aSmrg	PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
127673143b9aSmrg	xfree (newciptr);
127773143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
127873143b9aSmrg	return NULL;
127973143b9aSmrg    }
128073143b9aSmrg
128173143b9aSmrg#ifdef TCP_NODELAY
128273143b9aSmrg    {
128373143b9aSmrg	/*
128473143b9aSmrg	 * turn off TCP coalescence for INET sockets
128573143b9aSmrg	 */
128673143b9aSmrg
128773143b9aSmrg	int tmp = 1;
128873143b9aSmrg	setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
128973143b9aSmrg	    (char *) &tmp, sizeof (int));
129073143b9aSmrg    }
129173143b9aSmrg#endif
129273143b9aSmrg
129373143b9aSmrg    /*
129473143b9aSmrg     * Get this address again because the transport may give a more
129573143b9aSmrg     * specific address now that a connection is established.
129673143b9aSmrg     */
129773143b9aSmrg
129873143b9aSmrg    if (TRANS(SocketINETGetAddr) (newciptr) < 0)
129973143b9aSmrg    {
130073143b9aSmrg	PRMSG (1,
130173143b9aSmrg	    "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
130273143b9aSmrg	    0, 0, 0);
130373143b9aSmrg	close (newciptr->fd);
130473143b9aSmrg	xfree (newciptr);
130573143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
130673143b9aSmrg        return NULL;
130773143b9aSmrg    }
130873143b9aSmrg
130973143b9aSmrg    if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
131073143b9aSmrg    {
131173143b9aSmrg	PRMSG (1,
131273143b9aSmrg	  "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
131373143b9aSmrg		0, 0, 0);
131473143b9aSmrg	close (newciptr->fd);
131573143b9aSmrg	if (newciptr->addr) xfree (newciptr->addr);
131673143b9aSmrg	xfree (newciptr);
131773143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
131873143b9aSmrg        return NULL;
131973143b9aSmrg    }
132073143b9aSmrg
132173143b9aSmrg    *status = 0;
132273143b9aSmrg
132373143b9aSmrg    return newciptr;
132473143b9aSmrg}
132573143b9aSmrg
132673143b9aSmrg#endif /* TCPCONN */
132773143b9aSmrg
132873143b9aSmrg
132973143b9aSmrg#ifdef UNIXCONN
133073143b9aSmrgstatic XtransConnInfo
133173143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
133273143b9aSmrg
133373143b9aSmrg{
133473143b9aSmrg    XtransConnInfo	newciptr;
133573143b9aSmrg    struct sockaddr_un	sockname;
133673143b9aSmrg    SOCKLEN_T 		namelen = sizeof sockname;
133773143b9aSmrg
133873143b9aSmrg    PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
133973143b9aSmrg
134073143b9aSmrg    if ((newciptr = (XtransConnInfo) xcalloc (
134173143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
134273143b9aSmrg    {
134373143b9aSmrg	PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
134473143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
134573143b9aSmrg	return NULL;
134673143b9aSmrg    }
134773143b9aSmrg
134873143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
134973143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
135073143b9aSmrg    {
135173143b9aSmrg	PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
135273143b9aSmrg	xfree (newciptr);
135373143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
135473143b9aSmrg	return NULL;
135573143b9aSmrg    }
135673143b9aSmrg
135773143b9aSmrg	ciptr->addrlen = namelen;
135873143b9aSmrg    /*
135973143b9aSmrg     * Get the socket name and the peer name from the listener socket,
136073143b9aSmrg     * since this is unix domain.
136173143b9aSmrg     */
136273143b9aSmrg
136373143b9aSmrg    if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
136473143b9aSmrg    {
136573143b9aSmrg        PRMSG (1,
136673143b9aSmrg        "SocketUNIXAccept: Can't allocate space for the addr\n",
136773143b9aSmrg	      0, 0, 0);
136873143b9aSmrg	close (newciptr->fd);
136973143b9aSmrg	xfree (newciptr);
137073143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
137173143b9aSmrg        return NULL;
137273143b9aSmrg    }
137373143b9aSmrg
137473143b9aSmrg    /*
137573143b9aSmrg     * if the socket is abstract, we already modified the address to have a
137673143b9aSmrg     * @ instead of the initial NUL, so no need to do that again here.
137773143b9aSmrg     */
137873143b9aSmrg
137973143b9aSmrg    newciptr->addrlen = ciptr->addrlen;
138073143b9aSmrg    memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
138173143b9aSmrg
138273143b9aSmrg    if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
138373143b9aSmrg    {
138473143b9aSmrg        PRMSG (1,
138573143b9aSmrg	      "SocketUNIXAccept: Can't allocate space for the addr\n",
138673143b9aSmrg	      0, 0, 0);
138773143b9aSmrg	close (newciptr->fd);
138873143b9aSmrg	if (newciptr->addr) xfree (newciptr->addr);
138973143b9aSmrg	xfree (newciptr);
139073143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
139173143b9aSmrg        return NULL;
139273143b9aSmrg    }
139373143b9aSmrg
139473143b9aSmrg    newciptr->peeraddrlen = ciptr->addrlen;
139573143b9aSmrg    memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
139673143b9aSmrg
139773143b9aSmrg    newciptr->family = AF_UNIX;
139873143b9aSmrg
139973143b9aSmrg    *status = 0;
140073143b9aSmrg
140173143b9aSmrg    return newciptr;
140273143b9aSmrg}
140373143b9aSmrg
140473143b9aSmrg#endif /* UNIXCONN */
140573143b9aSmrg
140673143b9aSmrg#endif /* TRANS_SERVER */
140773143b9aSmrg
140873143b9aSmrg
140973143b9aSmrg#ifdef TRANS_CLIENT
141073143b9aSmrg
141173143b9aSmrg#ifdef TCPCONN
141273143b9aSmrg
141373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
141473143b9aSmrgstruct addrlist {
141573143b9aSmrg    struct addrinfo *	addr;
141673143b9aSmrg    struct addrinfo *	firstaddr;
141773143b9aSmrg    char 		port[PORTBUFSIZE];
141873143b9aSmrg    char 		host[MAXHOSTNAMELEN];
141973143b9aSmrg};
142073143b9aSmrgstatic struct addrlist  *addrlist = NULL;
142173143b9aSmrg#endif
142273143b9aSmrg
142373143b9aSmrg
142473143b9aSmrgstatic int
142573143b9aSmrgTRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
142673143b9aSmrg
142773143b9aSmrg{
142873143b9aSmrg    struct sockaddr *	socketaddr = NULL;
142973143b9aSmrg    int			socketaddrlen = 0;
143073143b9aSmrg    int			res;
143173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
143273143b9aSmrg    struct addrinfo 	hints;
143373143b9aSmrg    char		ntopbuf[INET6_ADDRSTRLEN];
143473143b9aSmrg    int			resetonce = 0;
143573143b9aSmrg#endif
143673143b9aSmrg    struct sockaddr_in	sockname;
143773143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
143873143b9aSmrg    _Xgethostbynameparams hparams;
143973143b9aSmrg    _Xgetservbynameparams sparams;
144073143b9aSmrg#endif
144173143b9aSmrg    struct hostent	*hostp;
144273143b9aSmrg    struct servent	*servp;
144373143b9aSmrg    unsigned long 	tmpaddr;
144473143b9aSmrg#ifdef X11_t
144573143b9aSmrg    char	portbuf[PORTBUFSIZE];
144673143b9aSmrg#endif
144773143b9aSmrg
144873143b9aSmrg    long		tmpport;
144973143b9aSmrg    char 		hostnamebuf[256];		/* tmp space */
145073143b9aSmrg
145173143b9aSmrg    PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
145273143b9aSmrg
145373143b9aSmrg    if (!host)
145473143b9aSmrg    {
145573143b9aSmrg	hostnamebuf[0] = '\0';
145673143b9aSmrg	(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
145773143b9aSmrg	host = hostnamebuf;
145873143b9aSmrg    }
145973143b9aSmrg
146073143b9aSmrg#ifdef X11_t
146173143b9aSmrg    /*
146273143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
146373143b9aSmrg     * to handle it here, than try and come up with a transport independent
146473143b9aSmrg     * representation that can be passed in and resolved the usual way.
146573143b9aSmrg     *
146673143b9aSmrg     * The port that is passed here is really a string containing the idisplay
146773143b9aSmrg     * from ConnectDisplay().
146873143b9aSmrg     */
146973143b9aSmrg
147073143b9aSmrg    if (is_numeric (port))
147173143b9aSmrg    {
147273143b9aSmrg	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
147373143b9aSmrg	sprintf (portbuf, "%lu", tmpport);
147473143b9aSmrg	port = portbuf;
147573143b9aSmrg    }
147673143b9aSmrg#endif
147773143b9aSmrg
147873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
147973143b9aSmrg    if (haveIPv6) {
148073143b9aSmrg	if (addrlist != NULL) {
148173143b9aSmrg	    if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
148273143b9aSmrg		if (addrlist->firstaddr)
148373143b9aSmrg		    freeaddrinfo(addrlist->firstaddr);
148473143b9aSmrg		addrlist->firstaddr = NULL;
148573143b9aSmrg	    }
148673143b9aSmrg	} else {
148773143b9aSmrg	    addrlist = malloc(sizeof(struct addrlist));
148873143b9aSmrg	    addrlist->firstaddr = NULL;
148973143b9aSmrg	}
149073143b9aSmrg
149173143b9aSmrg	if (addrlist->firstaddr == NULL) {
149273143b9aSmrg	    strncpy(addrlist->port, port, sizeof(addrlist->port));
149373143b9aSmrg	    addrlist->port[sizeof(addrlist->port) - 1] = '\0';
149473143b9aSmrg	    strncpy(addrlist->host, host, sizeof(addrlist->host));
149573143b9aSmrg	    addrlist->host[sizeof(addrlist->host) - 1] = '\0';
149673143b9aSmrg
149773143b9aSmrg	    bzero(&hints,sizeof(hints));
149873143b9aSmrg	    hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
149973143b9aSmrg
150073143b9aSmrg	    res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
150173143b9aSmrg	    if (res != 0) {
150273143b9aSmrg		PRMSG (1, "SocketINETConnect() can't get address "
150373143b9aSmrg			"for %s:%s: %s\n", host, port, gai_strerror(res));
150473143b9aSmrg		ESET(EINVAL);
150573143b9aSmrg		return TRANS_CONNECT_FAILED;
150673143b9aSmrg	    }
150773143b9aSmrg	    for (res = 0, addrlist->addr = addrlist->firstaddr;
150873143b9aSmrg		 addrlist->addr ; res++) {
150973143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
151073143b9aSmrg	    }
151173143b9aSmrg	    PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
151273143b9aSmrg	    res = 0;
151373143b9aSmrg	    addrlist->addr = NULL;
151473143b9aSmrg	}
151573143b9aSmrg
151673143b9aSmrg	while (socketaddr == NULL) {
151773143b9aSmrg	    if (addrlist->addr == NULL) {
151873143b9aSmrg		if (resetonce) {
151973143b9aSmrg		    /* Already checked entire list - no usable addresses */
152073143b9aSmrg		    PRMSG (1, "SocketINETConnect() no usable address "
152173143b9aSmrg			   "for %s:%s\n", host, port, 0);
152273143b9aSmrg		    return TRANS_CONNECT_FAILED;
152373143b9aSmrg		} else {
152473143b9aSmrg		    /* Go back to beginning of list */
152573143b9aSmrg		    resetonce = 1;
152673143b9aSmrg		    addrlist->addr = addrlist->firstaddr;
152773143b9aSmrg		}
152873143b9aSmrg	    }
152973143b9aSmrg
153073143b9aSmrg	    socketaddr = addrlist->addr->ai_addr;
153173143b9aSmrg	    socketaddrlen = addrlist->addr->ai_addrlen;
153273143b9aSmrg
153373143b9aSmrg	    if (addrlist->addr->ai_family == AF_INET) {
153473143b9aSmrg		struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
153573143b9aSmrg
153673143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
153773143b9aSmrg			inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
153873143b9aSmrg			ntopbuf,sizeof(ntopbuf)), 0, 0);
153973143b9aSmrg
154073143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
154173143b9aSmrg			ntohs(sin->sin_port), 0, 0);
154273143b9aSmrg
154373143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
154473143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
154573143b9aSmrg				"tcp") == 0) {
154673143b9aSmrg			XtransConnInfo newciptr;
154773143b9aSmrg
154873143b9aSmrg			/*
154973143b9aSmrg			 * Our socket is an IPv6 socket, but the address is
155073143b9aSmrg			 * IPv4.  Close it and get an IPv4 socket.  This is
155173143b9aSmrg			 * needed for IPv4 connections to work on platforms
155273143b9aSmrg			 * that don't allow IPv4 over IPv6 sockets.
155373143b9aSmrg			 */
155473143b9aSmrg			TRANS(SocketINETClose)(ciptr);
155573143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
155673143b9aSmrg					"tcp", "tcp", host, port, ciptr->index);
155773143b9aSmrg			if (newciptr)
155873143b9aSmrg			    ciptr->fd = newciptr->fd;
155973143b9aSmrg			if (!newciptr ||
156073143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
156173143b9aSmrg				AF_INET) {
156273143b9aSmrg			    socketaddr = NULL;
156373143b9aSmrg			    PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
156473143b9aSmrg					" socketfor IPv4 address\n", 0,0,0);
156573143b9aSmrg			}
156673143b9aSmrg			if (newciptr)
156773143b9aSmrg			    xfree(newciptr);
156873143b9aSmrg		    } else {
156973143b9aSmrg			socketaddr = NULL;
157073143b9aSmrg			PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
157173143b9aSmrg				0,0,0);
157273143b9aSmrg		    }
157373143b9aSmrg		}
157473143b9aSmrg	    } else if (addrlist->addr->ai_family == AF_INET6) {
157573143b9aSmrg		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
157673143b9aSmrg
157773143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
157873143b9aSmrg			inet_ntop(addrlist->addr->ai_family,
157973143b9aSmrg				  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
158073143b9aSmrg			0, 0);
158173143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
158273143b9aSmrg			ntohs(sin6->sin6_port), 0, 0);
158373143b9aSmrg
158473143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
158573143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
158673143b9aSmrg				"tcp") == 0) {
158773143b9aSmrg			XtransConnInfo newciptr;
158873143b9aSmrg
158973143b9aSmrg			/*
159073143b9aSmrg			 * Close the IPv4 socket and try to open an IPv6 socket.
159173143b9aSmrg			 */
159273143b9aSmrg			TRANS(SocketINETClose)(ciptr);
159373143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
159473143b9aSmrg					"tcp", "tcp", host, port, -1);
159573143b9aSmrg			if (newciptr)
159673143b9aSmrg			    ciptr->fd = newciptr->fd;
159773143b9aSmrg			if (!newciptr ||
159873143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
159973143b9aSmrg					AF_INET6) {
160073143b9aSmrg			    socketaddr = NULL;
160173143b9aSmrg			    PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
160273143b9aSmrg				   "socket for IPv6 address\n", 0,0,0);
160373143b9aSmrg			}
160473143b9aSmrg			if (newciptr)
160573143b9aSmrg			    xfree(newciptr);
160673143b9aSmrg		    }
160773143b9aSmrg		    else
160873143b9aSmrg		    {
160973143b9aSmrg			socketaddr = NULL;
161073143b9aSmrg			PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
161173143b9aSmrg				0,0,0);
161273143b9aSmrg		    }
161373143b9aSmrg		}
161473143b9aSmrg	    } else {
161573143b9aSmrg		socketaddr = NULL; /* Unsupported address type */
161673143b9aSmrg	    }
161773143b9aSmrg	    if (socketaddr == NULL) {
161873143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
161973143b9aSmrg	    }
162073143b9aSmrg	}
162173143b9aSmrg    } else
162273143b9aSmrg#endif
162373143b9aSmrg    {
162473143b9aSmrg	/*
162573143b9aSmrg	 * Build the socket name.
162673143b9aSmrg	 */
162773143b9aSmrg
162873143b9aSmrg#ifdef BSD44SOCKETS
162973143b9aSmrg	sockname.sin_len = sizeof (struct sockaddr_in);
163073143b9aSmrg#endif
163173143b9aSmrg	sockname.sin_family = AF_INET;
163273143b9aSmrg
163373143b9aSmrg	/*
163473143b9aSmrg	 * fill in sin_addr
163573143b9aSmrg	 */
163673143b9aSmrg
163773143b9aSmrg#ifndef INADDR_NONE
163873143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff)
163973143b9aSmrg#endif
164073143b9aSmrg
164173143b9aSmrg	/* check for ww.xx.yy.zz host string */
164273143b9aSmrg
164373143b9aSmrg	if (isascii (host[0]) && isdigit (host[0])) {
164473143b9aSmrg	    tmpaddr = inet_addr (host); /* returns network byte order */
164573143b9aSmrg	} else {
164673143b9aSmrg	    tmpaddr = INADDR_NONE;
164773143b9aSmrg	}
164873143b9aSmrg
164973143b9aSmrg	PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
165073143b9aSmrg
165173143b9aSmrg	if (tmpaddr == INADDR_NONE) {
165273143b9aSmrg	    if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
165373143b9aSmrg		PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
165473143b9aSmrg			host, 0, 0);
165573143b9aSmrg		ESET(EINVAL);
165673143b9aSmrg		return TRANS_CONNECT_FAILED;
165773143b9aSmrg	    }
165873143b9aSmrg	    if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
165973143b9aSmrg		PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
166073143b9aSmrg		ESET(EPROTOTYPE);
166173143b9aSmrg		return TRANS_CONNECT_FAILED;
166273143b9aSmrg	    }
166373143b9aSmrg
166473143b9aSmrg	    memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
166573143b9aSmrg		    sizeof (sockname.sin_addr));
166673143b9aSmrg
166773143b9aSmrg	} else {
166873143b9aSmrg	    sockname.sin_addr.s_addr = tmpaddr;
166973143b9aSmrg        }
167073143b9aSmrg
167173143b9aSmrg	/*
167273143b9aSmrg	 * fill in sin_port
167373143b9aSmrg	 */
167473143b9aSmrg
167573143b9aSmrg	/* Check for number in the port string */
167673143b9aSmrg
167773143b9aSmrg	if (!is_numeric (port)) {
167873143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
167973143b9aSmrg		PRMSG (1,"SocketINETConnect: can't get service for %s\n",
168073143b9aSmrg			port, 0, 0);
168173143b9aSmrg		return TRANS_CONNECT_FAILED;
168273143b9aSmrg	    }
168373143b9aSmrg	    sockname.sin_port = htons (servp->s_port);
168473143b9aSmrg	} else {
168573143b9aSmrg	    tmpport = strtol (port, (char**)NULL, 10);
168673143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
168773143b9aSmrg		return TRANS_CONNECT_FAILED;
168873143b9aSmrg	    sockname.sin_port = htons (((unsigned short) tmpport));
168973143b9aSmrg	}
169073143b9aSmrg
169173143b9aSmrg	PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
169273143b9aSmrg		ntohs(sockname.sin_port), 0, 0);
169373143b9aSmrg	socketaddr = (struct sockaddr *) &sockname;
169473143b9aSmrg	socketaddrlen = sizeof(sockname);
169573143b9aSmrg    }
169673143b9aSmrg
169773143b9aSmrg    /*
169873143b9aSmrg     * Turn on socket keepalive so the client process will eventually
169973143b9aSmrg     * be notified with a SIGPIPE signal if the display server fails
170073143b9aSmrg     * to respond to a periodic transmission of messages
170173143b9aSmrg     * on the connected socket.
170273143b9aSmrg     * This is useful to avoid hung application processes when the
170373143b9aSmrg     * processes are not spawned from the xdm session and
170473143b9aSmrg     * the display server terminates abnormally.
170573143b9aSmrg     * (Someone turned off the power switch.)
170673143b9aSmrg     */
170773143b9aSmrg
170873143b9aSmrg    {
170973143b9aSmrg	int tmp = 1;
171073143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
171173143b9aSmrg		(char *) &tmp, sizeof (int));
171273143b9aSmrg    }
171373143b9aSmrg
171473143b9aSmrg    /*
171573143b9aSmrg     * Do the connect()
171673143b9aSmrg     */
171773143b9aSmrg
171873143b9aSmrg    if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
171973143b9aSmrg    {
172073143b9aSmrg#ifdef WIN32
172173143b9aSmrg	int olderrno = WSAGetLastError();
172273143b9aSmrg#else
172373143b9aSmrg	int olderrno = errno;
172473143b9aSmrg#endif
172573143b9aSmrg
172673143b9aSmrg	/*
172773143b9aSmrg	 * If the error was ECONNREFUSED, the server may be overloaded
172873143b9aSmrg	 * and we should try again.
172973143b9aSmrg	 *
173073143b9aSmrg	 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
173173143b9aSmrg	 * was non-blocking and we should poll using select
173273143b9aSmrg	 *
173373143b9aSmrg	 * If the error was EINTR, the connect was interrupted and we
173473143b9aSmrg	 * should try again.
173573143b9aSmrg	 *
173673143b9aSmrg	 * If multiple addresses are found for a host then we should
173773143b9aSmrg	 * try to connect again with a different address for a larger
173873143b9aSmrg	 * number of errors that made us quit before, since those
173973143b9aSmrg	 * could be caused by trying to use an IPv6 address to contact
174073143b9aSmrg	 * a machine with an IPv4-only server or other reasons that
174173143b9aSmrg	 * only affect one of a set of addresses.
174273143b9aSmrg	 */
174373143b9aSmrg
174473143b9aSmrg	if (olderrno == ECONNREFUSED || olderrno == EINTR
174573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
174673143b9aSmrg	  || (haveIPv6 && ((addrlist->addr->ai_next != NULL) ||
174773143b9aSmrg	        (addrlist->addr != addrlist->firstaddr)) &&
174873143b9aSmrg               (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
174973143b9aSmrg		 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
175073143b9aSmrg#if defined(EHOSTDOWN)
175173143b9aSmrg		   || olderrno == EHOSTDOWN
175273143b9aSmrg#endif
175373143b9aSmrg	       ))
175473143b9aSmrg#endif
175573143b9aSmrg	    )
175673143b9aSmrg	    res = TRANS_TRY_CONNECT_AGAIN;
175773143b9aSmrg	else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
175873143b9aSmrg	    res = TRANS_IN_PROGRESS;
175973143b9aSmrg	else
176073143b9aSmrg	{
176173143b9aSmrg	    PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
176273143b9aSmrg		   olderrno,0, 0);
176373143b9aSmrg
176473143b9aSmrg	    res = TRANS_CONNECT_FAILED;
176573143b9aSmrg	}
176673143b9aSmrg    } else {
176773143b9aSmrg	res = 0;
176873143b9aSmrg
176973143b9aSmrg
177073143b9aSmrg	/*
177173143b9aSmrg	 * Sync up the address fields of ciptr.
177273143b9aSmrg	 */
177373143b9aSmrg
177473143b9aSmrg	if (TRANS(SocketINETGetAddr) (ciptr) < 0)
177573143b9aSmrg	{
177673143b9aSmrg	    PRMSG (1,
177773143b9aSmrg	     "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
177873143b9aSmrg	      0, 0, 0);
177973143b9aSmrg	    res = TRANS_CONNECT_FAILED;
178073143b9aSmrg	}
178173143b9aSmrg
178273143b9aSmrg	else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
178373143b9aSmrg	{
178473143b9aSmrg	    PRMSG (1,
178573143b9aSmrg	      "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
178673143b9aSmrg	      0, 0, 0);
178773143b9aSmrg	    res = TRANS_CONNECT_FAILED;
178873143b9aSmrg	}
178973143b9aSmrg    }
179073143b9aSmrg
179173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
179273143b9aSmrg   if (haveIPv6 && res != 0) {
179373143b9aSmrg	addrlist->addr = addrlist->addr->ai_next;
179473143b9aSmrg   }
179573143b9aSmrg#endif
179673143b9aSmrg
179773143b9aSmrg    return res;
179873143b9aSmrg}
179973143b9aSmrg
180073143b9aSmrg#endif /* TCPCONN */
180173143b9aSmrg
180273143b9aSmrg
180373143b9aSmrg
180473143b9aSmrg#ifdef UNIXCONN
180573143b9aSmrg
180673143b9aSmrg/*
180773143b9aSmrg * Make sure 'host' is really local.
180873143b9aSmrg */
180973143b9aSmrg
181073143b9aSmrgstatic int
181173143b9aSmrgUnixHostReallyLocal (char *host)
181273143b9aSmrg
181373143b9aSmrg{
181473143b9aSmrg    char hostnamebuf[256];
181573143b9aSmrg
181673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
181773143b9aSmrg    if (getaddrinfo == NULL)
181873143b9aSmrg	haveIPv6 = 0;
181973143b9aSmrg#endif
182073143b9aSmrg
182173143b9aSmrg    TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
182273143b9aSmrg
182373143b9aSmrg    if (strcmp (hostnamebuf, host) == 0)
182473143b9aSmrg    {
182573143b9aSmrg	return (1);
182673143b9aSmrg    }
182773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
182873143b9aSmrg    else if (haveIPv6)
182973143b9aSmrg    {
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) {
184673143b9aSmrg			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) {
185773143b9aSmrg			struct sockaddr_in6 *sinA
185873143b9aSmrg			  = (struct sockaddr_in6 *) i->ai_addr;
185973143b9aSmrg			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	}
187173143b9aSmrg
187273143b9aSmrg	freeaddrinfo(localhostaddr);
187373143b9aSmrg	freeaddrinfo(otherhostaddr);
187473143b9aSmrg	return equiv;
187573143b9aSmrg    }
187673143b9aSmrg#endif
187773143b9aSmrg    else
187873143b9aSmrg    {
187973143b9aSmrg	/*
188073143b9aSmrg	 * A host may have more than one network address.  If any of the
188173143b9aSmrg	 * network addresses of 'host' (specified to the connect call)
188273143b9aSmrg	 * match any of the network addresses of 'hostname' (determined
188373143b9aSmrg	 * by TRANS(GetHostname)), then the two hostnames are equivalent,
188473143b9aSmrg	 * and we know that 'host' is really a local host.
188573143b9aSmrg	 */
188673143b9aSmrg	char specified_local_addr_list[10][4];
188773143b9aSmrg	int scount, equiv, i, j;
188873143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
188973143b9aSmrg	_Xgethostbynameparams hparams;
189073143b9aSmrg#endif
189173143b9aSmrg	struct hostent *hostp;
189273143b9aSmrg
189373143b9aSmrg	if ((hostp = _XGethostbyname (host,hparams)) == NULL)
189473143b9aSmrg	    return (0);
189573143b9aSmrg
189673143b9aSmrg	scount = 0;
189773143b9aSmrg	while (hostp->h_addr_list[scount] && scount <= 8)
189873143b9aSmrg	{
189973143b9aSmrg	    /*
190073143b9aSmrg	     * The 2nd call to gethostname() overrides the data
190173143b9aSmrg	     * from the 1st call, so we must save the address list.
190273143b9aSmrg	     */
190373143b9aSmrg
190473143b9aSmrg	    specified_local_addr_list[scount][0] =
190573143b9aSmrg				hostp->h_addr_list[scount][0];
190673143b9aSmrg	    specified_local_addr_list[scount][1] =
190773143b9aSmrg				hostp->h_addr_list[scount][1];
190873143b9aSmrg	    specified_local_addr_list[scount][2] =
190973143b9aSmrg				hostp->h_addr_list[scount][2];
191073143b9aSmrg	    specified_local_addr_list[scount][3] =
191173143b9aSmrg				hostp->h_addr_list[scount][3];
191273143b9aSmrg	    scount++;
191373143b9aSmrg	}
191473143b9aSmrg	if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
191573143b9aSmrg	    return (0);
191673143b9aSmrg
191773143b9aSmrg	equiv = 0;
191873143b9aSmrg	i = 0;
191973143b9aSmrg
192073143b9aSmrg	while (i < scount && !equiv)
192173143b9aSmrg	{
192273143b9aSmrg	    j = 0;
192373143b9aSmrg
192473143b9aSmrg	    while (hostp->h_addr_list[j])
192573143b9aSmrg	    {
192673143b9aSmrg		if ((specified_local_addr_list[i][0] ==
192773143b9aSmrg					hostp->h_addr_list[j][0]) &&
192873143b9aSmrg		    (specified_local_addr_list[i][1] ==
192973143b9aSmrg					hostp->h_addr_list[j][1]) &&
193073143b9aSmrg		    (specified_local_addr_list[i][2] ==
193173143b9aSmrg					hostp->h_addr_list[j][2]) &&
193273143b9aSmrg		    (specified_local_addr_list[i][3] ==
193373143b9aSmrg					hostp->h_addr_list[j][3]))
193473143b9aSmrg		{
193573143b9aSmrg		    /* They're equal, so we're done */
193673143b9aSmrg
193773143b9aSmrg		    equiv = 1;
193873143b9aSmrg		    break;
193973143b9aSmrg		}
194073143b9aSmrg
194173143b9aSmrg		j++;
194273143b9aSmrg	    }
194373143b9aSmrg
194473143b9aSmrg	    i++;
194573143b9aSmrg	}
194673143b9aSmrg	return (equiv);
194773143b9aSmrg    }
194873143b9aSmrg}
194973143b9aSmrg
195073143b9aSmrgstatic int
195173143b9aSmrgTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
195273143b9aSmrg
195373143b9aSmrg{
195473143b9aSmrg    struct sockaddr_un	sockname;
195573143b9aSmrg    SOCKLEN_T		namelen;
195673143b9aSmrg
195773143b9aSmrg
195873143b9aSmrg    int abstract = 0;
195973143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
196073143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
196173143b9aSmrg#endif
196273143b9aSmrg
196373143b9aSmrg    PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
196473143b9aSmrg
196573143b9aSmrg    /*
196673143b9aSmrg     * Make sure 'host' is really local.  If not, we return failure.
196773143b9aSmrg     * The reason we make this check is because a process may advertise
196873143b9aSmrg     * a "local" network ID for which it can accept connections, but if
196973143b9aSmrg     * a process on a remote machine tries to connect to this network ID,
197073143b9aSmrg     * we know for sure it will fail.
197173143b9aSmrg     */
197273143b9aSmrg
197373143b9aSmrg    if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
197473143b9aSmrg    {
197573143b9aSmrg	PRMSG (1,
197673143b9aSmrg	   "SocketUNIXConnect: Cannot connect to non-local host %s\n",
197773143b9aSmrg	       host, 0, 0);
197873143b9aSmrg	return TRANS_CONNECT_FAILED;
197973143b9aSmrg    }
198073143b9aSmrg
198173143b9aSmrg
198273143b9aSmrg    /*
198373143b9aSmrg     * Check the port.
198473143b9aSmrg     */
198573143b9aSmrg
198673143b9aSmrg    if (!port || !*port)
198773143b9aSmrg    {
198873143b9aSmrg	PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
198973143b9aSmrg	      0, 0, 0);
199073143b9aSmrg	return TRANS_CONNECT_FAILED;
199173143b9aSmrg    }
199273143b9aSmrg
199373143b9aSmrg    /*
199473143b9aSmrg     * Build the socket name.
199573143b9aSmrg     */
199673143b9aSmrg
199773143b9aSmrg    sockname.sun_family = AF_UNIX;
199873143b9aSmrg
199973143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
200073143b9aSmrg	PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
200173143b9aSmrg	return TRANS_CONNECT_FAILED;
200273143b9aSmrg    }
200373143b9aSmrg
20048d4c0f7bSmrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
200573143b9aSmrg    sockname.sun_len = strlen (sockname.sun_path);
200673143b9aSmrg#endif
200773143b9aSmrg
200873143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
200973143b9aSmrg    namelen = SUN_LEN (&sockname);
201073143b9aSmrg#else
201173143b9aSmrg    namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
201273143b9aSmrg#endif
201373143b9aSmrg
201473143b9aSmrg
201573143b9aSmrg
201673143b9aSmrg    /*
201773143b9aSmrg     * Adjust the socket path if using abstract sockets.
201873143b9aSmrg     * Done here because otherwise all the strlen() calls above would fail.
201973143b9aSmrg     */
202073143b9aSmrg
202173143b9aSmrg    if (abstract) {
202273143b9aSmrg	sockname.sun_path[0] = '\0';
202373143b9aSmrg    }
202473143b9aSmrg
202573143b9aSmrg    /*
202673143b9aSmrg     * Do the connect()
202773143b9aSmrg     */
202873143b9aSmrg
202973143b9aSmrg    if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
203073143b9aSmrg    {
203173143b9aSmrg	int olderrno = errno;
203273143b9aSmrg	int connected = 0;
203373143b9aSmrg
203473143b9aSmrg	if (!connected)
203573143b9aSmrg	{
203673143b9aSmrg	    errno = olderrno;
203773143b9aSmrg
203873143b9aSmrg	    /*
203973143b9aSmrg	     * If the error was ENOENT, the server may be starting up; we used
204073143b9aSmrg	     * to suggest to try again in this case with
204173143b9aSmrg	     * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
204273143b9aSmrg	     * processes still referencing stale sockets in their environment.
204373143b9aSmrg	     * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
204473143b9aSmrg	     * is suggested that higher level stacks handle retries on their
204573143b9aSmrg	     * level when they face a slow starting server.
204673143b9aSmrg	     *
204773143b9aSmrg	     * If the error was EWOULDBLOCK or EINPROGRESS then the socket
204873143b9aSmrg	     * was non-blocking and we should poll using select
204973143b9aSmrg	     *
205073143b9aSmrg	     * If the error was EINTR, the connect was interrupted and we
205173143b9aSmrg	     * should try again.
205273143b9aSmrg	     */
205373143b9aSmrg
205473143b9aSmrg	    if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
205573143b9aSmrg		return TRANS_IN_PROGRESS;
205673143b9aSmrg	    else if (olderrno == EINTR)
205773143b9aSmrg		return TRANS_TRY_CONNECT_AGAIN;
20588d4c0f7bSmrg	    else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
205973143b9aSmrg		/* If opening as abstract socket failed, try again normally */
206073143b9aSmrg		if (abstract) {
206173143b9aSmrg		    ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
206273143b9aSmrg		    return TRANS_TRY_CONNECT_AGAIN;
206373143b9aSmrg		} else {
206473143b9aSmrg		    return TRANS_CONNECT_FAILED;
206573143b9aSmrg		}
206673143b9aSmrg	    } else {
206773143b9aSmrg		PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
206873143b9aSmrg		       EGET(),0, 0);
206973143b9aSmrg
207073143b9aSmrg		return TRANS_CONNECT_FAILED;
207173143b9aSmrg	    }
207273143b9aSmrg	}
207373143b9aSmrg    }
207473143b9aSmrg
207573143b9aSmrg    /*
207673143b9aSmrg     * Get the socket name and the peer name from the connect socket,
207773143b9aSmrg     * since this is unix domain.
207873143b9aSmrg     */
207973143b9aSmrg
208073143b9aSmrg    if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
208173143b9aSmrg       (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
208273143b9aSmrg    {
208373143b9aSmrg        PRMSG (1,
208473143b9aSmrg	"SocketUNIXCreateListener: Can't allocate space for the addr\n",
208573143b9aSmrg	      0, 0, 0);
208673143b9aSmrg        return TRANS_CONNECT_FAILED;
208773143b9aSmrg    }
208873143b9aSmrg
208973143b9aSmrg    if (abstract)
209073143b9aSmrg	sockname.sun_path[0] = '@';
209173143b9aSmrg
209273143b9aSmrg    ciptr->family = AF_UNIX;
209373143b9aSmrg    ciptr->addrlen = namelen;
209473143b9aSmrg    ciptr->peeraddrlen = namelen;
209573143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
209673143b9aSmrg    memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
209773143b9aSmrg
209873143b9aSmrg    return 0;
209973143b9aSmrg}
210073143b9aSmrg
210173143b9aSmrg#endif /* UNIXCONN */
210273143b9aSmrg
210373143b9aSmrg#endif /* TRANS_CLIENT */
210473143b9aSmrg
210573143b9aSmrg
210673143b9aSmrgstatic int
210773143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
210873143b9aSmrg
210973143b9aSmrg{
211073143b9aSmrg    PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
211173143b9aSmrg	ciptr, ciptr->fd, pend);
211273143b9aSmrg#ifdef WIN32
211373143b9aSmrg    {
211473143b9aSmrg	int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
211573143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
211673143b9aSmrg	return ret;
211773143b9aSmrg    }
211873143b9aSmrg#else
21198d4c0f7bSmrg#if defined(__i386__) && defined(SYSV) && !defined(SCO325)
212073143b9aSmrg    return ioctl (ciptr->fd, I_NREAD, (char *) pend);
212173143b9aSmrg#else
212273143b9aSmrg    return ioctl (ciptr->fd, FIONREAD, (char *) pend);
212373143b9aSmrg#endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
212473143b9aSmrg#endif /* WIN32 */
212573143b9aSmrg}
212673143b9aSmrg
212773143b9aSmrg
212873143b9aSmrgstatic int
212973143b9aSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
213073143b9aSmrg
213173143b9aSmrg{
213273143b9aSmrg    PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
213373143b9aSmrg
21348d4c0f7bSmrg#if defined(WIN32)
213573143b9aSmrg    {
213673143b9aSmrg	int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
213773143b9aSmrg#ifdef WIN32
213873143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
213973143b9aSmrg#endif
214073143b9aSmrg	return ret;
214173143b9aSmrg    }
214273143b9aSmrg#else
214373143b9aSmrg    return read (ciptr->fd, buf, size);
214473143b9aSmrg#endif /* WIN32 */
214573143b9aSmrg}
214673143b9aSmrg
214773143b9aSmrg
214873143b9aSmrgstatic int
214973143b9aSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
215073143b9aSmrg
215173143b9aSmrg{
215273143b9aSmrg    PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
215373143b9aSmrg
21548d4c0f7bSmrg#if defined(WIN32)
215573143b9aSmrg    {
215673143b9aSmrg	int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
215773143b9aSmrg#ifdef WIN32
215873143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
215973143b9aSmrg#endif
216073143b9aSmrg	return ret;
216173143b9aSmrg    }
216273143b9aSmrg#else
216373143b9aSmrg    return write (ciptr->fd, buf, size);
216473143b9aSmrg#endif /* WIN32 */
216573143b9aSmrg}
216673143b9aSmrg
216773143b9aSmrg
216873143b9aSmrgstatic int
216973143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
217073143b9aSmrg
217173143b9aSmrg{
217273143b9aSmrg    PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
217373143b9aSmrg
217473143b9aSmrg    return READV (ciptr, buf, size);
217573143b9aSmrg}
217673143b9aSmrg
217773143b9aSmrg
217873143b9aSmrgstatic int
217973143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
218073143b9aSmrg
218173143b9aSmrg{
218273143b9aSmrg    PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
218373143b9aSmrg
218473143b9aSmrg    return WRITEV (ciptr, buf, size);
218573143b9aSmrg}
218673143b9aSmrg
218773143b9aSmrg
218873143b9aSmrgstatic int
218973143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr)
219073143b9aSmrg
219173143b9aSmrg{
219273143b9aSmrg    PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
219373143b9aSmrg
219473143b9aSmrg#ifdef WIN32
219573143b9aSmrg    {
219673143b9aSmrg	int ret = shutdown (ciptr->fd, 2);
219773143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
219873143b9aSmrg	return ret;
219973143b9aSmrg    }
220073143b9aSmrg#else
220173143b9aSmrg    return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
220273143b9aSmrg#endif
220373143b9aSmrg}
220473143b9aSmrg
220573143b9aSmrg
220673143b9aSmrg#ifdef TCPCONN
220773143b9aSmrgstatic int
220873143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr)
220973143b9aSmrg
221073143b9aSmrg{
221173143b9aSmrg    PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
221273143b9aSmrg
221373143b9aSmrg#ifdef WIN32
221473143b9aSmrg    {
221573143b9aSmrg	int ret = close (ciptr->fd);
221673143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
221773143b9aSmrg	return ret;
221873143b9aSmrg    }
221973143b9aSmrg#else
222073143b9aSmrg    return close (ciptr->fd);
222173143b9aSmrg#endif
222273143b9aSmrg}
222373143b9aSmrg
222473143b9aSmrg#endif /* TCPCONN */
222573143b9aSmrg
222673143b9aSmrg
222773143b9aSmrg#ifdef UNIXCONN
222873143b9aSmrgstatic int
222973143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr)
223073143b9aSmrg{
223173143b9aSmrg    /*
223273143b9aSmrg     * If this is the server side, then once the socket is closed,
223373143b9aSmrg     * it must be unlinked to completely close it
223473143b9aSmrg     */
223573143b9aSmrg
223673143b9aSmrg    struct sockaddr_un	*sockname = (struct sockaddr_un *) ciptr->addr;
223773143b9aSmrg    int ret;
223873143b9aSmrg
223973143b9aSmrg    PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
224073143b9aSmrg
224173143b9aSmrg    ret = close(ciptr->fd);
224273143b9aSmrg
224373143b9aSmrg    if (ciptr->flags
224473143b9aSmrg       && sockname
224573143b9aSmrg       && sockname->sun_family == AF_UNIX
224673143b9aSmrg       && sockname->sun_path[0])
224773143b9aSmrg    {
224873143b9aSmrg	if (!(ciptr->flags & TRANS_NOUNLINK
224973143b9aSmrg	    || ciptr->transptr->flags & TRANS_ABSTRACT))
225073143b9aSmrg		unlink (sockname->sun_path);
225173143b9aSmrg    }
225273143b9aSmrg
225373143b9aSmrg    return ret;
225473143b9aSmrg}
225573143b9aSmrg
225673143b9aSmrgstatic int
225773143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
225873143b9aSmrg
225973143b9aSmrg{
226073143b9aSmrg    /*
226173143b9aSmrg     * Don't unlink path.
226273143b9aSmrg     */
226373143b9aSmrg
226473143b9aSmrg    int ret;
226573143b9aSmrg
226673143b9aSmrg    PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
226773143b9aSmrg	ciptr, ciptr->fd, 0);
226873143b9aSmrg
226973143b9aSmrg    ret = close(ciptr->fd);
227073143b9aSmrg
227173143b9aSmrg    return ret;
227273143b9aSmrg}
227373143b9aSmrg
227473143b9aSmrg#endif /* UNIXCONN */
227573143b9aSmrg
227673143b9aSmrg
227773143b9aSmrg#ifdef TCPCONN
227873143b9aSmrg# ifdef TRANS_SERVER
227973143b9aSmrgstatic char* tcp_nolisten[] = {
228073143b9aSmrg	"inet",
228173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
228273143b9aSmrg	"inet6",
228373143b9aSmrg#endif
228473143b9aSmrg	NULL
228573143b9aSmrg};
228673143b9aSmrg# endif
228773143b9aSmrg
228873143b9aSmrgXtransport	TRANS(SocketTCPFuncs) = {
228973143b9aSmrg	/* Socket Interface */
229073143b9aSmrg	"tcp",
229173143b9aSmrg        TRANS_ALIAS,
229273143b9aSmrg#ifdef TRANS_CLIENT
229373143b9aSmrg	TRANS(SocketOpenCOTSClient),
229473143b9aSmrg#endif /* TRANS_CLIENT */
229573143b9aSmrg#ifdef TRANS_SERVER
229673143b9aSmrg	tcp_nolisten,
229773143b9aSmrg	TRANS(SocketOpenCOTSServer),
229873143b9aSmrg#endif /* TRANS_SERVER */
229973143b9aSmrg#ifdef TRANS_CLIENT
230073143b9aSmrg	TRANS(SocketOpenCLTSClient),
230173143b9aSmrg#endif /* TRANS_CLIENT */
230273143b9aSmrg#ifdef TRANS_SERVER
230373143b9aSmrg	TRANS(SocketOpenCLTSServer),
230473143b9aSmrg#endif /* TRANS_SERVER */
230573143b9aSmrg#ifdef TRANS_REOPEN
230673143b9aSmrg	TRANS(SocketReopenCOTSServer),
230773143b9aSmrg	TRANS(SocketReopenCLTSServer),
230873143b9aSmrg#endif
230973143b9aSmrg	TRANS(SocketSetOption),
231073143b9aSmrg#ifdef TRANS_SERVER
231173143b9aSmrg	TRANS(SocketINETCreateListener),
231273143b9aSmrg	NULL,		       			/* ResetListener */
231373143b9aSmrg	TRANS(SocketINETAccept),
231473143b9aSmrg#endif /* TRANS_SERVER */
231573143b9aSmrg#ifdef TRANS_CLIENT
231673143b9aSmrg	TRANS(SocketINETConnect),
231773143b9aSmrg#endif /* TRANS_CLIENT */
231873143b9aSmrg	TRANS(SocketBytesReadable),
231973143b9aSmrg	TRANS(SocketRead),
232073143b9aSmrg	TRANS(SocketWrite),
232173143b9aSmrg	TRANS(SocketReadv),
232273143b9aSmrg	TRANS(SocketWritev),
232373143b9aSmrg	TRANS(SocketDisconnect),
232473143b9aSmrg	TRANS(SocketINETClose),
232573143b9aSmrg	TRANS(SocketINETClose),
232673143b9aSmrg	};
232773143b9aSmrg
232873143b9aSmrgXtransport	TRANS(SocketINETFuncs) = {
232973143b9aSmrg	/* Socket Interface */
233073143b9aSmrg	"inet",
233173143b9aSmrg	0,
233273143b9aSmrg#ifdef TRANS_CLIENT
233373143b9aSmrg	TRANS(SocketOpenCOTSClient),
233473143b9aSmrg#endif /* TRANS_CLIENT */
233573143b9aSmrg#ifdef TRANS_SERVER
233673143b9aSmrg	NULL,
233773143b9aSmrg	TRANS(SocketOpenCOTSServer),
233873143b9aSmrg#endif /* TRANS_SERVER */
233973143b9aSmrg#ifdef TRANS_CLIENT
234073143b9aSmrg	TRANS(SocketOpenCLTSClient),
234173143b9aSmrg#endif /* TRANS_CLIENT */
234273143b9aSmrg#ifdef TRANS_SERVER
234373143b9aSmrg	TRANS(SocketOpenCLTSServer),
234473143b9aSmrg#endif /* TRANS_SERVER */
234573143b9aSmrg#ifdef TRANS_REOPEN
234673143b9aSmrg	TRANS(SocketReopenCOTSServer),
234773143b9aSmrg	TRANS(SocketReopenCLTSServer),
234873143b9aSmrg#endif
234973143b9aSmrg	TRANS(SocketSetOption),
235073143b9aSmrg#ifdef TRANS_SERVER
235173143b9aSmrg	TRANS(SocketINETCreateListener),
235273143b9aSmrg	NULL,		       			/* ResetListener */
235373143b9aSmrg	TRANS(SocketINETAccept),
235473143b9aSmrg#endif /* TRANS_SERVER */
235573143b9aSmrg#ifdef TRANS_CLIENT
235673143b9aSmrg	TRANS(SocketINETConnect),
235773143b9aSmrg#endif /* TRANS_CLIENT */
235873143b9aSmrg	TRANS(SocketBytesReadable),
235973143b9aSmrg	TRANS(SocketRead),
236073143b9aSmrg	TRANS(SocketWrite),
236173143b9aSmrg	TRANS(SocketReadv),
236273143b9aSmrg	TRANS(SocketWritev),
236373143b9aSmrg	TRANS(SocketDisconnect),
236473143b9aSmrg	TRANS(SocketINETClose),
236573143b9aSmrg	TRANS(SocketINETClose),
236673143b9aSmrg	};
236773143b9aSmrg
236873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
236973143b9aSmrgXtransport     TRANS(SocketINET6Funcs) = {
237073143b9aSmrg	/* Socket Interface */
237173143b9aSmrg	"inet6",
237273143b9aSmrg	0,
237373143b9aSmrg#ifdef TRANS_CLIENT
237473143b9aSmrg	TRANS(SocketOpenCOTSClient),
237573143b9aSmrg#endif /* TRANS_CLIENT */
237673143b9aSmrg#ifdef TRANS_SERVER
237773143b9aSmrg	NULL,
237873143b9aSmrg	TRANS(SocketOpenCOTSServer),
237973143b9aSmrg#endif /* TRANS_SERVER */
238073143b9aSmrg#ifdef TRANS_CLIENT
238173143b9aSmrg	TRANS(SocketOpenCLTSClient),
238273143b9aSmrg#endif /* TRANS_CLIENT */
238373143b9aSmrg#ifdef TRANS_SERVER
238473143b9aSmrg	TRANS(SocketOpenCLTSServer),
238573143b9aSmrg#endif /* TRANS_SERVER */
238673143b9aSmrg#ifdef TRANS_REOPEN
238773143b9aSmrg	TRANS(SocketReopenCOTSServer),
238873143b9aSmrg	TRANS(SocketReopenCLTSServer),
238973143b9aSmrg#endif
239073143b9aSmrg	TRANS(SocketSetOption),
239173143b9aSmrg#ifdef TRANS_SERVER
239273143b9aSmrg	TRANS(SocketINETCreateListener),
239373143b9aSmrg	NULL,					/* ResetListener */
239473143b9aSmrg	TRANS(SocketINETAccept),
239573143b9aSmrg#endif /* TRANS_SERVER */
239673143b9aSmrg#ifdef TRANS_CLIENT
239773143b9aSmrg	TRANS(SocketINETConnect),
239873143b9aSmrg#endif /* TRANS_CLIENT */
239973143b9aSmrg	TRANS(SocketBytesReadable),
240073143b9aSmrg	TRANS(SocketRead),
240173143b9aSmrg	TRANS(SocketWrite),
240273143b9aSmrg	TRANS(SocketReadv),
240373143b9aSmrg	TRANS(SocketWritev),
240473143b9aSmrg	TRANS(SocketDisconnect),
240573143b9aSmrg	TRANS(SocketINETClose),
240673143b9aSmrg	TRANS(SocketINETClose),
240773143b9aSmrg	};
240873143b9aSmrg#endif /* IPv6 */
240973143b9aSmrg#endif /* TCPCONN */
241073143b9aSmrg
241173143b9aSmrg#ifdef UNIXCONN
241273143b9aSmrg#if !defined(LOCALCONN)
241373143b9aSmrgXtransport	TRANS(SocketLocalFuncs) = {
241473143b9aSmrg	/* Socket Interface */
241573143b9aSmrg	"local",
241673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
241773143b9aSmrg	TRANS_ABSTRACT,
241873143b9aSmrg#else
241973143b9aSmrg	0,
242073143b9aSmrg#endif
242173143b9aSmrg#ifdef TRANS_CLIENT
242273143b9aSmrg	TRANS(SocketOpenCOTSClient),
242373143b9aSmrg#endif /* TRANS_CLIENT */
242473143b9aSmrg#ifdef TRANS_SERVER
242573143b9aSmrg	NULL,
242673143b9aSmrg	TRANS(SocketOpenCOTSServer),
242773143b9aSmrg#endif /* TRANS_SERVER */
242873143b9aSmrg#ifdef TRANS_CLIENT
242973143b9aSmrg	TRANS(SocketOpenCLTSClient),
243073143b9aSmrg#endif /* TRANS_CLIENT */
243173143b9aSmrg#ifdef TRANS_SERVER
243273143b9aSmrg	TRANS(SocketOpenCLTSServer),
243373143b9aSmrg#endif /* TRANS_SERVER */
243473143b9aSmrg#ifdef TRANS_REOPEN
243573143b9aSmrg	TRANS(SocketReopenCOTSServer),
243673143b9aSmrg	TRANS(SocketReopenCLTSServer),
243773143b9aSmrg#endif
243873143b9aSmrg	TRANS(SocketSetOption),
243973143b9aSmrg#ifdef TRANS_SERVER
244073143b9aSmrg	TRANS(SocketUNIXCreateListener),
244173143b9aSmrg	TRANS(SocketUNIXResetListener),
244273143b9aSmrg	TRANS(SocketUNIXAccept),
244373143b9aSmrg#endif /* TRANS_SERVER */
244473143b9aSmrg#ifdef TRANS_CLIENT
244573143b9aSmrg	TRANS(SocketUNIXConnect),
244673143b9aSmrg#endif /* TRANS_CLIENT */
244773143b9aSmrg	TRANS(SocketBytesReadable),
244873143b9aSmrg	TRANS(SocketRead),
244973143b9aSmrg	TRANS(SocketWrite),
245073143b9aSmrg	TRANS(SocketReadv),
245173143b9aSmrg	TRANS(SocketWritev),
245273143b9aSmrg	TRANS(SocketDisconnect),
245373143b9aSmrg	TRANS(SocketUNIXClose),
245473143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
245573143b9aSmrg	};
245673143b9aSmrg#endif /* !LOCALCONN */
245773143b9aSmrg# ifdef TRANS_SERVER
245873143b9aSmrg#  if !defined(LOCALCONN)
245973143b9aSmrgstatic char* unix_nolisten[] = { "local" , NULL };
246073143b9aSmrg#  endif
246173143b9aSmrg# endif
246273143b9aSmrg
246373143b9aSmrgXtransport	TRANS(SocketUNIXFuncs) = {
246473143b9aSmrg	/* Socket Interface */
246573143b9aSmrg	"unix",
246673143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
246773143b9aSmrg        TRANS_ALIAS,
246873143b9aSmrg#else
246973143b9aSmrg	0,
247073143b9aSmrg#endif
247173143b9aSmrg#ifdef TRANS_CLIENT
247273143b9aSmrg	TRANS(SocketOpenCOTSClient),
247373143b9aSmrg#endif /* TRANS_CLIENT */
247473143b9aSmrg#ifdef TRANS_SERVER
247573143b9aSmrg#if !defined(LOCALCONN)
247673143b9aSmrg	unix_nolisten,
247773143b9aSmrg#else
247873143b9aSmrg	NULL,
247973143b9aSmrg#endif
248073143b9aSmrg	TRANS(SocketOpenCOTSServer),
248173143b9aSmrg#endif /* TRANS_SERVER */
248273143b9aSmrg#ifdef TRANS_CLIENT
248373143b9aSmrg	TRANS(SocketOpenCLTSClient),
248473143b9aSmrg#endif /* TRANS_CLIENT */
248573143b9aSmrg#ifdef TRANS_SERVER
248673143b9aSmrg	TRANS(SocketOpenCLTSServer),
248773143b9aSmrg#endif /* TRANS_SERVER */
248873143b9aSmrg#ifdef TRANS_REOPEN
248973143b9aSmrg	TRANS(SocketReopenCOTSServer),
249073143b9aSmrg	TRANS(SocketReopenCLTSServer),
249173143b9aSmrg#endif
249273143b9aSmrg	TRANS(SocketSetOption),
249373143b9aSmrg#ifdef TRANS_SERVER
249473143b9aSmrg	TRANS(SocketUNIXCreateListener),
249573143b9aSmrg	TRANS(SocketUNIXResetListener),
249673143b9aSmrg	TRANS(SocketUNIXAccept),
249773143b9aSmrg#endif /* TRANS_SERVER */
249873143b9aSmrg#ifdef TRANS_CLIENT
249973143b9aSmrg	TRANS(SocketUNIXConnect),
250073143b9aSmrg#endif /* TRANS_CLIENT */
250173143b9aSmrg	TRANS(SocketBytesReadable),
250273143b9aSmrg	TRANS(SocketRead),
250373143b9aSmrg	TRANS(SocketWrite),
250473143b9aSmrg	TRANS(SocketReadv),
250573143b9aSmrg	TRANS(SocketWritev),
250673143b9aSmrg	TRANS(SocketDisconnect),
250773143b9aSmrg	TRANS(SocketUNIXClose),
250873143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
250973143b9aSmrg	};
251073143b9aSmrg
251173143b9aSmrg#endif /* UNIXCONN */
2512