Xtranssock.c revision e8a71cdf
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>
90e8a71cdfSmrg#if defined(SVR4) || 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
225e8a71cdfSmrg#elif defined(SVR4) || 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, ':');
531e8a71cdfSmrg    if (ciptr->port == NULL) {
532e8a71cdfSmrg	if (is_numeric(addr->sa_data)) {
533e8a71cdfSmrg	    ciptr->port = addr->sa_data;
534e8a71cdfSmrg	}
535e8a71cdfSmrg    } else if (ciptr->port[0] == ':') {
536e8a71cdfSmrg	ciptr->port++;
537e8a71cdfSmrg    }
538e8a71cdfSmrg    /* port should now point to portnum or NULL */
53973143b9aSmrg    return ciptr;
54073143b9aSmrg}
54173143b9aSmrg
54273143b9aSmrg#endif /* TRANS_REOPEN */
54373143b9aSmrg
54473143b9aSmrg
54573143b9aSmrg/*
54673143b9aSmrg * These functions are the interface supplied in the Xtransport structure
54773143b9aSmrg */
54873143b9aSmrg
54973143b9aSmrg#ifdef TRANS_CLIENT
55073143b9aSmrg
55173143b9aSmrgstatic XtransConnInfo
55273143b9aSmrgTRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
55373143b9aSmrg				char *host, char *port, int previndex)
55473143b9aSmrg{
55573143b9aSmrg    XtransConnInfo	ciptr;
55673143b9aSmrg    int			i = previndex;
55773143b9aSmrg
55873143b9aSmrg    PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
55973143b9aSmrg	protocol, host, port);
56073143b9aSmrg
56173143b9aSmrg    SocketInitOnce();
56273143b9aSmrg
56373143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
56473143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
565e8a71cdfSmrg		i, Sockettrans2devtab[i].devcotsname)) != NULL) {
566e8a71cdfSmrg	    /* Save the index for later use */
567e8a71cdfSmrg
568e8a71cdfSmrg	    ciptr->index = i;
56973143b9aSmrg	    break;
570e8a71cdfSmrg	}
57173143b9aSmrg    }
57273143b9aSmrg    if (i < 0) {
57373143b9aSmrg	if (i == -1)
57473143b9aSmrg	    PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
57573143b9aSmrg		   transname, 0, 0);
57673143b9aSmrg	else
57773143b9aSmrg	    PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
57873143b9aSmrg		   transname, 0, 0);
57973143b9aSmrg	return NULL;
58073143b9aSmrg    }
58173143b9aSmrg
58273143b9aSmrg    return ciptr;
58373143b9aSmrg}
58473143b9aSmrg
58573143b9aSmrgstatic XtransConnInfo
58673143b9aSmrgTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
58773143b9aSmrg			     char *host, char *port)
58873143b9aSmrg{
58973143b9aSmrg    return TRANS(SocketOpenCOTSClientBase)(
59073143b9aSmrg			thistrans->TransName, protocol, host, port, -1);
59173143b9aSmrg}
59273143b9aSmrg
59373143b9aSmrg
59473143b9aSmrg#endif /* TRANS_CLIENT */
59573143b9aSmrg
59673143b9aSmrg
59773143b9aSmrg#ifdef TRANS_SERVER
59873143b9aSmrg
59973143b9aSmrgstatic XtransConnInfo
60073143b9aSmrgTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
60173143b9aSmrg			     char *host, char *port)
60273143b9aSmrg
60373143b9aSmrg{
60473143b9aSmrg    XtransConnInfo	ciptr;
60573143b9aSmrg    int	i = -1;
60673143b9aSmrg
60773143b9aSmrg    PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
60873143b9aSmrg
60973143b9aSmrg    SocketInitOnce();
61073143b9aSmrg
61173143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
61273143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
61373143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
61473143b9aSmrg	    break;
61573143b9aSmrg    }
61673143b9aSmrg    if (i < 0) {
61773143b9aSmrg	if (i == -1)
61873143b9aSmrg	    PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
61973143b9aSmrg		   thistrans->TransName, 0, 0);
62073143b9aSmrg	else
62173143b9aSmrg	    PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
62273143b9aSmrg		   thistrans->TransName, 0, 0);
62373143b9aSmrg	return NULL;
62473143b9aSmrg    }
62573143b9aSmrg
62673143b9aSmrg    /*
62773143b9aSmrg     * Using this prevents the bind() check for an existing server listening
62873143b9aSmrg     * on the same port, but it is required for other reasons.
62973143b9aSmrg     */
63073143b9aSmrg#ifdef SO_REUSEADDR
63173143b9aSmrg
63273143b9aSmrg    /*
63373143b9aSmrg     * SO_REUSEADDR only applied to AF_INET && AF_INET6
63473143b9aSmrg     */
63573143b9aSmrg
63673143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
63773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
63873143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
63973143b9aSmrg#endif
64073143b9aSmrg    )
64173143b9aSmrg    {
64273143b9aSmrg	int one = 1;
64373143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
64473143b9aSmrg		    (char *) &one, sizeof (int));
64573143b9aSmrg    }
64673143b9aSmrg#endif
64773143b9aSmrg#ifdef IPV6_V6ONLY
64873143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
64973143b9aSmrg    {
65073143b9aSmrg	int one = 1;
65173143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
65273143b9aSmrg    }
65373143b9aSmrg#endif
65473143b9aSmrg    /* Save the index for later use */
65573143b9aSmrg
65673143b9aSmrg    ciptr->index = i;
65773143b9aSmrg
65873143b9aSmrg    return ciptr;
65973143b9aSmrg}
66073143b9aSmrg
66173143b9aSmrg#endif /* TRANS_SERVER */
66273143b9aSmrg
66373143b9aSmrg
66473143b9aSmrg#ifdef TRANS_CLIENT
66573143b9aSmrg
66673143b9aSmrgstatic XtransConnInfo
66773143b9aSmrgTRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
66873143b9aSmrg			     char *host, char *port)
66973143b9aSmrg
67073143b9aSmrg{
67173143b9aSmrg    XtransConnInfo	ciptr;
67273143b9aSmrg    int			i = -1;
67373143b9aSmrg
67473143b9aSmrg    PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
67573143b9aSmrg
67673143b9aSmrg    SocketInitOnce();
67773143b9aSmrg
67873143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
67973143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
68073143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
68173143b9aSmrg	    break;
68273143b9aSmrg    }
68373143b9aSmrg    if (i < 0) {
68473143b9aSmrg	if (i == -1)
68573143b9aSmrg	    PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
68673143b9aSmrg		   thistrans->TransName, 0, 0);
68773143b9aSmrg	else
68873143b9aSmrg	    PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
68973143b9aSmrg		   thistrans->TransName, 0, 0);
69073143b9aSmrg	return NULL;
69173143b9aSmrg    }
69273143b9aSmrg
69373143b9aSmrg    /* Save the index for later use */
69473143b9aSmrg
69573143b9aSmrg    ciptr->index = i;
69673143b9aSmrg
69773143b9aSmrg    return ciptr;
69873143b9aSmrg}
69973143b9aSmrg
70073143b9aSmrg#endif /* TRANS_CLIENT */
70173143b9aSmrg
70273143b9aSmrg
70373143b9aSmrg#ifdef TRANS_SERVER
70473143b9aSmrg
70573143b9aSmrgstatic XtransConnInfo
70673143b9aSmrgTRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
70773143b9aSmrg			     char *host, char *port)
70873143b9aSmrg
70973143b9aSmrg{
71073143b9aSmrg    XtransConnInfo	ciptr;
71173143b9aSmrg    int	i = -1;
71273143b9aSmrg
71373143b9aSmrg    PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
71473143b9aSmrg
71573143b9aSmrg    SocketInitOnce();
71673143b9aSmrg
71773143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
71873143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
71973143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
72073143b9aSmrg	    break;
72173143b9aSmrg    }
72273143b9aSmrg    if (i < 0) {
72373143b9aSmrg	if (i == -1)
72473143b9aSmrg	    PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
72573143b9aSmrg		   thistrans->TransName, 0, 0);
72673143b9aSmrg	else
72773143b9aSmrg	    PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
72873143b9aSmrg		   thistrans->TransName, 0, 0);
72973143b9aSmrg	return NULL;
73073143b9aSmrg    }
73173143b9aSmrg
73273143b9aSmrg#ifdef IPV6_V6ONLY
73373143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
73473143b9aSmrg    {
73573143b9aSmrg	int one = 1;
73673143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
73773143b9aSmrg    }
73873143b9aSmrg#endif
73973143b9aSmrg    /* Save the index for later use */
74073143b9aSmrg
74173143b9aSmrg    ciptr->index = i;
74273143b9aSmrg
74373143b9aSmrg    return ciptr;
74473143b9aSmrg}
74573143b9aSmrg
74673143b9aSmrg#endif /* TRANS_SERVER */
74773143b9aSmrg
74873143b9aSmrg
74973143b9aSmrg#ifdef TRANS_REOPEN
75073143b9aSmrg
75173143b9aSmrgstatic XtransConnInfo
75273143b9aSmrgTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
75373143b9aSmrg
75473143b9aSmrg{
75573143b9aSmrg    XtransConnInfo	ciptr;
75673143b9aSmrg    int			i = -1;
75773143b9aSmrg
75873143b9aSmrg    PRMSG (2,
75973143b9aSmrg	"SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
76073143b9aSmrg
76173143b9aSmrg    SocketInitOnce();
76273143b9aSmrg
76373143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
76473143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
76573143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
76673143b9aSmrg	    break;
76773143b9aSmrg    }
76873143b9aSmrg    if (i < 0) {
76973143b9aSmrg	if (i == -1)
77073143b9aSmrg	    PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
77173143b9aSmrg		   thistrans->TransName, 0, 0);
77273143b9aSmrg	else
77373143b9aSmrg	    PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
77473143b9aSmrg		   thistrans->TransName, 0, 0);
77573143b9aSmrg	return NULL;
77673143b9aSmrg    }
77773143b9aSmrg
77873143b9aSmrg    /* Save the index for later use */
77973143b9aSmrg
78073143b9aSmrg    ciptr->index = i;
78173143b9aSmrg
78273143b9aSmrg    return ciptr;
78373143b9aSmrg}
78473143b9aSmrg
78573143b9aSmrgstatic XtransConnInfo
78673143b9aSmrgTRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
78773143b9aSmrg
78873143b9aSmrg{
78973143b9aSmrg    XtransConnInfo	ciptr;
79073143b9aSmrg    int			i = -1;
79173143b9aSmrg
79273143b9aSmrg    PRMSG (2,
79373143b9aSmrg	"SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
79473143b9aSmrg
79573143b9aSmrg    SocketInitOnce();
79673143b9aSmrg
79773143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
79873143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
79973143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
80073143b9aSmrg	    break;
80173143b9aSmrg    }
80273143b9aSmrg    if (i < 0) {
80373143b9aSmrg	if (i == -1)
80473143b9aSmrg	    PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
80573143b9aSmrg		   thistrans->TransName, 0, 0);
80673143b9aSmrg	else
80773143b9aSmrg	    PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
80873143b9aSmrg		   thistrans->TransName, 0, 0);
80973143b9aSmrg	return NULL;
81073143b9aSmrg    }
81173143b9aSmrg
81273143b9aSmrg    /* Save the index for later use */
81373143b9aSmrg
81473143b9aSmrg    ciptr->index = i;
81573143b9aSmrg
81673143b9aSmrg    return ciptr;
81773143b9aSmrg}
81873143b9aSmrg
81973143b9aSmrg#endif /* TRANS_REOPEN */
82073143b9aSmrg
82173143b9aSmrg
82273143b9aSmrgstatic int
82373143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
82473143b9aSmrg
82573143b9aSmrg{
82673143b9aSmrg    PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
82773143b9aSmrg
82873143b9aSmrg    return -1;
82973143b9aSmrg}
83073143b9aSmrg
83173143b9aSmrg#ifdef UNIXCONN
83273143b9aSmrgstatic int
83373143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract)
83473143b9aSmrg{
83573143b9aSmrg    struct sockaddr_un s;
83673143b9aSmrg    int maxlen = sizeof(s.sun_path) - 1;
83773143b9aSmrg    const char *at = "";
83873143b9aSmrg
83973143b9aSmrg    if (!port || !*port || !path)
84073143b9aSmrg	return -1;
84173143b9aSmrg
84273143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
84373143b9aSmrg    if (port[0] == '@')
84473143b9aSmrg	upath = "";
84573143b9aSmrg    else if (abstract)
84673143b9aSmrg	at = "@";
84773143b9aSmrg#endif
84873143b9aSmrg
84973143b9aSmrg    if (*port == '/') /* a full pathname */
85073143b9aSmrg	upath = "";
85173143b9aSmrg
85273143b9aSmrg    if (strlen(port) + strlen(upath) > maxlen)
85373143b9aSmrg	return -1;
85473143b9aSmrg    sprintf(path, "%s%s%s", at, upath, port);
85573143b9aSmrg    return 0;
85673143b9aSmrg}
85773143b9aSmrg#endif
85873143b9aSmrg
85973143b9aSmrg#ifdef TRANS_SERVER
86073143b9aSmrg
86173143b9aSmrgstatic int
86273143b9aSmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr,
86373143b9aSmrg			     struct sockaddr *sockname,
86473143b9aSmrg			     int socknamelen, unsigned int flags)
86573143b9aSmrg
86673143b9aSmrg{
86773143b9aSmrg    SOCKLEN_T namelen = socknamelen;
86873143b9aSmrg    int	fd = ciptr->fd;
86973143b9aSmrg    int	retry;
87073143b9aSmrg
87173143b9aSmrg    PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
87273143b9aSmrg
87373143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
87473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
87573143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
87673143b9aSmrg#endif
87773143b9aSmrg	)
87873143b9aSmrg	retry = 20;
87973143b9aSmrg    else
88073143b9aSmrg	retry = 0;
88173143b9aSmrg
88273143b9aSmrg    while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
88373143b9aSmrg    {
88473143b9aSmrg	if (errno == EADDRINUSE) {
88573143b9aSmrg	    if (flags & ADDR_IN_USE_ALLOWED)
88673143b9aSmrg		break;
88773143b9aSmrg	    else
88873143b9aSmrg		return TRANS_ADDR_IN_USE;
88973143b9aSmrg	}
89073143b9aSmrg
89173143b9aSmrg	if (retry-- == 0) {
89273143b9aSmrg	    PRMSG (1, "SocketCreateListener: failed to bind listener\n",
89373143b9aSmrg		0, 0, 0);
89473143b9aSmrg	    close (fd);
89573143b9aSmrg	    return TRANS_CREATE_LISTENER_FAILED;
89673143b9aSmrg	}
89773143b9aSmrg#ifdef SO_REUSEADDR
89873143b9aSmrg	sleep (1);
89973143b9aSmrg#else
90073143b9aSmrg	sleep (10);
90173143b9aSmrg#endif /* SO_REUSEDADDR */
90273143b9aSmrg    }
90373143b9aSmrg
90473143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
90573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
90673143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
90773143b9aSmrg#endif
90873143b9aSmrg	) {
90973143b9aSmrg#ifdef SO_DONTLINGER
91073143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
91173143b9aSmrg#else
91273143b9aSmrg#ifdef SO_LINGER
91373143b9aSmrg    {
91473143b9aSmrg	static int linger[2] = { 0, 0 };
91573143b9aSmrg	setsockopt (fd, SOL_SOCKET, SO_LINGER,
91673143b9aSmrg		(char *) linger, sizeof (linger));
91773143b9aSmrg    }
91873143b9aSmrg#endif
91973143b9aSmrg#endif
92073143b9aSmrg}
92173143b9aSmrg
92273143b9aSmrg    if (listen (fd, BACKLOG) < 0)
92373143b9aSmrg    {
92473143b9aSmrg	PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
92573143b9aSmrg	close (fd);
92673143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
92773143b9aSmrg    }
92873143b9aSmrg
92973143b9aSmrg    /* Set a flag to indicate that this connection is a listener */
93073143b9aSmrg
93173143b9aSmrg    ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
93273143b9aSmrg
93373143b9aSmrg    return 0;
93473143b9aSmrg}
93573143b9aSmrg
93673143b9aSmrg#ifdef TCPCONN
93773143b9aSmrgstatic int
93873143b9aSmrgTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
93973143b9aSmrg
94073143b9aSmrg{
94173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
94273143b9aSmrg    struct sockaddr_storage sockname;
94373143b9aSmrg#else
94473143b9aSmrg    struct sockaddr_in	    sockname;
94573143b9aSmrg#endif
94673143b9aSmrg    unsigned short	    sport;
94773143b9aSmrg    SOCKLEN_T	namelen = sizeof(sockname);
94873143b9aSmrg    int		status;
94973143b9aSmrg    long	tmpport;
95073143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
95173143b9aSmrg    _Xgetservbynameparams sparams;
95273143b9aSmrg#endif
95373143b9aSmrg    struct servent *servp;
95473143b9aSmrg
95573143b9aSmrg#ifdef X11_t
95673143b9aSmrg    char	portbuf[PORTBUFSIZE];
95773143b9aSmrg#endif
95873143b9aSmrg
95973143b9aSmrg    PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
96073143b9aSmrg
96173143b9aSmrg#ifdef X11_t
96273143b9aSmrg    /*
96373143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
96473143b9aSmrg     * to handle it here, than try and come up with a transport independent
96573143b9aSmrg     * representation that can be passed in and resolved the usual way.
96673143b9aSmrg     *
96773143b9aSmrg     * The port that is passed here is really a string containing the idisplay
96873143b9aSmrg     * from ConnectDisplay().
96973143b9aSmrg     */
97073143b9aSmrg
97173143b9aSmrg    if (is_numeric (port))
97273143b9aSmrg    {
97373143b9aSmrg	/* fixup the server port address */
97473143b9aSmrg	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
97573143b9aSmrg	sprintf (portbuf,"%lu", tmpport);
97673143b9aSmrg	port = portbuf;
97773143b9aSmrg    }
97873143b9aSmrg#endif
97973143b9aSmrg
98073143b9aSmrg    if (port && *port)
98173143b9aSmrg    {
98273143b9aSmrg	/* Check to see if the port string is just a number (handles X11) */
98373143b9aSmrg
98473143b9aSmrg	if (!is_numeric (port))
98573143b9aSmrg	{
98673143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
98773143b9aSmrg	    {
98873143b9aSmrg		PRMSG (1,
98973143b9aSmrg	     "SocketINETCreateListener: Unable to get service for %s\n",
99073143b9aSmrg		      port, 0, 0);
99173143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
99273143b9aSmrg	    }
99373143b9aSmrg	    /* we trust getservbyname to return a valid number */
99473143b9aSmrg	    sport = servp->s_port;
99573143b9aSmrg	}
99673143b9aSmrg	else
99773143b9aSmrg	{
99873143b9aSmrg	    tmpport = strtol (port, (char**)NULL, 10);
99973143b9aSmrg	    /*
100073143b9aSmrg	     * check that somehow the port address isn't negative or in
100173143b9aSmrg	     * the range of reserved port addresses. This can happen and
100273143b9aSmrg	     * be very bad if the server is suid-root and the user does
100373143b9aSmrg	     * something (dumb) like `X :60049`.
100473143b9aSmrg	     */
100573143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
100673143b9aSmrg		return TRANS_CREATE_LISTENER_FAILED;
100773143b9aSmrg
100873143b9aSmrg	    sport = (unsigned short) tmpport;
100973143b9aSmrg	}
101073143b9aSmrg    }
101173143b9aSmrg    else
101273143b9aSmrg	sport = 0;
101373143b9aSmrg
101473143b9aSmrg    bzero(&sockname, sizeof(sockname));
101573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
101673143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
101773143b9aSmrg	namelen = sizeof (struct sockaddr_in);
101873143b9aSmrg#ifdef BSD44SOCKETS
101973143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_len = namelen;
102073143b9aSmrg#endif
102173143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
102273143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
102373143b9aSmrg	((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
102473143b9aSmrg    } else {
102573143b9aSmrg	namelen = sizeof (struct sockaddr_in6);
102673143b9aSmrg#ifdef SIN6_LEN
102773143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
102873143b9aSmrg#endif
102973143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
103073143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
103173143b9aSmrg	((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
103273143b9aSmrg    }
103373143b9aSmrg#else
103473143b9aSmrg#ifdef BSD44SOCKETS
103573143b9aSmrg    sockname.sin_len = sizeof (sockname);
103673143b9aSmrg#endif
103773143b9aSmrg    sockname.sin_family = AF_INET;
103873143b9aSmrg    sockname.sin_port = htons (sport);
103973143b9aSmrg    sockname.sin_addr.s_addr = htonl (INADDR_ANY);
104073143b9aSmrg#endif
104173143b9aSmrg
104273143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
104373143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
104473143b9aSmrg    {
104573143b9aSmrg	PRMSG (1,
104673143b9aSmrg    "SocketINETCreateListener: ...SocketCreateListener() failed\n",
104773143b9aSmrg	    0, 0, 0);
104873143b9aSmrg	return status;
104973143b9aSmrg    }
105073143b9aSmrg
105173143b9aSmrg    if (TRANS(SocketINETGetAddr) (ciptr) < 0)
105273143b9aSmrg    {
105373143b9aSmrg	PRMSG (1,
105473143b9aSmrg       "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
105573143b9aSmrg	    0, 0, 0);
105673143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
105773143b9aSmrg    }
105873143b9aSmrg
105973143b9aSmrg    return 0;
106073143b9aSmrg}
106173143b9aSmrg
106273143b9aSmrg#endif /* TCPCONN */
106373143b9aSmrg
106473143b9aSmrg
106573143b9aSmrg#ifdef UNIXCONN
106673143b9aSmrg
106773143b9aSmrgstatic int
106873143b9aSmrgTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
106973143b9aSmrg				 unsigned int flags)
107073143b9aSmrg
107173143b9aSmrg{
107273143b9aSmrg    struct sockaddr_un	sockname;
107373143b9aSmrg    int			namelen;
107473143b9aSmrg    int			oldUmask;
107573143b9aSmrg    int			status;
107673143b9aSmrg    unsigned int	mode;
107773143b9aSmrg    char		tmpport[108];
107873143b9aSmrg
107973143b9aSmrg    int			abstract = 0;
108073143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
108173143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
108273143b9aSmrg#endif
108373143b9aSmrg
108473143b9aSmrg    PRMSG (2, "SocketUNIXCreateListener(%s)\n",
108573143b9aSmrg	port ? port : "NULL", 0, 0);
108673143b9aSmrg
108773143b9aSmrg    /* Make sure the directory is created */
108873143b9aSmrg
108973143b9aSmrg    oldUmask = umask (0);
109073143b9aSmrg
109173143b9aSmrg#ifdef UNIX_DIR
109273143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
109373143b9aSmrg    mode = 01777;
109473143b9aSmrg#else
109573143b9aSmrg    mode = 0777;
109673143b9aSmrg#endif
10978d4c0f7bSmrg    if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
109873143b9aSmrg	PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
109973143b9aSmrg	       UNIX_DIR, errno, 0);
110073143b9aSmrg	(void) umask (oldUmask);
110173143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
110273143b9aSmrg    }
110373143b9aSmrg#endif
110473143b9aSmrg
110573143b9aSmrg    memset(&sockname, 0, sizeof(sockname));
110673143b9aSmrg    sockname.sun_family = AF_UNIX;
110773143b9aSmrg
110873143b9aSmrg    if (!(port && *port)) {
110973143b9aSmrg	snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
111073143b9aSmrg	port = tmpport;
111173143b9aSmrg    }
111273143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
111373143b9aSmrg	PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
111473143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
111573143b9aSmrg    }
111673143b9aSmrg
11178d4c0f7bSmrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
111873143b9aSmrg    sockname.sun_len = strlen(sockname.sun_path);
111973143b9aSmrg#endif
112073143b9aSmrg
112173143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
112273143b9aSmrg    namelen = SUN_LEN(&sockname);
112373143b9aSmrg#else
112473143b9aSmrg    namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
112573143b9aSmrg#endif
112673143b9aSmrg
112773143b9aSmrg    if (abstract) {
112873143b9aSmrg	sockname.sun_path[0] = '\0';
112973143b9aSmrg	namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
113073143b9aSmrg    }
113173143b9aSmrg    else
113273143b9aSmrg	unlink (sockname.sun_path);
113373143b9aSmrg
113473143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
113573143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
113673143b9aSmrg    {
113773143b9aSmrg	PRMSG (1,
113873143b9aSmrg    "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
113973143b9aSmrg	    0, 0, 0);
114073143b9aSmrg	(void) umask (oldUmask);
114173143b9aSmrg	return status;
114273143b9aSmrg    }
114373143b9aSmrg
114473143b9aSmrg    /*
114573143b9aSmrg     * Now that the listener is esablished, create the addr info for
114673143b9aSmrg     * this connection. getpeername() doesn't work for UNIX Domain Sockets
114773143b9aSmrg     * on some systems (hpux at least), so we will just do it manually, instead
114873143b9aSmrg     * of calling something like TRANS(SocketUNIXGetAddr).
114973143b9aSmrg     */
115073143b9aSmrg
115173143b9aSmrg    namelen = sizeof (sockname); /* this will always make it the same size */
115273143b9aSmrg
115373143b9aSmrg    if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
115473143b9aSmrg    {
115573143b9aSmrg        PRMSG (1,
115673143b9aSmrg        "SocketUNIXCreateListener: Can't allocate space for the addr\n",
115773143b9aSmrg	    0, 0, 0);
115873143b9aSmrg	(void) umask (oldUmask);
115973143b9aSmrg        return TRANS_CREATE_LISTENER_FAILED;
116073143b9aSmrg    }
116173143b9aSmrg
116273143b9aSmrg    if (abstract)
116373143b9aSmrg	sockname.sun_path[0] = '@';
116473143b9aSmrg
116573143b9aSmrg    ciptr->family = sockname.sun_family;
116673143b9aSmrg    ciptr->addrlen = namelen;
116773143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
116873143b9aSmrg
116973143b9aSmrg    (void) umask (oldUmask);
117073143b9aSmrg
117173143b9aSmrg    return 0;
117273143b9aSmrg}
117373143b9aSmrg
117473143b9aSmrg
117573143b9aSmrgstatic int
117673143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
117773143b9aSmrg
117873143b9aSmrg{
117973143b9aSmrg    /*
118073143b9aSmrg     * See if the unix domain socket has disappeared.  If it has, recreate it.
118173143b9aSmrg     */
118273143b9aSmrg
118373143b9aSmrg    struct sockaddr_un 	*unsock = (struct sockaddr_un *) ciptr->addr;
118473143b9aSmrg    struct stat		statb;
118573143b9aSmrg    int 		status = TRANS_RESET_NOOP;
118673143b9aSmrg    unsigned int	mode;
118773143b9aSmrg    int abstract = 0;
118873143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
118973143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
119073143b9aSmrg#endif
119173143b9aSmrg
119273143b9aSmrg    PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
119373143b9aSmrg
119473143b9aSmrg    if (!abstract && (
119573143b9aSmrg	stat (unsock->sun_path, &statb) == -1 ||
119673143b9aSmrg        ((statb.st_mode & S_IFMT) !=
1197e8a71cdfSmrg#if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
119873143b9aSmrg	  		S_IFIFO
119973143b9aSmrg#else
120073143b9aSmrg			S_IFSOCK
120173143b9aSmrg#endif
120273143b9aSmrg				)))
120373143b9aSmrg    {
120473143b9aSmrg	int oldUmask = umask (0);
120573143b9aSmrg
120673143b9aSmrg#ifdef UNIX_DIR
120773143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
120873143b9aSmrg	mode = 01777;
120973143b9aSmrg#else
121073143b9aSmrg	mode = 0777;
121173143b9aSmrg#endif
121273143b9aSmrg        if (trans_mkdir(UNIX_DIR, mode) == -1) {
121373143b9aSmrg            PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
121473143b9aSmrg	    UNIX_DIR, errno, 0);
121573143b9aSmrg	    (void) umask (oldUmask);
121673143b9aSmrg	    return TRANS_RESET_FAILURE;
121773143b9aSmrg        }
121873143b9aSmrg#endif
121973143b9aSmrg
122073143b9aSmrg	close (ciptr->fd);
122173143b9aSmrg	unlink (unsock->sun_path);
122273143b9aSmrg
122373143b9aSmrg	if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
122473143b9aSmrg	{
122573143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
122673143b9aSmrg	    (void) umask (oldUmask);
122773143b9aSmrg	    return TRANS_RESET_FAILURE;
122873143b9aSmrg	}
122973143b9aSmrg
123073143b9aSmrg	if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
123173143b9aSmrg	{
123273143b9aSmrg	    close (ciptr->fd);
123373143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
123473143b9aSmrg	    return TRANS_RESET_FAILURE;
123573143b9aSmrg	}
123673143b9aSmrg
123773143b9aSmrg	if (listen (ciptr->fd, BACKLOG) < 0)
123873143b9aSmrg	{
123973143b9aSmrg	    close (ciptr->fd);
124073143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
124173143b9aSmrg	    (void) umask (oldUmask);
124273143b9aSmrg	    return TRANS_RESET_FAILURE;
124373143b9aSmrg	}
124473143b9aSmrg
124573143b9aSmrg	umask (oldUmask);
124673143b9aSmrg
124773143b9aSmrg	status = TRANS_RESET_NEW_FD;
124873143b9aSmrg    }
124973143b9aSmrg
125073143b9aSmrg    return status;
125173143b9aSmrg}
125273143b9aSmrg
125373143b9aSmrg#endif /* UNIXCONN */
125473143b9aSmrg
125573143b9aSmrg
125673143b9aSmrg#ifdef TCPCONN
125773143b9aSmrg
125873143b9aSmrgstatic XtransConnInfo
125973143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
126073143b9aSmrg
126173143b9aSmrg{
126273143b9aSmrg    XtransConnInfo	newciptr;
126373143b9aSmrg    struct sockaddr_in	sockname;
126473143b9aSmrg    SOCKLEN_T		namelen = sizeof(sockname);
126573143b9aSmrg
126673143b9aSmrg    PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
126773143b9aSmrg
126873143b9aSmrg    if ((newciptr = (XtransConnInfo) xcalloc (
126973143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
127073143b9aSmrg    {
127173143b9aSmrg	PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
127273143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
127373143b9aSmrg	return NULL;
127473143b9aSmrg    }
127573143b9aSmrg
127673143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
127773143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
127873143b9aSmrg    {
127973143b9aSmrg#ifdef WIN32
128073143b9aSmrg	errno = WSAGetLastError();
128173143b9aSmrg#endif
128273143b9aSmrg	PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
128373143b9aSmrg	xfree (newciptr);
128473143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
128573143b9aSmrg	return NULL;
128673143b9aSmrg    }
128773143b9aSmrg
128873143b9aSmrg#ifdef TCP_NODELAY
128973143b9aSmrg    {
129073143b9aSmrg	/*
129173143b9aSmrg	 * turn off TCP coalescence for INET sockets
129273143b9aSmrg	 */
129373143b9aSmrg
129473143b9aSmrg	int tmp = 1;
129573143b9aSmrg	setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
129673143b9aSmrg	    (char *) &tmp, sizeof (int));
129773143b9aSmrg    }
129873143b9aSmrg#endif
129973143b9aSmrg
130073143b9aSmrg    /*
130173143b9aSmrg     * Get this address again because the transport may give a more
130273143b9aSmrg     * specific address now that a connection is established.
130373143b9aSmrg     */
130473143b9aSmrg
130573143b9aSmrg    if (TRANS(SocketINETGetAddr) (newciptr) < 0)
130673143b9aSmrg    {
130773143b9aSmrg	PRMSG (1,
130873143b9aSmrg	    "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
130973143b9aSmrg	    0, 0, 0);
131073143b9aSmrg	close (newciptr->fd);
131173143b9aSmrg	xfree (newciptr);
131273143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
131373143b9aSmrg        return NULL;
131473143b9aSmrg    }
131573143b9aSmrg
131673143b9aSmrg    if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
131773143b9aSmrg    {
131873143b9aSmrg	PRMSG (1,
131973143b9aSmrg	  "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
132073143b9aSmrg		0, 0, 0);
132173143b9aSmrg	close (newciptr->fd);
132273143b9aSmrg	if (newciptr->addr) xfree (newciptr->addr);
132373143b9aSmrg	xfree (newciptr);
132473143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
132573143b9aSmrg        return NULL;
132673143b9aSmrg    }
132773143b9aSmrg
132873143b9aSmrg    *status = 0;
132973143b9aSmrg
133073143b9aSmrg    return newciptr;
133173143b9aSmrg}
133273143b9aSmrg
133373143b9aSmrg#endif /* TCPCONN */
133473143b9aSmrg
133573143b9aSmrg
133673143b9aSmrg#ifdef UNIXCONN
133773143b9aSmrgstatic XtransConnInfo
133873143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
133973143b9aSmrg
134073143b9aSmrg{
134173143b9aSmrg    XtransConnInfo	newciptr;
134273143b9aSmrg    struct sockaddr_un	sockname;
134373143b9aSmrg    SOCKLEN_T 		namelen = sizeof sockname;
134473143b9aSmrg
134573143b9aSmrg    PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
134673143b9aSmrg
134773143b9aSmrg    if ((newciptr = (XtransConnInfo) xcalloc (
134873143b9aSmrg	1, sizeof(struct _XtransConnInfo))) == NULL)
134973143b9aSmrg    {
135073143b9aSmrg	PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
135173143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
135273143b9aSmrg	return NULL;
135373143b9aSmrg    }
135473143b9aSmrg
135573143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
135673143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
135773143b9aSmrg    {
135873143b9aSmrg	PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
135973143b9aSmrg	xfree (newciptr);
136073143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
136173143b9aSmrg	return NULL;
136273143b9aSmrg    }
136373143b9aSmrg
136473143b9aSmrg	ciptr->addrlen = namelen;
136573143b9aSmrg    /*
136673143b9aSmrg     * Get the socket name and the peer name from the listener socket,
136773143b9aSmrg     * since this is unix domain.
136873143b9aSmrg     */
136973143b9aSmrg
137073143b9aSmrg    if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
137173143b9aSmrg    {
137273143b9aSmrg        PRMSG (1,
137373143b9aSmrg        "SocketUNIXAccept: Can't allocate space for the addr\n",
137473143b9aSmrg	      0, 0, 0);
137573143b9aSmrg	close (newciptr->fd);
137673143b9aSmrg	xfree (newciptr);
137773143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
137873143b9aSmrg        return NULL;
137973143b9aSmrg    }
138073143b9aSmrg
138173143b9aSmrg    /*
138273143b9aSmrg     * if the socket is abstract, we already modified the address to have a
138373143b9aSmrg     * @ instead of the initial NUL, so no need to do that again here.
138473143b9aSmrg     */
138573143b9aSmrg
138673143b9aSmrg    newciptr->addrlen = ciptr->addrlen;
138773143b9aSmrg    memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
138873143b9aSmrg
138973143b9aSmrg    if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
139073143b9aSmrg    {
139173143b9aSmrg        PRMSG (1,
139273143b9aSmrg	      "SocketUNIXAccept: Can't allocate space for the addr\n",
139373143b9aSmrg	      0, 0, 0);
139473143b9aSmrg	close (newciptr->fd);
139573143b9aSmrg	if (newciptr->addr) xfree (newciptr->addr);
139673143b9aSmrg	xfree (newciptr);
139773143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
139873143b9aSmrg        return NULL;
139973143b9aSmrg    }
140073143b9aSmrg
140173143b9aSmrg    newciptr->peeraddrlen = ciptr->addrlen;
140273143b9aSmrg    memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
140373143b9aSmrg
140473143b9aSmrg    newciptr->family = AF_UNIX;
140573143b9aSmrg
140673143b9aSmrg    *status = 0;
140773143b9aSmrg
140873143b9aSmrg    return newciptr;
140973143b9aSmrg}
141073143b9aSmrg
141173143b9aSmrg#endif /* UNIXCONN */
141273143b9aSmrg
141373143b9aSmrg#endif /* TRANS_SERVER */
141473143b9aSmrg
141573143b9aSmrg
141673143b9aSmrg#ifdef TRANS_CLIENT
141773143b9aSmrg
141873143b9aSmrg#ifdef TCPCONN
141973143b9aSmrg
142073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
142173143b9aSmrgstruct addrlist {
142273143b9aSmrg    struct addrinfo *	addr;
142373143b9aSmrg    struct addrinfo *	firstaddr;
142473143b9aSmrg    char 		port[PORTBUFSIZE];
142573143b9aSmrg    char 		host[MAXHOSTNAMELEN];
142673143b9aSmrg};
142773143b9aSmrgstatic struct addrlist  *addrlist = NULL;
142873143b9aSmrg#endif
142973143b9aSmrg
143073143b9aSmrg
143173143b9aSmrgstatic int
143273143b9aSmrgTRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
143373143b9aSmrg
143473143b9aSmrg{
143573143b9aSmrg    struct sockaddr *	socketaddr = NULL;
143673143b9aSmrg    int			socketaddrlen = 0;
143773143b9aSmrg    int			res;
143873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
143973143b9aSmrg    struct addrinfo 	hints;
144073143b9aSmrg    char		ntopbuf[INET6_ADDRSTRLEN];
144173143b9aSmrg    int			resetonce = 0;
144273143b9aSmrg#endif
144373143b9aSmrg    struct sockaddr_in	sockname;
144473143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
144573143b9aSmrg    _Xgethostbynameparams hparams;
144673143b9aSmrg    _Xgetservbynameparams sparams;
144773143b9aSmrg#endif
144873143b9aSmrg    struct hostent	*hostp;
144973143b9aSmrg    struct servent	*servp;
145073143b9aSmrg    unsigned long 	tmpaddr;
145173143b9aSmrg#ifdef X11_t
145273143b9aSmrg    char	portbuf[PORTBUFSIZE];
145373143b9aSmrg#endif
145473143b9aSmrg
145573143b9aSmrg    long		tmpport;
145673143b9aSmrg    char 		hostnamebuf[256];		/* tmp space */
145773143b9aSmrg
145873143b9aSmrg    PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
145973143b9aSmrg
146073143b9aSmrg    if (!host)
146173143b9aSmrg    {
146273143b9aSmrg	hostnamebuf[0] = '\0';
146373143b9aSmrg	(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
146473143b9aSmrg	host = hostnamebuf;
146573143b9aSmrg    }
146673143b9aSmrg
146773143b9aSmrg#ifdef X11_t
146873143b9aSmrg    /*
146973143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
147073143b9aSmrg     * to handle it here, than try and come up with a transport independent
147173143b9aSmrg     * representation that can be passed in and resolved the usual way.
147273143b9aSmrg     *
147373143b9aSmrg     * The port that is passed here is really a string containing the idisplay
147473143b9aSmrg     * from ConnectDisplay().
147573143b9aSmrg     */
147673143b9aSmrg
147773143b9aSmrg    if (is_numeric (port))
147873143b9aSmrg    {
147973143b9aSmrg	tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
148073143b9aSmrg	sprintf (portbuf, "%lu", tmpport);
148173143b9aSmrg	port = portbuf;
148273143b9aSmrg    }
148373143b9aSmrg#endif
148473143b9aSmrg
148573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
148673143b9aSmrg    if (haveIPv6) {
148773143b9aSmrg	if (addrlist != NULL) {
148873143b9aSmrg	    if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
148973143b9aSmrg		if (addrlist->firstaddr)
149073143b9aSmrg		    freeaddrinfo(addrlist->firstaddr);
149173143b9aSmrg		addrlist->firstaddr = NULL;
149273143b9aSmrg	    }
149373143b9aSmrg	} else {
149473143b9aSmrg	    addrlist = malloc(sizeof(struct addrlist));
149573143b9aSmrg	    addrlist->firstaddr = NULL;
149673143b9aSmrg	}
149773143b9aSmrg
149873143b9aSmrg	if (addrlist->firstaddr == NULL) {
149973143b9aSmrg	    strncpy(addrlist->port, port, sizeof(addrlist->port));
150073143b9aSmrg	    addrlist->port[sizeof(addrlist->port) - 1] = '\0';
150173143b9aSmrg	    strncpy(addrlist->host, host, sizeof(addrlist->host));
150273143b9aSmrg	    addrlist->host[sizeof(addrlist->host) - 1] = '\0';
150373143b9aSmrg
150473143b9aSmrg	    bzero(&hints,sizeof(hints));
150573143b9aSmrg	    hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
150673143b9aSmrg
150773143b9aSmrg	    res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
150873143b9aSmrg	    if (res != 0) {
150973143b9aSmrg		PRMSG (1, "SocketINETConnect() can't get address "
151073143b9aSmrg			"for %s:%s: %s\n", host, port, gai_strerror(res));
151173143b9aSmrg		ESET(EINVAL);
151273143b9aSmrg		return TRANS_CONNECT_FAILED;
151373143b9aSmrg	    }
151473143b9aSmrg	    for (res = 0, addrlist->addr = addrlist->firstaddr;
151573143b9aSmrg		 addrlist->addr ; res++) {
151673143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
151773143b9aSmrg	    }
151873143b9aSmrg	    PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
151973143b9aSmrg	    res = 0;
152073143b9aSmrg	    addrlist->addr = NULL;
152173143b9aSmrg	}
152273143b9aSmrg
152373143b9aSmrg	while (socketaddr == NULL) {
152473143b9aSmrg	    if (addrlist->addr == NULL) {
152573143b9aSmrg		if (resetonce) {
152673143b9aSmrg		    /* Already checked entire list - no usable addresses */
152773143b9aSmrg		    PRMSG (1, "SocketINETConnect() no usable address "
152873143b9aSmrg			   "for %s:%s\n", host, port, 0);
152973143b9aSmrg		    return TRANS_CONNECT_FAILED;
153073143b9aSmrg		} else {
153173143b9aSmrg		    /* Go back to beginning of list */
153273143b9aSmrg		    resetonce = 1;
153373143b9aSmrg		    addrlist->addr = addrlist->firstaddr;
153473143b9aSmrg		}
153573143b9aSmrg	    }
153673143b9aSmrg
153773143b9aSmrg	    socketaddr = addrlist->addr->ai_addr;
153873143b9aSmrg	    socketaddrlen = addrlist->addr->ai_addrlen;
153973143b9aSmrg
154073143b9aSmrg	    if (addrlist->addr->ai_family == AF_INET) {
154173143b9aSmrg		struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
154273143b9aSmrg
154373143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
154473143b9aSmrg			inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
154573143b9aSmrg			ntopbuf,sizeof(ntopbuf)), 0, 0);
154673143b9aSmrg
154773143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
154873143b9aSmrg			ntohs(sin->sin_port), 0, 0);
154973143b9aSmrg
155073143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
155173143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
155273143b9aSmrg				"tcp") == 0) {
155373143b9aSmrg			XtransConnInfo newciptr;
155473143b9aSmrg
155573143b9aSmrg			/*
155673143b9aSmrg			 * Our socket is an IPv6 socket, but the address is
155773143b9aSmrg			 * IPv4.  Close it and get an IPv4 socket.  This is
155873143b9aSmrg			 * needed for IPv4 connections to work on platforms
155973143b9aSmrg			 * that don't allow IPv4 over IPv6 sockets.
156073143b9aSmrg			 */
156173143b9aSmrg			TRANS(SocketINETClose)(ciptr);
156273143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
156373143b9aSmrg					"tcp", "tcp", host, port, ciptr->index);
156473143b9aSmrg			if (newciptr)
156573143b9aSmrg			    ciptr->fd = newciptr->fd;
156673143b9aSmrg			if (!newciptr ||
156773143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
156873143b9aSmrg				AF_INET) {
156973143b9aSmrg			    socketaddr = NULL;
157073143b9aSmrg			    PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
157173143b9aSmrg					" socketfor IPv4 address\n", 0,0,0);
157273143b9aSmrg			}
157373143b9aSmrg			if (newciptr)
157473143b9aSmrg			    xfree(newciptr);
157573143b9aSmrg		    } else {
157673143b9aSmrg			socketaddr = NULL;
157773143b9aSmrg			PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
157873143b9aSmrg				0,0,0);
157973143b9aSmrg		    }
158073143b9aSmrg		}
158173143b9aSmrg	    } else if (addrlist->addr->ai_family == AF_INET6) {
158273143b9aSmrg		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
158373143b9aSmrg
158473143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
158573143b9aSmrg			inet_ntop(addrlist->addr->ai_family,
158673143b9aSmrg				  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
158773143b9aSmrg			0, 0);
158873143b9aSmrg		PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
158973143b9aSmrg			ntohs(sin6->sin6_port), 0, 0);
159073143b9aSmrg
159173143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
159273143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
159373143b9aSmrg				"tcp") == 0) {
159473143b9aSmrg			XtransConnInfo newciptr;
159573143b9aSmrg
159673143b9aSmrg			/*
159773143b9aSmrg			 * Close the IPv4 socket and try to open an IPv6 socket.
159873143b9aSmrg			 */
159973143b9aSmrg			TRANS(SocketINETClose)(ciptr);
160073143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
160173143b9aSmrg					"tcp", "tcp", host, port, -1);
160273143b9aSmrg			if (newciptr)
160373143b9aSmrg			    ciptr->fd = newciptr->fd;
160473143b9aSmrg			if (!newciptr ||
160573143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
160673143b9aSmrg					AF_INET6) {
160773143b9aSmrg			    socketaddr = NULL;
160873143b9aSmrg			    PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
160973143b9aSmrg				   "socket for IPv6 address\n", 0,0,0);
161073143b9aSmrg			}
161173143b9aSmrg			if (newciptr)
161273143b9aSmrg			    xfree(newciptr);
161373143b9aSmrg		    }
161473143b9aSmrg		    else
161573143b9aSmrg		    {
161673143b9aSmrg			socketaddr = NULL;
161773143b9aSmrg			PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
161873143b9aSmrg				0,0,0);
161973143b9aSmrg		    }
162073143b9aSmrg		}
162173143b9aSmrg	    } else {
162273143b9aSmrg		socketaddr = NULL; /* Unsupported address type */
162373143b9aSmrg	    }
162473143b9aSmrg	    if (socketaddr == NULL) {
162573143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
162673143b9aSmrg	    }
162773143b9aSmrg	}
162873143b9aSmrg    } else
162973143b9aSmrg#endif
163073143b9aSmrg    {
163173143b9aSmrg	/*
163273143b9aSmrg	 * Build the socket name.
163373143b9aSmrg	 */
163473143b9aSmrg
163573143b9aSmrg#ifdef BSD44SOCKETS
163673143b9aSmrg	sockname.sin_len = sizeof (struct sockaddr_in);
163773143b9aSmrg#endif
163873143b9aSmrg	sockname.sin_family = AF_INET;
163973143b9aSmrg
164073143b9aSmrg	/*
164173143b9aSmrg	 * fill in sin_addr
164273143b9aSmrg	 */
164373143b9aSmrg
164473143b9aSmrg#ifndef INADDR_NONE
164573143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff)
164673143b9aSmrg#endif
164773143b9aSmrg
164873143b9aSmrg	/* check for ww.xx.yy.zz host string */
164973143b9aSmrg
165073143b9aSmrg	if (isascii (host[0]) && isdigit (host[0])) {
165173143b9aSmrg	    tmpaddr = inet_addr (host); /* returns network byte order */
165273143b9aSmrg	} else {
165373143b9aSmrg	    tmpaddr = INADDR_NONE;
165473143b9aSmrg	}
165573143b9aSmrg
165673143b9aSmrg	PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
165773143b9aSmrg
165873143b9aSmrg	if (tmpaddr == INADDR_NONE) {
165973143b9aSmrg	    if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
166073143b9aSmrg		PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
166173143b9aSmrg			host, 0, 0);
166273143b9aSmrg		ESET(EINVAL);
166373143b9aSmrg		return TRANS_CONNECT_FAILED;
166473143b9aSmrg	    }
166573143b9aSmrg	    if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
166673143b9aSmrg		PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
166773143b9aSmrg		ESET(EPROTOTYPE);
166873143b9aSmrg		return TRANS_CONNECT_FAILED;
166973143b9aSmrg	    }
167073143b9aSmrg
167173143b9aSmrg	    memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
167273143b9aSmrg		    sizeof (sockname.sin_addr));
167373143b9aSmrg
167473143b9aSmrg	} else {
167573143b9aSmrg	    sockname.sin_addr.s_addr = tmpaddr;
167673143b9aSmrg        }
167773143b9aSmrg
167873143b9aSmrg	/*
167973143b9aSmrg	 * fill in sin_port
168073143b9aSmrg	 */
168173143b9aSmrg
168273143b9aSmrg	/* Check for number in the port string */
168373143b9aSmrg
168473143b9aSmrg	if (!is_numeric (port)) {
168573143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
168673143b9aSmrg		PRMSG (1,"SocketINETConnect: can't get service for %s\n",
168773143b9aSmrg			port, 0, 0);
168873143b9aSmrg		return TRANS_CONNECT_FAILED;
168973143b9aSmrg	    }
169073143b9aSmrg	    sockname.sin_port = htons (servp->s_port);
169173143b9aSmrg	} else {
169273143b9aSmrg	    tmpport = strtol (port, (char**)NULL, 10);
169373143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
169473143b9aSmrg		return TRANS_CONNECT_FAILED;
169573143b9aSmrg	    sockname.sin_port = htons (((unsigned short) tmpport));
169673143b9aSmrg	}
169773143b9aSmrg
169873143b9aSmrg	PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
169973143b9aSmrg		ntohs(sockname.sin_port), 0, 0);
170073143b9aSmrg	socketaddr = (struct sockaddr *) &sockname;
170173143b9aSmrg	socketaddrlen = sizeof(sockname);
170273143b9aSmrg    }
170373143b9aSmrg
170473143b9aSmrg    /*
170573143b9aSmrg     * Turn on socket keepalive so the client process will eventually
170673143b9aSmrg     * be notified with a SIGPIPE signal if the display server fails
170773143b9aSmrg     * to respond to a periodic transmission of messages
170873143b9aSmrg     * on the connected socket.
170973143b9aSmrg     * This is useful to avoid hung application processes when the
171073143b9aSmrg     * processes are not spawned from the xdm session and
171173143b9aSmrg     * the display server terminates abnormally.
171273143b9aSmrg     * (Someone turned off the power switch.)
171373143b9aSmrg     */
171473143b9aSmrg
171573143b9aSmrg    {
171673143b9aSmrg	int tmp = 1;
171773143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
171873143b9aSmrg		(char *) &tmp, sizeof (int));
171973143b9aSmrg    }
172073143b9aSmrg
172173143b9aSmrg    /*
172273143b9aSmrg     * Do the connect()
172373143b9aSmrg     */
172473143b9aSmrg
172573143b9aSmrg    if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
172673143b9aSmrg    {
172773143b9aSmrg#ifdef WIN32
172873143b9aSmrg	int olderrno = WSAGetLastError();
172973143b9aSmrg#else
173073143b9aSmrg	int olderrno = errno;
173173143b9aSmrg#endif
173273143b9aSmrg
173373143b9aSmrg	/*
173473143b9aSmrg	 * If the error was ECONNREFUSED, the server may be overloaded
173573143b9aSmrg	 * and we should try again.
173673143b9aSmrg	 *
173773143b9aSmrg	 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
173873143b9aSmrg	 * was non-blocking and we should poll using select
173973143b9aSmrg	 *
174073143b9aSmrg	 * If the error was EINTR, the connect was interrupted and we
174173143b9aSmrg	 * should try again.
174273143b9aSmrg	 *
174373143b9aSmrg	 * If multiple addresses are found for a host then we should
174473143b9aSmrg	 * try to connect again with a different address for a larger
174573143b9aSmrg	 * number of errors that made us quit before, since those
174673143b9aSmrg	 * could be caused by trying to use an IPv6 address to contact
174773143b9aSmrg	 * a machine with an IPv4-only server or other reasons that
174873143b9aSmrg	 * only affect one of a set of addresses.
174973143b9aSmrg	 */
175073143b9aSmrg
175173143b9aSmrg	if (olderrno == ECONNREFUSED || olderrno == EINTR
175273143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
175373143b9aSmrg	  || (haveIPv6 && ((addrlist->addr->ai_next != NULL) ||
175473143b9aSmrg	        (addrlist->addr != addrlist->firstaddr)) &&
175573143b9aSmrg               (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
175673143b9aSmrg		 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
175773143b9aSmrg#if defined(EHOSTDOWN)
175873143b9aSmrg		   || olderrno == EHOSTDOWN
175973143b9aSmrg#endif
176073143b9aSmrg	       ))
176173143b9aSmrg#endif
176273143b9aSmrg	    )
176373143b9aSmrg	    res = TRANS_TRY_CONNECT_AGAIN;
176473143b9aSmrg	else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
176573143b9aSmrg	    res = TRANS_IN_PROGRESS;
176673143b9aSmrg	else
176773143b9aSmrg	{
176873143b9aSmrg	    PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
176973143b9aSmrg		   olderrno,0, 0);
177073143b9aSmrg
177173143b9aSmrg	    res = TRANS_CONNECT_FAILED;
177273143b9aSmrg	}
177373143b9aSmrg    } else {
177473143b9aSmrg	res = 0;
177573143b9aSmrg
177673143b9aSmrg
177773143b9aSmrg	/*
177873143b9aSmrg	 * Sync up the address fields of ciptr.
177973143b9aSmrg	 */
178073143b9aSmrg
178173143b9aSmrg	if (TRANS(SocketINETGetAddr) (ciptr) < 0)
178273143b9aSmrg	{
178373143b9aSmrg	    PRMSG (1,
178473143b9aSmrg	     "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
178573143b9aSmrg	      0, 0, 0);
178673143b9aSmrg	    res = TRANS_CONNECT_FAILED;
178773143b9aSmrg	}
178873143b9aSmrg
178973143b9aSmrg	else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
179073143b9aSmrg	{
179173143b9aSmrg	    PRMSG (1,
179273143b9aSmrg	      "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
179373143b9aSmrg	      0, 0, 0);
179473143b9aSmrg	    res = TRANS_CONNECT_FAILED;
179573143b9aSmrg	}
179673143b9aSmrg    }
179773143b9aSmrg
179873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
179973143b9aSmrg   if (haveIPv6 && res != 0) {
180073143b9aSmrg	addrlist->addr = addrlist->addr->ai_next;
180173143b9aSmrg   }
180273143b9aSmrg#endif
180373143b9aSmrg
180473143b9aSmrg    return res;
180573143b9aSmrg}
180673143b9aSmrg
180773143b9aSmrg#endif /* TCPCONN */
180873143b9aSmrg
180973143b9aSmrg
181073143b9aSmrg
181173143b9aSmrg#ifdef UNIXCONN
181273143b9aSmrg
181373143b9aSmrg/*
181473143b9aSmrg * Make sure 'host' is really local.
181573143b9aSmrg */
181673143b9aSmrg
181773143b9aSmrgstatic int
181873143b9aSmrgUnixHostReallyLocal (char *host)
181973143b9aSmrg
182073143b9aSmrg{
182173143b9aSmrg    char hostnamebuf[256];
182273143b9aSmrg
182373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
182473143b9aSmrg    if (getaddrinfo == NULL)
182573143b9aSmrg	haveIPv6 = 0;
182673143b9aSmrg#endif
182773143b9aSmrg
182873143b9aSmrg    TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
182973143b9aSmrg
183073143b9aSmrg    if (strcmp (hostnamebuf, host) == 0)
183173143b9aSmrg    {
183273143b9aSmrg	return (1);
183373143b9aSmrg    }
183473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
183573143b9aSmrg    else if (haveIPv6)
183673143b9aSmrg    {
183773143b9aSmrg	struct addrinfo *localhostaddr;
183873143b9aSmrg	struct addrinfo *otherhostaddr;
183973143b9aSmrg	struct addrinfo *i, *j;
184073143b9aSmrg	int equiv = 0;
184173143b9aSmrg
184273143b9aSmrg	if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
184373143b9aSmrg	    return 0;
184473143b9aSmrg	if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
184573143b9aSmrg	    freeaddrinfo(localhostaddr);
184673143b9aSmrg	    return 0;
184773143b9aSmrg	}
184873143b9aSmrg
184973143b9aSmrg	for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
185073143b9aSmrg	    for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
185173143b9aSmrg		if (i->ai_family == j->ai_family) {
185273143b9aSmrg		    if (i->ai_family == AF_INET) {
185373143b9aSmrg			struct sockaddr_in *sinA
185473143b9aSmrg			  = (struct sockaddr_in *) i->ai_addr;
185573143b9aSmrg			struct sockaddr_in *sinB
185673143b9aSmrg			  = (struct sockaddr_in *) j->ai_addr;
185773143b9aSmrg			struct in_addr *A = &sinA->sin_addr;
185873143b9aSmrg			struct in_addr *B = &sinB->sin_addr;
185973143b9aSmrg
186073143b9aSmrg			if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
186173143b9aSmrg			    equiv = 1;
186273143b9aSmrg			}
186373143b9aSmrg		    } else if (i->ai_family == AF_INET6) {
186473143b9aSmrg			struct sockaddr_in6 *sinA
186573143b9aSmrg			  = (struct sockaddr_in6 *) i->ai_addr;
186673143b9aSmrg			struct sockaddr_in6 *sinB
186773143b9aSmrg			  = (struct sockaddr_in6 *) j->ai_addr;
186873143b9aSmrg			struct in6_addr *A = &sinA->sin6_addr;
186973143b9aSmrg			struct in6_addr *B = &sinB->sin6_addr;
187073143b9aSmrg
187173143b9aSmrg			if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
187273143b9aSmrg			    equiv = 1;
187373143b9aSmrg			}
187473143b9aSmrg		    }
187573143b9aSmrg		}
187673143b9aSmrg	    }
187773143b9aSmrg	}
187873143b9aSmrg
187973143b9aSmrg	freeaddrinfo(localhostaddr);
188073143b9aSmrg	freeaddrinfo(otherhostaddr);
188173143b9aSmrg	return equiv;
188273143b9aSmrg    }
188373143b9aSmrg#endif
188473143b9aSmrg    else
188573143b9aSmrg    {
188673143b9aSmrg	/*
188773143b9aSmrg	 * A host may have more than one network address.  If any of the
188873143b9aSmrg	 * network addresses of 'host' (specified to the connect call)
188973143b9aSmrg	 * match any of the network addresses of 'hostname' (determined
189073143b9aSmrg	 * by TRANS(GetHostname)), then the two hostnames are equivalent,
189173143b9aSmrg	 * and we know that 'host' is really a local host.
189273143b9aSmrg	 */
189373143b9aSmrg	char specified_local_addr_list[10][4];
189473143b9aSmrg	int scount, equiv, i, j;
189573143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
189673143b9aSmrg	_Xgethostbynameparams hparams;
189773143b9aSmrg#endif
189873143b9aSmrg	struct hostent *hostp;
189973143b9aSmrg
190073143b9aSmrg	if ((hostp = _XGethostbyname (host,hparams)) == NULL)
190173143b9aSmrg	    return (0);
190273143b9aSmrg
190373143b9aSmrg	scount = 0;
190473143b9aSmrg	while (hostp->h_addr_list[scount] && scount <= 8)
190573143b9aSmrg	{
190673143b9aSmrg	    /*
190773143b9aSmrg	     * The 2nd call to gethostname() overrides the data
190873143b9aSmrg	     * from the 1st call, so we must save the address list.
190973143b9aSmrg	     */
191073143b9aSmrg
191173143b9aSmrg	    specified_local_addr_list[scount][0] =
191273143b9aSmrg				hostp->h_addr_list[scount][0];
191373143b9aSmrg	    specified_local_addr_list[scount][1] =
191473143b9aSmrg				hostp->h_addr_list[scount][1];
191573143b9aSmrg	    specified_local_addr_list[scount][2] =
191673143b9aSmrg				hostp->h_addr_list[scount][2];
191773143b9aSmrg	    specified_local_addr_list[scount][3] =
191873143b9aSmrg				hostp->h_addr_list[scount][3];
191973143b9aSmrg	    scount++;
192073143b9aSmrg	}
192173143b9aSmrg	if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
192273143b9aSmrg	    return (0);
192373143b9aSmrg
192473143b9aSmrg	equiv = 0;
192573143b9aSmrg	i = 0;
192673143b9aSmrg
192773143b9aSmrg	while (i < scount && !equiv)
192873143b9aSmrg	{
192973143b9aSmrg	    j = 0;
193073143b9aSmrg
193173143b9aSmrg	    while (hostp->h_addr_list[j])
193273143b9aSmrg	    {
193373143b9aSmrg		if ((specified_local_addr_list[i][0] ==
193473143b9aSmrg					hostp->h_addr_list[j][0]) &&
193573143b9aSmrg		    (specified_local_addr_list[i][1] ==
193673143b9aSmrg					hostp->h_addr_list[j][1]) &&
193773143b9aSmrg		    (specified_local_addr_list[i][2] ==
193873143b9aSmrg					hostp->h_addr_list[j][2]) &&
193973143b9aSmrg		    (specified_local_addr_list[i][3] ==
194073143b9aSmrg					hostp->h_addr_list[j][3]))
194173143b9aSmrg		{
194273143b9aSmrg		    /* They're equal, so we're done */
194373143b9aSmrg
194473143b9aSmrg		    equiv = 1;
194573143b9aSmrg		    break;
194673143b9aSmrg		}
194773143b9aSmrg
194873143b9aSmrg		j++;
194973143b9aSmrg	    }
195073143b9aSmrg
195173143b9aSmrg	    i++;
195273143b9aSmrg	}
195373143b9aSmrg	return (equiv);
195473143b9aSmrg    }
195573143b9aSmrg}
195673143b9aSmrg
195773143b9aSmrgstatic int
195873143b9aSmrgTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
195973143b9aSmrg
196073143b9aSmrg{
196173143b9aSmrg    struct sockaddr_un	sockname;
196273143b9aSmrg    SOCKLEN_T		namelen;
196373143b9aSmrg
196473143b9aSmrg
196573143b9aSmrg    int abstract = 0;
196673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
196773143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
196873143b9aSmrg#endif
196973143b9aSmrg
197073143b9aSmrg    PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
197173143b9aSmrg
197273143b9aSmrg    /*
197373143b9aSmrg     * Make sure 'host' is really local.  If not, we return failure.
197473143b9aSmrg     * The reason we make this check is because a process may advertise
197573143b9aSmrg     * a "local" network ID for which it can accept connections, but if
197673143b9aSmrg     * a process on a remote machine tries to connect to this network ID,
197773143b9aSmrg     * we know for sure it will fail.
197873143b9aSmrg     */
197973143b9aSmrg
198073143b9aSmrg    if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
198173143b9aSmrg    {
198273143b9aSmrg	PRMSG (1,
198373143b9aSmrg	   "SocketUNIXConnect: Cannot connect to non-local host %s\n",
198473143b9aSmrg	       host, 0, 0);
198573143b9aSmrg	return TRANS_CONNECT_FAILED;
198673143b9aSmrg    }
198773143b9aSmrg
198873143b9aSmrg
198973143b9aSmrg    /*
199073143b9aSmrg     * Check the port.
199173143b9aSmrg     */
199273143b9aSmrg
199373143b9aSmrg    if (!port || !*port)
199473143b9aSmrg    {
199573143b9aSmrg	PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
199673143b9aSmrg	      0, 0, 0);
199773143b9aSmrg	return TRANS_CONNECT_FAILED;
199873143b9aSmrg    }
199973143b9aSmrg
200073143b9aSmrg    /*
200173143b9aSmrg     * Build the socket name.
200273143b9aSmrg     */
200373143b9aSmrg
200473143b9aSmrg    sockname.sun_family = AF_UNIX;
200573143b9aSmrg
200673143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
200773143b9aSmrg	PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
200873143b9aSmrg	return TRANS_CONNECT_FAILED;
200973143b9aSmrg    }
201073143b9aSmrg
20118d4c0f7bSmrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
201273143b9aSmrg    sockname.sun_len = strlen (sockname.sun_path);
201373143b9aSmrg#endif
201473143b9aSmrg
201573143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
201673143b9aSmrg    namelen = SUN_LEN (&sockname);
201773143b9aSmrg#else
201873143b9aSmrg    namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
201973143b9aSmrg#endif
202073143b9aSmrg
202173143b9aSmrg
202273143b9aSmrg
202373143b9aSmrg    /*
202473143b9aSmrg     * Adjust the socket path if using abstract sockets.
202573143b9aSmrg     * Done here because otherwise all the strlen() calls above would fail.
202673143b9aSmrg     */
202773143b9aSmrg
202873143b9aSmrg    if (abstract) {
202973143b9aSmrg	sockname.sun_path[0] = '\0';
203073143b9aSmrg    }
203173143b9aSmrg
203273143b9aSmrg    /*
203373143b9aSmrg     * Do the connect()
203473143b9aSmrg     */
203573143b9aSmrg
203673143b9aSmrg    if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
203773143b9aSmrg    {
203873143b9aSmrg	int olderrno = errno;
203973143b9aSmrg	int connected = 0;
204073143b9aSmrg
204173143b9aSmrg	if (!connected)
204273143b9aSmrg	{
204373143b9aSmrg	    errno = olderrno;
204473143b9aSmrg
204573143b9aSmrg	    /*
204673143b9aSmrg	     * If the error was ENOENT, the server may be starting up; we used
204773143b9aSmrg	     * to suggest to try again in this case with
204873143b9aSmrg	     * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
204973143b9aSmrg	     * processes still referencing stale sockets in their environment.
205073143b9aSmrg	     * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
205173143b9aSmrg	     * is suggested that higher level stacks handle retries on their
205273143b9aSmrg	     * level when they face a slow starting server.
205373143b9aSmrg	     *
205473143b9aSmrg	     * If the error was EWOULDBLOCK or EINPROGRESS then the socket
205573143b9aSmrg	     * was non-blocking and we should poll using select
205673143b9aSmrg	     *
205773143b9aSmrg	     * If the error was EINTR, the connect was interrupted and we
205873143b9aSmrg	     * should try again.
205973143b9aSmrg	     */
206073143b9aSmrg
206173143b9aSmrg	    if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
206273143b9aSmrg		return TRANS_IN_PROGRESS;
206373143b9aSmrg	    else if (olderrno == EINTR)
206473143b9aSmrg		return TRANS_TRY_CONNECT_AGAIN;
20658d4c0f7bSmrg	    else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
206673143b9aSmrg		/* If opening as abstract socket failed, try again normally */
206773143b9aSmrg		if (abstract) {
206873143b9aSmrg		    ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
206973143b9aSmrg		    return TRANS_TRY_CONNECT_AGAIN;
207073143b9aSmrg		} else {
207173143b9aSmrg		    return TRANS_CONNECT_FAILED;
207273143b9aSmrg		}
207373143b9aSmrg	    } else {
207473143b9aSmrg		PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
207573143b9aSmrg		       EGET(),0, 0);
207673143b9aSmrg
207773143b9aSmrg		return TRANS_CONNECT_FAILED;
207873143b9aSmrg	    }
207973143b9aSmrg	}
208073143b9aSmrg    }
208173143b9aSmrg
208273143b9aSmrg    /*
208373143b9aSmrg     * Get the socket name and the peer name from the connect socket,
208473143b9aSmrg     * since this is unix domain.
208573143b9aSmrg     */
208673143b9aSmrg
208773143b9aSmrg    if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
208873143b9aSmrg       (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
208973143b9aSmrg    {
209073143b9aSmrg        PRMSG (1,
209173143b9aSmrg	"SocketUNIXCreateListener: Can't allocate space for the addr\n",
209273143b9aSmrg	      0, 0, 0);
209373143b9aSmrg        return TRANS_CONNECT_FAILED;
209473143b9aSmrg    }
209573143b9aSmrg
209673143b9aSmrg    if (abstract)
209773143b9aSmrg	sockname.sun_path[0] = '@';
209873143b9aSmrg
209973143b9aSmrg    ciptr->family = AF_UNIX;
210073143b9aSmrg    ciptr->addrlen = namelen;
210173143b9aSmrg    ciptr->peeraddrlen = namelen;
210273143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
210373143b9aSmrg    memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
210473143b9aSmrg
210573143b9aSmrg    return 0;
210673143b9aSmrg}
210773143b9aSmrg
210873143b9aSmrg#endif /* UNIXCONN */
210973143b9aSmrg
211073143b9aSmrg#endif /* TRANS_CLIENT */
211173143b9aSmrg
211273143b9aSmrg
211373143b9aSmrgstatic int
211473143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
211573143b9aSmrg
211673143b9aSmrg{
211773143b9aSmrg    PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
211873143b9aSmrg	ciptr, ciptr->fd, pend);
211973143b9aSmrg#ifdef WIN32
212073143b9aSmrg    {
212173143b9aSmrg	int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
212273143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
212373143b9aSmrg	return ret;
212473143b9aSmrg    }
212573143b9aSmrg#else
21268d4c0f7bSmrg#if defined(__i386__) && defined(SYSV) && !defined(SCO325)
212773143b9aSmrg    return ioctl (ciptr->fd, I_NREAD, (char *) pend);
212873143b9aSmrg#else
212973143b9aSmrg    return ioctl (ciptr->fd, FIONREAD, (char *) pend);
213073143b9aSmrg#endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
213173143b9aSmrg#endif /* WIN32 */
213273143b9aSmrg}
213373143b9aSmrg
213473143b9aSmrg
213573143b9aSmrgstatic int
213673143b9aSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
213773143b9aSmrg
213873143b9aSmrg{
213973143b9aSmrg    PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
214073143b9aSmrg
21418d4c0f7bSmrg#if defined(WIN32)
214273143b9aSmrg    {
214373143b9aSmrg	int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
214473143b9aSmrg#ifdef WIN32
214573143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
214673143b9aSmrg#endif
214773143b9aSmrg	return ret;
214873143b9aSmrg    }
214973143b9aSmrg#else
215073143b9aSmrg    return read (ciptr->fd, buf, size);
215173143b9aSmrg#endif /* WIN32 */
215273143b9aSmrg}
215373143b9aSmrg
215473143b9aSmrg
215573143b9aSmrgstatic int
215673143b9aSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
215773143b9aSmrg
215873143b9aSmrg{
215973143b9aSmrg    PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
216073143b9aSmrg
21618d4c0f7bSmrg#if defined(WIN32)
216273143b9aSmrg    {
216373143b9aSmrg	int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
216473143b9aSmrg#ifdef WIN32
216573143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
216673143b9aSmrg#endif
216773143b9aSmrg	return ret;
216873143b9aSmrg    }
216973143b9aSmrg#else
217073143b9aSmrg    return write (ciptr->fd, buf, size);
217173143b9aSmrg#endif /* WIN32 */
217273143b9aSmrg}
217373143b9aSmrg
217473143b9aSmrg
217573143b9aSmrgstatic int
217673143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
217773143b9aSmrg
217873143b9aSmrg{
217973143b9aSmrg    PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
218073143b9aSmrg
218173143b9aSmrg    return READV (ciptr, buf, size);
218273143b9aSmrg}
218373143b9aSmrg
218473143b9aSmrg
218573143b9aSmrgstatic int
218673143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
218773143b9aSmrg
218873143b9aSmrg{
218973143b9aSmrg    PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
219073143b9aSmrg
219173143b9aSmrg    return WRITEV (ciptr, buf, size);
219273143b9aSmrg}
219373143b9aSmrg
219473143b9aSmrg
219573143b9aSmrgstatic int
219673143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr)
219773143b9aSmrg
219873143b9aSmrg{
219973143b9aSmrg    PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
220073143b9aSmrg
220173143b9aSmrg#ifdef WIN32
220273143b9aSmrg    {
220373143b9aSmrg	int ret = shutdown (ciptr->fd, 2);
220473143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
220573143b9aSmrg	return ret;
220673143b9aSmrg    }
220773143b9aSmrg#else
220873143b9aSmrg    return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
220973143b9aSmrg#endif
221073143b9aSmrg}
221173143b9aSmrg
221273143b9aSmrg
221373143b9aSmrg#ifdef TCPCONN
221473143b9aSmrgstatic int
221573143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr)
221673143b9aSmrg
221773143b9aSmrg{
221873143b9aSmrg    PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
221973143b9aSmrg
222073143b9aSmrg#ifdef WIN32
222173143b9aSmrg    {
222273143b9aSmrg	int ret = close (ciptr->fd);
222373143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
222473143b9aSmrg	return ret;
222573143b9aSmrg    }
222673143b9aSmrg#else
222773143b9aSmrg    return close (ciptr->fd);
222873143b9aSmrg#endif
222973143b9aSmrg}
223073143b9aSmrg
223173143b9aSmrg#endif /* TCPCONN */
223273143b9aSmrg
223373143b9aSmrg
223473143b9aSmrg#ifdef UNIXCONN
223573143b9aSmrgstatic int
223673143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr)
223773143b9aSmrg{
223873143b9aSmrg    /*
223973143b9aSmrg     * If this is the server side, then once the socket is closed,
224073143b9aSmrg     * it must be unlinked to completely close it
224173143b9aSmrg     */
224273143b9aSmrg
224373143b9aSmrg    struct sockaddr_un	*sockname = (struct sockaddr_un *) ciptr->addr;
224473143b9aSmrg    int ret;
224573143b9aSmrg
224673143b9aSmrg    PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
224773143b9aSmrg
224873143b9aSmrg    ret = close(ciptr->fd);
224973143b9aSmrg
225073143b9aSmrg    if (ciptr->flags
225173143b9aSmrg       && sockname
225273143b9aSmrg       && sockname->sun_family == AF_UNIX
225373143b9aSmrg       && sockname->sun_path[0])
225473143b9aSmrg    {
225573143b9aSmrg	if (!(ciptr->flags & TRANS_NOUNLINK
225673143b9aSmrg	    || ciptr->transptr->flags & TRANS_ABSTRACT))
225773143b9aSmrg		unlink (sockname->sun_path);
225873143b9aSmrg    }
225973143b9aSmrg
226073143b9aSmrg    return ret;
226173143b9aSmrg}
226273143b9aSmrg
226373143b9aSmrgstatic int
226473143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
226573143b9aSmrg
226673143b9aSmrg{
226773143b9aSmrg    /*
226873143b9aSmrg     * Don't unlink path.
226973143b9aSmrg     */
227073143b9aSmrg
227173143b9aSmrg    int ret;
227273143b9aSmrg
227373143b9aSmrg    PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
227473143b9aSmrg	ciptr, ciptr->fd, 0);
227573143b9aSmrg
227673143b9aSmrg    ret = close(ciptr->fd);
227773143b9aSmrg
227873143b9aSmrg    return ret;
227973143b9aSmrg}
228073143b9aSmrg
228173143b9aSmrg#endif /* UNIXCONN */
228273143b9aSmrg
228373143b9aSmrg
228473143b9aSmrg#ifdef TCPCONN
228573143b9aSmrg# ifdef TRANS_SERVER
228673143b9aSmrgstatic char* tcp_nolisten[] = {
228773143b9aSmrg	"inet",
228873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
228973143b9aSmrg	"inet6",
229073143b9aSmrg#endif
229173143b9aSmrg	NULL
229273143b9aSmrg};
229373143b9aSmrg# endif
229473143b9aSmrg
229573143b9aSmrgXtransport	TRANS(SocketTCPFuncs) = {
229673143b9aSmrg	/* Socket Interface */
229773143b9aSmrg	"tcp",
229873143b9aSmrg        TRANS_ALIAS,
229973143b9aSmrg#ifdef TRANS_CLIENT
230073143b9aSmrg	TRANS(SocketOpenCOTSClient),
230173143b9aSmrg#endif /* TRANS_CLIENT */
230273143b9aSmrg#ifdef TRANS_SERVER
230373143b9aSmrg	tcp_nolisten,
230473143b9aSmrg	TRANS(SocketOpenCOTSServer),
230573143b9aSmrg#endif /* TRANS_SERVER */
230673143b9aSmrg#ifdef TRANS_CLIENT
230773143b9aSmrg	TRANS(SocketOpenCLTSClient),
230873143b9aSmrg#endif /* TRANS_CLIENT */
230973143b9aSmrg#ifdef TRANS_SERVER
231073143b9aSmrg	TRANS(SocketOpenCLTSServer),
231173143b9aSmrg#endif /* TRANS_SERVER */
231273143b9aSmrg#ifdef TRANS_REOPEN
231373143b9aSmrg	TRANS(SocketReopenCOTSServer),
231473143b9aSmrg	TRANS(SocketReopenCLTSServer),
231573143b9aSmrg#endif
231673143b9aSmrg	TRANS(SocketSetOption),
231773143b9aSmrg#ifdef TRANS_SERVER
231873143b9aSmrg	TRANS(SocketINETCreateListener),
231973143b9aSmrg	NULL,		       			/* ResetListener */
232073143b9aSmrg	TRANS(SocketINETAccept),
232173143b9aSmrg#endif /* TRANS_SERVER */
232273143b9aSmrg#ifdef TRANS_CLIENT
232373143b9aSmrg	TRANS(SocketINETConnect),
232473143b9aSmrg#endif /* TRANS_CLIENT */
232573143b9aSmrg	TRANS(SocketBytesReadable),
232673143b9aSmrg	TRANS(SocketRead),
232773143b9aSmrg	TRANS(SocketWrite),
232873143b9aSmrg	TRANS(SocketReadv),
232973143b9aSmrg	TRANS(SocketWritev),
233073143b9aSmrg	TRANS(SocketDisconnect),
233173143b9aSmrg	TRANS(SocketINETClose),
233273143b9aSmrg	TRANS(SocketINETClose),
233373143b9aSmrg	};
233473143b9aSmrg
233573143b9aSmrgXtransport	TRANS(SocketINETFuncs) = {
233673143b9aSmrg	/* Socket Interface */
233773143b9aSmrg	"inet",
233873143b9aSmrg	0,
233973143b9aSmrg#ifdef TRANS_CLIENT
234073143b9aSmrg	TRANS(SocketOpenCOTSClient),
234173143b9aSmrg#endif /* TRANS_CLIENT */
234273143b9aSmrg#ifdef TRANS_SERVER
234373143b9aSmrg	NULL,
234473143b9aSmrg	TRANS(SocketOpenCOTSServer),
234573143b9aSmrg#endif /* TRANS_SERVER */
234673143b9aSmrg#ifdef TRANS_CLIENT
234773143b9aSmrg	TRANS(SocketOpenCLTSClient),
234873143b9aSmrg#endif /* TRANS_CLIENT */
234973143b9aSmrg#ifdef TRANS_SERVER
235073143b9aSmrg	TRANS(SocketOpenCLTSServer),
235173143b9aSmrg#endif /* TRANS_SERVER */
235273143b9aSmrg#ifdef TRANS_REOPEN
235373143b9aSmrg	TRANS(SocketReopenCOTSServer),
235473143b9aSmrg	TRANS(SocketReopenCLTSServer),
235573143b9aSmrg#endif
235673143b9aSmrg	TRANS(SocketSetOption),
235773143b9aSmrg#ifdef TRANS_SERVER
235873143b9aSmrg	TRANS(SocketINETCreateListener),
235973143b9aSmrg	NULL,		       			/* ResetListener */
236073143b9aSmrg	TRANS(SocketINETAccept),
236173143b9aSmrg#endif /* TRANS_SERVER */
236273143b9aSmrg#ifdef TRANS_CLIENT
236373143b9aSmrg	TRANS(SocketINETConnect),
236473143b9aSmrg#endif /* TRANS_CLIENT */
236573143b9aSmrg	TRANS(SocketBytesReadable),
236673143b9aSmrg	TRANS(SocketRead),
236773143b9aSmrg	TRANS(SocketWrite),
236873143b9aSmrg	TRANS(SocketReadv),
236973143b9aSmrg	TRANS(SocketWritev),
237073143b9aSmrg	TRANS(SocketDisconnect),
237173143b9aSmrg	TRANS(SocketINETClose),
237273143b9aSmrg	TRANS(SocketINETClose),
237373143b9aSmrg	};
237473143b9aSmrg
237573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
237673143b9aSmrgXtransport     TRANS(SocketINET6Funcs) = {
237773143b9aSmrg	/* Socket Interface */
237873143b9aSmrg	"inet6",
237973143b9aSmrg	0,
238073143b9aSmrg#ifdef TRANS_CLIENT
238173143b9aSmrg	TRANS(SocketOpenCOTSClient),
238273143b9aSmrg#endif /* TRANS_CLIENT */
238373143b9aSmrg#ifdef TRANS_SERVER
238473143b9aSmrg	NULL,
238573143b9aSmrg	TRANS(SocketOpenCOTSServer),
238673143b9aSmrg#endif /* TRANS_SERVER */
238773143b9aSmrg#ifdef TRANS_CLIENT
238873143b9aSmrg	TRANS(SocketOpenCLTSClient),
238973143b9aSmrg#endif /* TRANS_CLIENT */
239073143b9aSmrg#ifdef TRANS_SERVER
239173143b9aSmrg	TRANS(SocketOpenCLTSServer),
239273143b9aSmrg#endif /* TRANS_SERVER */
239373143b9aSmrg#ifdef TRANS_REOPEN
239473143b9aSmrg	TRANS(SocketReopenCOTSServer),
239573143b9aSmrg	TRANS(SocketReopenCLTSServer),
239673143b9aSmrg#endif
239773143b9aSmrg	TRANS(SocketSetOption),
239873143b9aSmrg#ifdef TRANS_SERVER
239973143b9aSmrg	TRANS(SocketINETCreateListener),
240073143b9aSmrg	NULL,					/* ResetListener */
240173143b9aSmrg	TRANS(SocketINETAccept),
240273143b9aSmrg#endif /* TRANS_SERVER */
240373143b9aSmrg#ifdef TRANS_CLIENT
240473143b9aSmrg	TRANS(SocketINETConnect),
240573143b9aSmrg#endif /* TRANS_CLIENT */
240673143b9aSmrg	TRANS(SocketBytesReadable),
240773143b9aSmrg	TRANS(SocketRead),
240873143b9aSmrg	TRANS(SocketWrite),
240973143b9aSmrg	TRANS(SocketReadv),
241073143b9aSmrg	TRANS(SocketWritev),
241173143b9aSmrg	TRANS(SocketDisconnect),
241273143b9aSmrg	TRANS(SocketINETClose),
241373143b9aSmrg	TRANS(SocketINETClose),
241473143b9aSmrg	};
241573143b9aSmrg#endif /* IPv6 */
241673143b9aSmrg#endif /* TCPCONN */
241773143b9aSmrg
241873143b9aSmrg#ifdef UNIXCONN
241973143b9aSmrg#if !defined(LOCALCONN)
242073143b9aSmrgXtransport	TRANS(SocketLocalFuncs) = {
242173143b9aSmrg	/* Socket Interface */
242273143b9aSmrg	"local",
242373143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
242473143b9aSmrg	TRANS_ABSTRACT,
242573143b9aSmrg#else
242673143b9aSmrg	0,
242773143b9aSmrg#endif
242873143b9aSmrg#ifdef TRANS_CLIENT
242973143b9aSmrg	TRANS(SocketOpenCOTSClient),
243073143b9aSmrg#endif /* TRANS_CLIENT */
243173143b9aSmrg#ifdef TRANS_SERVER
243273143b9aSmrg	NULL,
243373143b9aSmrg	TRANS(SocketOpenCOTSServer),
243473143b9aSmrg#endif /* TRANS_SERVER */
243573143b9aSmrg#ifdef TRANS_CLIENT
243673143b9aSmrg	TRANS(SocketOpenCLTSClient),
243773143b9aSmrg#endif /* TRANS_CLIENT */
243873143b9aSmrg#ifdef TRANS_SERVER
243973143b9aSmrg	TRANS(SocketOpenCLTSServer),
244073143b9aSmrg#endif /* TRANS_SERVER */
244173143b9aSmrg#ifdef TRANS_REOPEN
244273143b9aSmrg	TRANS(SocketReopenCOTSServer),
244373143b9aSmrg	TRANS(SocketReopenCLTSServer),
244473143b9aSmrg#endif
244573143b9aSmrg	TRANS(SocketSetOption),
244673143b9aSmrg#ifdef TRANS_SERVER
244773143b9aSmrg	TRANS(SocketUNIXCreateListener),
244873143b9aSmrg	TRANS(SocketUNIXResetListener),
244973143b9aSmrg	TRANS(SocketUNIXAccept),
245073143b9aSmrg#endif /* TRANS_SERVER */
245173143b9aSmrg#ifdef TRANS_CLIENT
245273143b9aSmrg	TRANS(SocketUNIXConnect),
245373143b9aSmrg#endif /* TRANS_CLIENT */
245473143b9aSmrg	TRANS(SocketBytesReadable),
245573143b9aSmrg	TRANS(SocketRead),
245673143b9aSmrg	TRANS(SocketWrite),
245773143b9aSmrg	TRANS(SocketReadv),
245873143b9aSmrg	TRANS(SocketWritev),
245973143b9aSmrg	TRANS(SocketDisconnect),
246073143b9aSmrg	TRANS(SocketUNIXClose),
246173143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
246273143b9aSmrg	};
246373143b9aSmrg#endif /* !LOCALCONN */
246473143b9aSmrg# ifdef TRANS_SERVER
246573143b9aSmrg#  if !defined(LOCALCONN)
246673143b9aSmrgstatic char* unix_nolisten[] = { "local" , NULL };
246773143b9aSmrg#  endif
246873143b9aSmrg# endif
246973143b9aSmrg
247073143b9aSmrgXtransport	TRANS(SocketUNIXFuncs) = {
247173143b9aSmrg	/* Socket Interface */
247273143b9aSmrg	"unix",
247373143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
247473143b9aSmrg        TRANS_ALIAS,
247573143b9aSmrg#else
247673143b9aSmrg	0,
247773143b9aSmrg#endif
247873143b9aSmrg#ifdef TRANS_CLIENT
247973143b9aSmrg	TRANS(SocketOpenCOTSClient),
248073143b9aSmrg#endif /* TRANS_CLIENT */
248173143b9aSmrg#ifdef TRANS_SERVER
248273143b9aSmrg#if !defined(LOCALCONN)
248373143b9aSmrg	unix_nolisten,
248473143b9aSmrg#else
248573143b9aSmrg	NULL,
248673143b9aSmrg#endif
248773143b9aSmrg	TRANS(SocketOpenCOTSServer),
248873143b9aSmrg#endif /* TRANS_SERVER */
248973143b9aSmrg#ifdef TRANS_CLIENT
249073143b9aSmrg	TRANS(SocketOpenCLTSClient),
249173143b9aSmrg#endif /* TRANS_CLIENT */
249273143b9aSmrg#ifdef TRANS_SERVER
249373143b9aSmrg	TRANS(SocketOpenCLTSServer),
249473143b9aSmrg#endif /* TRANS_SERVER */
249573143b9aSmrg#ifdef TRANS_REOPEN
249673143b9aSmrg	TRANS(SocketReopenCOTSServer),
249773143b9aSmrg	TRANS(SocketReopenCLTSServer),
249873143b9aSmrg#endif
249973143b9aSmrg	TRANS(SocketSetOption),
250073143b9aSmrg#ifdef TRANS_SERVER
250173143b9aSmrg	TRANS(SocketUNIXCreateListener),
250273143b9aSmrg	TRANS(SocketUNIXResetListener),
250373143b9aSmrg	TRANS(SocketUNIXAccept),
250473143b9aSmrg#endif /* TRANS_SERVER */
250573143b9aSmrg#ifdef TRANS_CLIENT
250673143b9aSmrg	TRANS(SocketUNIXConnect),
250773143b9aSmrg#endif /* TRANS_CLIENT */
250873143b9aSmrg	TRANS(SocketBytesReadable),
250973143b9aSmrg	TRANS(SocketRead),
251073143b9aSmrg	TRANS(SocketWrite),
251173143b9aSmrg	TRANS(SocketReadv),
251273143b9aSmrg	TRANS(SocketWritev),
251373143b9aSmrg	TRANS(SocketDisconnect),
251473143b9aSmrg	TRANS(SocketUNIXClose),
251573143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
251673143b9aSmrg	};
251773143b9aSmrg
251873143b9aSmrg#endif /* UNIXCONN */
2519