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