Xtranssock.c revision fe567363
1af928962Smrg/*
2af928962Smrg * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
3af928962Smrg *
4af928962Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5af928962Smrg * copy of this software and associated documentation files (the "Software"),
6af928962Smrg * to deal in the Software without restriction, including without limitation
7af928962Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8af928962Smrg * and/or sell copies of the Software, and to permit persons to whom the
9af928962Smrg * Software is furnished to do so, subject to the following conditions:
10af928962Smrg *
11af928962Smrg * The above copyright notice and this permission notice (including the next
12af928962Smrg * paragraph) shall be included in all copies or substantial portions of the
13af928962Smrg * Software.
14af928962Smrg *
15af928962Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16af928962Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17af928962Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18af928962Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19af928962Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20af928962Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21af928962Smrg * DEALINGS IN THE SOFTWARE.
22af928962Smrg */
2373143b9aSmrg/*
2473143b9aSmrg
2573143b9aSmrgCopyright 1993, 1994, 1998  The Open Group
2673143b9aSmrg
2773143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its
2873143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that
2973143b9aSmrgthe above copyright notice appear in all copies and that both that
3073143b9aSmrgcopyright notice and this permission notice appear in supporting
3173143b9aSmrgdocumentation.
3273143b9aSmrg
3373143b9aSmrgThe above copyright notice and this permission notice shall be included
3473143b9aSmrgin all copies or substantial portions of the Software.
3573143b9aSmrg
3673143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3773143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3873143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
3973143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
4073143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4173143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
4273143b9aSmrgOTHER DEALINGS IN THE SOFTWARE.
4373143b9aSmrg
4473143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall
4573143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or
4673143b9aSmrgother dealings in this Software without prior written authorization
4773143b9aSmrgfrom the copyright holders.
4873143b9aSmrg
4973143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
5073143b9aSmrg *
5173143b9aSmrg * All Rights Reserved
5273143b9aSmrg *
5373143b9aSmrg * Permission to use, copy, modify, and distribute this software and its
5473143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided
5573143b9aSmrg * that the above copyright notice appear in all copies and that both that
5673143b9aSmrg * copyright notice and this permission notice appear in supporting
5773143b9aSmrg * documentation, and that the name NCR not be used in advertising
5873143b9aSmrg * or publicity pertaining to distribution of the software without specific,
5973143b9aSmrg * written prior permission.  NCR makes no representations about the
6073143b9aSmrg * suitability of this software for any purpose.  It is provided "as is"
6173143b9aSmrg * without express or implied warranty.
6273143b9aSmrg *
6373143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
6473143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
6573143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
6673143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
6773143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
6873143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
6973143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7073143b9aSmrg */
7173143b9aSmrg
7273143b9aSmrg#include <ctype.h>
7373143b9aSmrg#ifdef XTHREADS
7473143b9aSmrg#include <X11/Xthreads.h>
7573143b9aSmrg#endif
7673143b9aSmrg
7773143b9aSmrg#ifndef WIN32
7873143b9aSmrg
7973143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
8073143b9aSmrg#include <sys/socket.h>
8173143b9aSmrg#include <netinet/in.h>
8273143b9aSmrg#include <arpa/inet.h>
8373143b9aSmrg#endif
8473143b9aSmrg
8573143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN)
8673143b9aSmrg#define X_INCLUDE_NETDB_H
8773143b9aSmrg#define XOS_USE_NO_LOCKING
8873143b9aSmrg#include <X11/Xos_r.h>
8973143b9aSmrg#endif
9073143b9aSmrg
9173143b9aSmrg#ifdef UNIXCONN
9273143b9aSmrg#ifndef X_NO_SYS_UN
9373143b9aSmrg#include <sys/un.h>
9473143b9aSmrg#endif
9573143b9aSmrg#include <sys/stat.h>
9673143b9aSmrg#endif
9773143b9aSmrg
9873143b9aSmrg
9973143b9aSmrg#ifndef NO_TCP_H
100fe567363Smrg#if defined(linux) || defined(__GLIBC__)
10173143b9aSmrg#include <sys/param.h>
10273143b9aSmrg#endif /* osf */
10373143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
10473143b9aSmrg#include <sys/param.h>
10573143b9aSmrg#include <machine/endian.h>
10673143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
10773143b9aSmrg#include <netinet/tcp.h>
10873143b9aSmrg#endif /* !NO_TCP_H */
10973143b9aSmrg
11073143b9aSmrg#include <sys/ioctl.h>
111e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
11273143b9aSmrg#include <sys/filio.h>
11373143b9aSmrg#endif
11473143b9aSmrg
11573143b9aSmrg#if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
11673143b9aSmrg#include <net/errno.h>
117fe567363Smrg#endif
11873143b9aSmrg
119fe567363Smrg#if defined(__i386__) && defined(SYSV)
12073143b9aSmrg#include <sys/stropts.h>
121fe567363Smrg#endif
12273143b9aSmrg
1238d4c0f7bSmrg#include <unistd.h>
1248d4c0f7bSmrg
12573143b9aSmrg#else /* !WIN32 */
12673143b9aSmrg
12773143b9aSmrg#include <X11/Xwinsock.h>
12873143b9aSmrg#include <X11/Xwindows.h>
12973143b9aSmrg#include <X11/Xw32defs.h>
13073143b9aSmrg#undef close
13173143b9aSmrg#define close closesocket
13273143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED
13373143b9aSmrg#define EADDRINUSE WSAEADDRINUSE
13473143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE
13573143b9aSmrg#undef EWOULDBLOCK
13673143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK
13773143b9aSmrg#define EINPROGRESS WSAEINPROGRESS
13873143b9aSmrg#undef EINTR
13973143b9aSmrg#define EINTR WSAEINTR
14073143b9aSmrg#define X_INCLUDE_NETDB_H
14173143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI
14273143b9aSmrg#include <X11/Xos_r.h>
14373143b9aSmrg#endif /* WIN32 */
14473143b9aSmrg
14573143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER)
14673143b9aSmrg#undef SO_DONTLINGER
14773143b9aSmrg#endif
14873143b9aSmrg
14973143b9aSmrg/* others don't need this */
15073143b9aSmrg#define SocketInitOnce() /**/
15173143b9aSmrg
15273143b9aSmrg#ifdef linux
15373143b9aSmrg#define HAVE_ABSTRACT_SOCKETS
15473143b9aSmrg#endif
15573143b9aSmrg
15673143b9aSmrg#define MIN_BACKLOG 128
15773143b9aSmrg#ifdef SOMAXCONN
15873143b9aSmrg#if SOMAXCONN > MIN_BACKLOG
15973143b9aSmrg#define BACKLOG SOMAXCONN
16073143b9aSmrg#endif
16173143b9aSmrg#endif
16273143b9aSmrg#ifndef BACKLOG
16373143b9aSmrg#define BACKLOG MIN_BACKLOG
16473143b9aSmrg#endif
16573143b9aSmrg
16673143b9aSmrg/*
16773143b9aSmrg * This is the Socket implementation of the X Transport service layer
16873143b9aSmrg *
16973143b9aSmrg * This file contains the implementation for both the UNIX and INET domains,
17073143b9aSmrg * and can be built for either one, or both.
17173143b9aSmrg *
17273143b9aSmrg */
17373143b9aSmrg
174fe567363Smrgtypedef struct _Sockettrans2dev {
175fe567363Smrg    const char	*transname;
17673143b9aSmrg    int		family;
17773143b9aSmrg    int		devcotsname;
17873143b9aSmrg    int		devcltsname;
17973143b9aSmrg    int		protocol;
18073143b9aSmrg} Sockettrans2dev;
18173143b9aSmrg
18273143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = {
18373143b9aSmrg#ifdef TCPCONN
18473143b9aSmrg    {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
18573143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6)
18673143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
18773143b9aSmrg#else /* IPv6 */
18873143b9aSmrg    {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
18973143b9aSmrg    {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
19073143b9aSmrg    {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
19173143b9aSmrg#endif
19273143b9aSmrg#endif /* TCPCONN */
19373143b9aSmrg#ifdef UNIXCONN
19473143b9aSmrg    {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
19573143b9aSmrg#if !defined(LOCALCONN)
19673143b9aSmrg    {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
19773143b9aSmrg#endif /* !LOCALCONN */
19873143b9aSmrg#endif /* UNIXCONN */
19973143b9aSmrg};
20073143b9aSmrg
20173143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
20273143b9aSmrg
20373143b9aSmrg#ifdef TCPCONN
20473143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr);
20573143b9aSmrg#endif
20673143b9aSmrg
20773143b9aSmrg#ifdef UNIXCONN
20873143b9aSmrg
20973143b9aSmrg
21073143b9aSmrg#if defined(X11_t)
21173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
21273143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix"
21373143b9aSmrg#endif /* X11_t */
21473143b9aSmrg#if defined(XIM_t)
21573143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM"
21673143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix"
21773143b9aSmrg#endif /* XIM_t */
21873143b9aSmrg#if defined(FS_t) || defined(FONT_t)
21973143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs"
22073143b9aSmrg#define UNIX_DIR "/tmp/.font-unix"
22173143b9aSmrg#endif /* FS_t || FONT_t */
22273143b9aSmrg#if defined(ICE_t)
22373143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/"
22473143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix"
22573143b9aSmrg#endif /* ICE_t */
22673143b9aSmrg#if defined(TEST_t)
22773143b9aSmrg#define UNIX_PATH "/tmp/.Test-unix/test"
22873143b9aSmrg#define UNIX_DIR "/tmp/.Test-unix"
22973143b9aSmrg#endif
23073143b9aSmrg#if defined(LBXPROXY_t)
23173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X"
23273143b9aSmrg#define UNIX_DIR  "/tmp/.X11-unix"
23373143b9aSmrg#endif
23473143b9aSmrg
23573143b9aSmrg
23673143b9aSmrg#endif /* UNIXCONN */
23773143b9aSmrg
23873143b9aSmrg#define PORTBUFSIZE	32
23973143b9aSmrg
24073143b9aSmrg#ifndef MAXHOSTNAMELEN
24173143b9aSmrg#define MAXHOSTNAMELEN 255
24273143b9aSmrg#endif
24373143b9aSmrg
24473143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6))
24573143b9aSmrg# define SOCKLEN_T socklen_t
246e8a71cdfSmrg#elif defined(SVR4) || defined(__SVR4) || defined(__SCO__)
247fe567363Smrg# define SOCKLEN_T size_t
24873143b9aSmrg#else
24973143b9aSmrg# define SOCKLEN_T int
25073143b9aSmrg#endif
25173143b9aSmrg
25273143b9aSmrg/*
25373143b9aSmrg * These are some utility function used by the real interface function below.
25473143b9aSmrg */
25573143b9aSmrg
25673143b9aSmrgstatic int
257fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family)
25873143b9aSmrg
25973143b9aSmrg{
26073143b9aSmrg    int     i;
26173143b9aSmrg
262fe567363Smrg    prmsg (3,"SocketSelectFamily(%s)\n", family);
26373143b9aSmrg
26473143b9aSmrg    for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
26573143b9aSmrg    {
26673143b9aSmrg        if (!strcmp (family, Sockettrans2devtab[i].transname))
26773143b9aSmrg	    return i;
26873143b9aSmrg    }
26973143b9aSmrg
27073143b9aSmrg    return (first == -1 ? -2 : -1);
27173143b9aSmrg}
27273143b9aSmrg
27373143b9aSmrg
27473143b9aSmrg/*
27573143b9aSmrg * This function gets the local address of the socket and stores it in the
27673143b9aSmrg * XtransConnInfo structure for the connection.
27773143b9aSmrg */
27873143b9aSmrg
27973143b9aSmrgstatic int
28073143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
28173143b9aSmrg
28273143b9aSmrg{
28373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
28473143b9aSmrg    struct sockaddr_storage socknamev6;
285b53e5eeaSmrg#else
28673143b9aSmrg    struct sockaddr_in socknamev4;
287b53e5eeaSmrg#endif
28873143b9aSmrg    void *socknamePtr;
28973143b9aSmrg    SOCKLEN_T namelen;
29073143b9aSmrg
291fe567363Smrg    prmsg (3,"SocketINETGetAddr(%p)\n", ciptr);
29273143b9aSmrg
29373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
294b53e5eeaSmrg    namelen = sizeof(socknamev6);
295b53e5eeaSmrg    socknamePtr = &socknamev6;
296b53e5eeaSmrg#else
297b53e5eeaSmrg    namelen = sizeof(socknamev4);
298b53e5eeaSmrg    socknamePtr = &socknamev4;
29973143b9aSmrg#endif
30073143b9aSmrg
30173143b9aSmrg    bzero(socknamePtr, namelen);
302fe567363Smrg
30373143b9aSmrg    if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
30473143b9aSmrg		     (void *)&namelen) < 0)
30573143b9aSmrg    {
30673143b9aSmrg#ifdef WIN32
30773143b9aSmrg	errno = WSAGetLastError();
30873143b9aSmrg#endif
309fe567363Smrg	prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n",
310fe567363Smrg	    EGET());
31173143b9aSmrg	return -1;
31273143b9aSmrg    }
31373143b9aSmrg
31473143b9aSmrg    /*
31573143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
31673143b9aSmrg     */
31773143b9aSmrg
318fe567363Smrg    if ((ciptr->addr = malloc (namelen)) == NULL)
31973143b9aSmrg    {
320fe567363Smrg        prmsg (1,
321fe567363Smrg	    "SocketINETGetAddr: Can't allocate space for the addr\n");
32273143b9aSmrg        return -1;
32373143b9aSmrg    }
32473143b9aSmrg
32573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
326b53e5eeaSmrg    ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
327b53e5eeaSmrg#else
328b53e5eeaSmrg    ciptr->family = socknamev4.sin_family;
32973143b9aSmrg#endif
33073143b9aSmrg    ciptr->addrlen = namelen;
33173143b9aSmrg    memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
33273143b9aSmrg
33373143b9aSmrg    return 0;
33473143b9aSmrg}
33573143b9aSmrg
33673143b9aSmrg
33773143b9aSmrg/*
33873143b9aSmrg * This function gets the remote address of the socket and stores it in the
33973143b9aSmrg * XtransConnInfo structure for the connection.
34073143b9aSmrg */
34173143b9aSmrg
34273143b9aSmrgstatic int
34373143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
34473143b9aSmrg
34573143b9aSmrg{
34673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
34773143b9aSmrg    struct sockaddr_storage socknamev6;
34873143b9aSmrg#endif
34973143b9aSmrg    struct sockaddr_in 	socknamev4;
35073143b9aSmrg    void *socknamePtr;
35173143b9aSmrg    SOCKLEN_T namelen;
35273143b9aSmrg
35373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
354b53e5eeaSmrg    if (ciptr->family == AF_INET6)
35573143b9aSmrg    {
35673143b9aSmrg	namelen = sizeof(socknamev6);
35773143b9aSmrg	socknamePtr = &socknamev6;
35873143b9aSmrg    }
35973143b9aSmrg    else
36073143b9aSmrg#endif
36173143b9aSmrg    {
36273143b9aSmrg	namelen = sizeof(socknamev4);
36373143b9aSmrg	socknamePtr = &socknamev4;
36473143b9aSmrg    }
36573143b9aSmrg
36673143b9aSmrg    bzero(socknamePtr, namelen);
367fe567363Smrg
368fe567363Smrg    prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr);
36973143b9aSmrg
37073143b9aSmrg    if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
37173143b9aSmrg		     (void *)&namelen) < 0)
37273143b9aSmrg    {
37373143b9aSmrg#ifdef WIN32
37473143b9aSmrg	errno = WSAGetLastError();
37573143b9aSmrg#endif
376fe567363Smrg	prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
377fe567363Smrg	    EGET());
37873143b9aSmrg	return -1;
37973143b9aSmrg    }
38073143b9aSmrg
38173143b9aSmrg    /*
38273143b9aSmrg     * Everything looks good: fill in the XtransConnInfo structure.
38373143b9aSmrg     */
38473143b9aSmrg
385fe567363Smrg    if ((ciptr->peeraddr = malloc (namelen)) == NULL)
38673143b9aSmrg    {
387fe567363Smrg        prmsg (1,
388fe567363Smrg	   "SocketINETGetPeerAddr: Can't allocate space for the addr\n");
38973143b9aSmrg        return -1;
39073143b9aSmrg    }
39173143b9aSmrg
39273143b9aSmrg    ciptr->peeraddrlen = namelen;
39373143b9aSmrg    memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
39473143b9aSmrg
39573143b9aSmrg    return 0;
39673143b9aSmrg}
39773143b9aSmrg
39873143b9aSmrg
39973143b9aSmrgstatic XtransConnInfo
40073143b9aSmrgTRANS(SocketOpen) (int i, int type)
40173143b9aSmrg
40273143b9aSmrg{
40373143b9aSmrg    XtransConnInfo	ciptr;
40473143b9aSmrg
405fe567363Smrg    prmsg (3,"SocketOpen(%d,%d)\n", i, type);
40673143b9aSmrg
407fe567363Smrg    if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
40873143b9aSmrg    {
409fe567363Smrg	prmsg (1, "SocketOpen: malloc failed\n");
41073143b9aSmrg	return NULL;
41173143b9aSmrg    }
41273143b9aSmrg
41373143b9aSmrg    if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
41473143b9aSmrg	Sockettrans2devtab[i].protocol)) < 0
41573143b9aSmrg#ifndef WIN32
41673143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
4178d4c0f7bSmrg       || ciptr->fd >= sysconf(_SC_OPEN_MAX)
41873143b9aSmrg#endif
41973143b9aSmrg#endif
42073143b9aSmrg      ) {
42173143b9aSmrg#ifdef WIN32
42273143b9aSmrg	errno = WSAGetLastError();
42373143b9aSmrg#endif
424fe567363Smrg	prmsg (2, "SocketOpen: socket() failed for %s\n",
425fe567363Smrg	    Sockettrans2devtab[i].transname);
42673143b9aSmrg
427fe567363Smrg	free (ciptr);
42873143b9aSmrg	return NULL;
42973143b9aSmrg    }
43073143b9aSmrg
43173143b9aSmrg#ifdef TCP_NODELAY
43273143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
43373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
43473143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
43573143b9aSmrg#endif
43673143b9aSmrg    )
43773143b9aSmrg    {
43873143b9aSmrg	/*
43973143b9aSmrg	 * turn off TCP coalescence for INET sockets
44073143b9aSmrg	 */
44173143b9aSmrg
44273143b9aSmrg	int tmp = 1;
44373143b9aSmrg	setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
44473143b9aSmrg	    (char *) &tmp, sizeof (int));
44573143b9aSmrg    }
44673143b9aSmrg#endif
44773143b9aSmrg
44873143b9aSmrg    return ciptr;
44973143b9aSmrg}
45073143b9aSmrg
45173143b9aSmrg
45273143b9aSmrg#ifdef TRANS_REOPEN
45373143b9aSmrg
45473143b9aSmrgstatic XtransConnInfo
455fe567363SmrgTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, char *port)
45673143b9aSmrg
45773143b9aSmrg{
45873143b9aSmrg    XtransConnInfo	ciptr;
45973143b9aSmrg    int portlen;
46073143b9aSmrg    struct sockaddr *addr;
461fe567363Smrg    size_t addrlen;
46273143b9aSmrg
463fe567363Smrg    prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
46473143b9aSmrg
46573143b9aSmrg    if (port == NULL) {
466fe567363Smrg      prmsg (1, "SocketReopen: port was null!\n");
46773143b9aSmrg      return NULL;
46873143b9aSmrg    }
46973143b9aSmrg
47073143b9aSmrg    portlen = strlen(port) + 1; // include space for trailing null
47173143b9aSmrg#ifdef SOCK_MAXADDRLEN
47273143b9aSmrg    if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
473fe567363Smrg      prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
47473143b9aSmrg      return NULL;
47573143b9aSmrg    }
47673143b9aSmrg    if (portlen < 14) portlen = 14;
47773143b9aSmrg#else
47873143b9aSmrg    if (portlen < 0 || portlen > 14) {
479fe567363Smrg      prmsg (1, "SocketReopen: invalid portlen %d\n", portlen);
48073143b9aSmrg      return NULL;
48173143b9aSmrg    }
48273143b9aSmrg#endif /*SOCK_MAXADDRLEN*/
48373143b9aSmrg
484fe567363Smrg    if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
48573143b9aSmrg    {
486fe567363Smrg	prmsg (1, "SocketReopen: malloc(ciptr) failed\n");
48773143b9aSmrg	return NULL;
48873143b9aSmrg    }
48973143b9aSmrg
49073143b9aSmrg    ciptr->fd = fd;
49173143b9aSmrg
492fe567363Smrg    addrlen = portlen + offsetof(struct sockaddr, sa_data);
493fe567363Smrg    if ((addr = calloc (1, addrlen)) == NULL) {
494fe567363Smrg	prmsg (1, "SocketReopen: malloc(addr) failed\n");
495fe567363Smrg	free (ciptr);
49673143b9aSmrg	return NULL;
49773143b9aSmrg    }
4988d4c0f7bSmrg    ciptr->addr = (char *) addr;
499fe567363Smrg    ciptr->addrlen = addrlen;
50073143b9aSmrg
501fe567363Smrg    if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) {
502fe567363Smrg	prmsg (1, "SocketReopen: malloc(portaddr) failed\n");
503fe567363Smrg	free (addr);
504fe567363Smrg	free (ciptr);
50573143b9aSmrg	return NULL;
50673143b9aSmrg    }
507fe567363Smrg    ciptr->peeraddrlen = addrlen;
50873143b9aSmrg
50973143b9aSmrg    /* Initialize ciptr structure as if it were a normally-opened unix socket */
51073143b9aSmrg    ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
51173143b9aSmrg#ifdef BSD44SOCKETS
512fe567363Smrg    addr->sa_len = addrlen;
51373143b9aSmrg#endif
51473143b9aSmrg    addr->sa_family = AF_UNIX;
51573143b9aSmrg#ifdef HAS_STRLCPY
51673143b9aSmrg    strlcpy(addr->sa_data, port, portlen);
51773143b9aSmrg#else
51873143b9aSmrg    strncpy(addr->sa_data, port, portlen);
51973143b9aSmrg#endif
52073143b9aSmrg    ciptr->family = AF_UNIX;
521fe567363Smrg    memcpy(ciptr->peeraddr, ciptr->addr, addrlen);
52273143b9aSmrg    ciptr->port = rindex(addr->sa_data, ':');
523e8a71cdfSmrg    if (ciptr->port == NULL) {
524e8a71cdfSmrg	if (is_numeric(addr->sa_data)) {
525e8a71cdfSmrg	    ciptr->port = addr->sa_data;
526e8a71cdfSmrg	}
527e8a71cdfSmrg    } else if (ciptr->port[0] == ':') {
528e8a71cdfSmrg	ciptr->port++;
529e8a71cdfSmrg    }
530e8a71cdfSmrg    /* port should now point to portnum or NULL */
53173143b9aSmrg    return ciptr;
53273143b9aSmrg}
53373143b9aSmrg
53473143b9aSmrg#endif /* TRANS_REOPEN */
53573143b9aSmrg
53673143b9aSmrg
53773143b9aSmrg/*
53873143b9aSmrg * These functions are the interface supplied in the Xtransport structure
53973143b9aSmrg */
54073143b9aSmrg
54173143b9aSmrg#ifdef TRANS_CLIENT
54273143b9aSmrg
54373143b9aSmrgstatic XtransConnInfo
544fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol,
545fe567363Smrg			   const char *host, const char *port, int previndex)
54673143b9aSmrg{
54773143b9aSmrg    XtransConnInfo	ciptr;
54873143b9aSmrg    int			i = previndex;
54973143b9aSmrg
550fe567363Smrg    prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
55173143b9aSmrg	protocol, host, port);
55273143b9aSmrg
55373143b9aSmrg    SocketInitOnce();
55473143b9aSmrg
55573143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
55673143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
557e8a71cdfSmrg		i, Sockettrans2devtab[i].devcotsname)) != NULL) {
558e8a71cdfSmrg	    /* Save the index for later use */
559e8a71cdfSmrg
560e8a71cdfSmrg	    ciptr->index = i;
56173143b9aSmrg	    break;
562e8a71cdfSmrg	}
56373143b9aSmrg    }
56473143b9aSmrg    if (i < 0) {
56573143b9aSmrg	if (i == -1)
566fe567363Smrg	    prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
567fe567363Smrg		   transname);
56873143b9aSmrg	else
569fe567363Smrg	    prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
570fe567363Smrg		   transname);
57173143b9aSmrg	return NULL;
57273143b9aSmrg    }
57373143b9aSmrg
57473143b9aSmrg    return ciptr;
57573143b9aSmrg}
57673143b9aSmrg
57773143b9aSmrgstatic XtransConnInfo
578fe567363SmrgTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
57973143b9aSmrg			     char *host, char *port)
58073143b9aSmrg{
58173143b9aSmrg    return TRANS(SocketOpenCOTSClientBase)(
58273143b9aSmrg			thistrans->TransName, protocol, host, port, -1);
58373143b9aSmrg}
58473143b9aSmrg
58573143b9aSmrg
58673143b9aSmrg#endif /* TRANS_CLIENT */
58773143b9aSmrg
58873143b9aSmrg
58973143b9aSmrg#ifdef TRANS_SERVER
59073143b9aSmrg
59173143b9aSmrgstatic XtransConnInfo
592fe567363SmrgTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
59373143b9aSmrg			     char *host, char *port)
59473143b9aSmrg
59573143b9aSmrg{
59673143b9aSmrg    XtransConnInfo	ciptr;
59773143b9aSmrg    int	i = -1;
59873143b9aSmrg
599fe567363Smrg    prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
60073143b9aSmrg
60173143b9aSmrg    SocketInitOnce();
60273143b9aSmrg
60373143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
60473143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
60573143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
60673143b9aSmrg	    break;
60773143b9aSmrg    }
60873143b9aSmrg    if (i < 0) {
60973143b9aSmrg	if (i == -1)
610fe567363Smrg	    prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
611fe567363Smrg		   thistrans->TransName);
61273143b9aSmrg	else
613fe567363Smrg	    prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
614fe567363Smrg		   thistrans->TransName);
61573143b9aSmrg	return NULL;
61673143b9aSmrg    }
61773143b9aSmrg
61873143b9aSmrg    /*
61973143b9aSmrg     * Using this prevents the bind() check for an existing server listening
62073143b9aSmrg     * on the same port, but it is required for other reasons.
62173143b9aSmrg     */
62273143b9aSmrg#ifdef SO_REUSEADDR
62373143b9aSmrg
62473143b9aSmrg    /*
62573143b9aSmrg     * SO_REUSEADDR only applied to AF_INET && AF_INET6
62673143b9aSmrg     */
62773143b9aSmrg
62873143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET
62973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
63073143b9aSmrg      || Sockettrans2devtab[i].family == AF_INET6
63173143b9aSmrg#endif
63273143b9aSmrg    )
63373143b9aSmrg    {
63473143b9aSmrg	int one = 1;
63573143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
63673143b9aSmrg		    (char *) &one, sizeof (int));
63773143b9aSmrg    }
63873143b9aSmrg#endif
63973143b9aSmrg#ifdef IPV6_V6ONLY
64073143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
64173143b9aSmrg    {
64273143b9aSmrg	int one = 1;
64373143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
64473143b9aSmrg    }
64573143b9aSmrg#endif
64673143b9aSmrg    /* Save the index for later use */
64773143b9aSmrg
64873143b9aSmrg    ciptr->index = i;
64973143b9aSmrg
65073143b9aSmrg    return ciptr;
65173143b9aSmrg}
65273143b9aSmrg
65373143b9aSmrg#endif /* TRANS_SERVER */
65473143b9aSmrg
65573143b9aSmrg
65673143b9aSmrg#ifdef TRANS_CLIENT
65773143b9aSmrg
65873143b9aSmrgstatic XtransConnInfo
659fe567363SmrgTRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
66073143b9aSmrg			     char *host, char *port)
66173143b9aSmrg
66273143b9aSmrg{
66373143b9aSmrg    XtransConnInfo	ciptr;
66473143b9aSmrg    int			i = -1;
66573143b9aSmrg
666fe567363Smrg    prmsg (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
66773143b9aSmrg
66873143b9aSmrg    SocketInitOnce();
66973143b9aSmrg
67073143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
67173143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
67273143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
67373143b9aSmrg	    break;
67473143b9aSmrg    }
67573143b9aSmrg    if (i < 0) {
67673143b9aSmrg	if (i == -1)
677fe567363Smrg	    prmsg (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
678fe567363Smrg		   thistrans->TransName);
67973143b9aSmrg	else
680fe567363Smrg	    prmsg (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
681fe567363Smrg		   thistrans->TransName);
68273143b9aSmrg	return NULL;
68373143b9aSmrg    }
68473143b9aSmrg
68573143b9aSmrg    /* Save the index for later use */
68673143b9aSmrg
68773143b9aSmrg    ciptr->index = i;
68873143b9aSmrg
68973143b9aSmrg    return ciptr;
69073143b9aSmrg}
69173143b9aSmrg
69273143b9aSmrg#endif /* TRANS_CLIENT */
69373143b9aSmrg
69473143b9aSmrg
69573143b9aSmrg#ifdef TRANS_SERVER
69673143b9aSmrg
69773143b9aSmrgstatic XtransConnInfo
698fe567363SmrgTRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
69973143b9aSmrg			     char *host, char *port)
70073143b9aSmrg
70173143b9aSmrg{
70273143b9aSmrg    XtransConnInfo	ciptr;
70373143b9aSmrg    int	i = -1;
70473143b9aSmrg
705fe567363Smrg    prmsg (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
70673143b9aSmrg
70773143b9aSmrg    SocketInitOnce();
70873143b9aSmrg
70973143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
71073143b9aSmrg	if ((ciptr = TRANS(SocketOpen) (
71173143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname)) != NULL)
71273143b9aSmrg	    break;
71373143b9aSmrg    }
71473143b9aSmrg    if (i < 0) {
71573143b9aSmrg	if (i == -1)
716fe567363Smrg	    prmsg (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
717fe567363Smrg		   thistrans->TransName);
71873143b9aSmrg	else
719fe567363Smrg	    prmsg (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
720fe567363Smrg		   thistrans->TransName);
72173143b9aSmrg	return NULL;
72273143b9aSmrg    }
72373143b9aSmrg
72473143b9aSmrg#ifdef IPV6_V6ONLY
72573143b9aSmrg    if (Sockettrans2devtab[i].family == AF_INET6)
72673143b9aSmrg    {
72773143b9aSmrg	int one = 1;
72873143b9aSmrg	setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
72973143b9aSmrg    }
73073143b9aSmrg#endif
73173143b9aSmrg    /* Save the index for later use */
73273143b9aSmrg
73373143b9aSmrg    ciptr->index = i;
73473143b9aSmrg
73573143b9aSmrg    return ciptr;
73673143b9aSmrg}
73773143b9aSmrg
73873143b9aSmrg#endif /* TRANS_SERVER */
73973143b9aSmrg
74073143b9aSmrg
74173143b9aSmrg#ifdef TRANS_REOPEN
74273143b9aSmrg
74373143b9aSmrgstatic XtransConnInfo
74473143b9aSmrgTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
74573143b9aSmrg
74673143b9aSmrg{
74773143b9aSmrg    XtransConnInfo	ciptr;
74873143b9aSmrg    int			i = -1;
74973143b9aSmrg
750fe567363Smrg    prmsg (2,
751fe567363Smrg	"SocketReopenCOTSServer(%d, %s)\n", fd, port);
75273143b9aSmrg
75373143b9aSmrg    SocketInitOnce();
75473143b9aSmrg
75573143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
75673143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
75773143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
75873143b9aSmrg	    break;
75973143b9aSmrg    }
76073143b9aSmrg    if (i < 0) {
76173143b9aSmrg	if (i == -1)
762fe567363Smrg	    prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
763fe567363Smrg		   thistrans->TransName);
76473143b9aSmrg	else
765fe567363Smrg	    prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
766fe567363Smrg		   thistrans->TransName);
76773143b9aSmrg	return NULL;
76873143b9aSmrg    }
76973143b9aSmrg
77073143b9aSmrg    /* Save the index for later use */
77173143b9aSmrg
77273143b9aSmrg    ciptr->index = i;
77373143b9aSmrg
77473143b9aSmrg    return ciptr;
77573143b9aSmrg}
77673143b9aSmrg
77773143b9aSmrgstatic XtransConnInfo
77873143b9aSmrgTRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
77973143b9aSmrg
78073143b9aSmrg{
78173143b9aSmrg    XtransConnInfo	ciptr;
78273143b9aSmrg    int			i = -1;
78373143b9aSmrg
784fe567363Smrg    prmsg (2,
785fe567363Smrg	"SocketReopenCLTSServer(%d, %s)\n", fd, port);
78673143b9aSmrg
78773143b9aSmrg    SocketInitOnce();
78873143b9aSmrg
78973143b9aSmrg    while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
79073143b9aSmrg	if ((ciptr = TRANS(SocketReopen) (
79173143b9aSmrg		 i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
79273143b9aSmrg	    break;
79373143b9aSmrg    }
79473143b9aSmrg    if (i < 0) {
79573143b9aSmrg	if (i == -1)
796fe567363Smrg	    prmsg (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
797fe567363Smrg		   thistrans->TransName);
79873143b9aSmrg	else
799fe567363Smrg	    prmsg (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
800fe567363Smrg		   thistrans->TransName);
80173143b9aSmrg	return NULL;
80273143b9aSmrg    }
80373143b9aSmrg
80473143b9aSmrg    /* Save the index for later use */
80573143b9aSmrg
80673143b9aSmrg    ciptr->index = i;
80773143b9aSmrg
80873143b9aSmrg    return ciptr;
80973143b9aSmrg}
81073143b9aSmrg
81173143b9aSmrg#endif /* TRANS_REOPEN */
81273143b9aSmrg
81373143b9aSmrg
81473143b9aSmrgstatic int
81573143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
81673143b9aSmrg
81773143b9aSmrg{
818fe567363Smrg    prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
81973143b9aSmrg
82073143b9aSmrg    return -1;
82173143b9aSmrg}
82273143b9aSmrg
82373143b9aSmrg#ifdef UNIXCONN
82473143b9aSmrgstatic int
82573143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract)
82673143b9aSmrg{
82773143b9aSmrg    struct sockaddr_un s;
82873143b9aSmrg    int maxlen = sizeof(s.sun_path) - 1;
82973143b9aSmrg    const char *at = "";
83073143b9aSmrg
83173143b9aSmrg    if (!port || !*port || !path)
83273143b9aSmrg	return -1;
83373143b9aSmrg
83473143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
83573143b9aSmrg    if (port[0] == '@')
83673143b9aSmrg	upath = "";
83773143b9aSmrg    else if (abstract)
83873143b9aSmrg	at = "@";
83973143b9aSmrg#endif
84073143b9aSmrg
84173143b9aSmrg    if (*port == '/') /* a full pathname */
84273143b9aSmrg	upath = "";
84373143b9aSmrg
84473143b9aSmrg    if (strlen(port) + strlen(upath) > maxlen)
84573143b9aSmrg	return -1;
846fe567363Smrg    snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port);
84773143b9aSmrg    return 0;
84873143b9aSmrg}
84973143b9aSmrg#endif
85073143b9aSmrg
85173143b9aSmrg#ifdef TRANS_SERVER
85273143b9aSmrg
85373143b9aSmrgstatic int
854fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr,
85573143b9aSmrg			     struct sockaddr *sockname,
85673143b9aSmrg			     int socknamelen, unsigned int flags)
85773143b9aSmrg
85873143b9aSmrg{
85973143b9aSmrg    SOCKLEN_T namelen = socknamelen;
86073143b9aSmrg    int	fd = ciptr->fd;
86173143b9aSmrg    int	retry;
86273143b9aSmrg
863fe567363Smrg    prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd);
86473143b9aSmrg
86573143b9aSmrg    if (Sockettrans2devtab[ciptr->index].family == AF_INET
86673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
86773143b9aSmrg      || Sockettrans2devtab[ciptr->index].family == AF_INET6
86873143b9aSmrg#endif
86973143b9aSmrg	)
87073143b9aSmrg	retry = 20;
87173143b9aSmrg    else
87273143b9aSmrg	retry = 0;
87373143b9aSmrg
87473143b9aSmrg    while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
87573143b9aSmrg    {
87673143b9aSmrg	if (errno == EADDRINUSE) {
87773143b9aSmrg	    if (flags & ADDR_IN_USE_ALLOWED)
87873143b9aSmrg		break;
87973143b9aSmrg	    else
88073143b9aSmrg		return TRANS_ADDR_IN_USE;
88173143b9aSmrg	}
882fe567363Smrg
88373143b9aSmrg	if (retry-- == 0) {
884fe567363Smrg	    prmsg (1, "SocketCreateListener: failed to bind listener\n");
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    {
915fe567363Smrg	prmsg (1, "SocketCreateListener: listen() failed\n");
91673143b9aSmrg	close (fd);
91773143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
91873143b9aSmrg    }
919fe567363Smrg
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
949fe567363Smrg
950fe567363Smrg    prmsg (2, "SocketINETCreateListener(%s)\n", port);
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);
966fe567363Smrg	snprintf (portbuf, sizeof(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	    {
979fe567363Smrg		prmsg (1,
98073143b9aSmrg	     "SocketINETCreateListener: Unable to get service for %s\n",
981fe567363Smrg		      port);
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);
990fe567363Smrg	    /*
99173143b9aSmrg	     * check that somehow the port address isn't negative or in
99273143b9aSmrg	     * the range of reserved port addresses. This can happen and
993fe567363Smrg	     * be very bad if the server is suid-root and the user does
994fe567363Smrg	     * 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    {
1036fe567363Smrg	prmsg (1,
1037fe567363Smrg    "SocketINETCreateListener: ...SocketCreateListener() failed\n");
103873143b9aSmrg	return status;
103973143b9aSmrg    }
104073143b9aSmrg
104173143b9aSmrg    if (TRANS(SocketINETGetAddr) (ciptr) < 0)
104273143b9aSmrg    {
1043fe567363Smrg	prmsg (1,
1044fe567363Smrg       "SocketINETCreateListener: ...SocketINETGetAddr() failed\n");
104573143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
104673143b9aSmrg    }
104773143b9aSmrg
104873143b9aSmrg    return 0;
104973143b9aSmrg}
105073143b9aSmrg
105173143b9aSmrg#endif /* TCPCONN */
105273143b9aSmrg
105373143b9aSmrg
105473143b9aSmrg#ifdef UNIXCONN
105573143b9aSmrg
105673143b9aSmrgstatic int
105773143b9aSmrgTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
105873143b9aSmrg				 unsigned int flags)
105973143b9aSmrg
106073143b9aSmrg{
106173143b9aSmrg    struct sockaddr_un	sockname;
106273143b9aSmrg    int			namelen;
106373143b9aSmrg    int			oldUmask;
106473143b9aSmrg    int			status;
106573143b9aSmrg    unsigned int	mode;
106673143b9aSmrg    char		tmpport[108];
106773143b9aSmrg
106873143b9aSmrg    int			abstract = 0;
106973143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
107073143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
107173143b9aSmrg#endif
107273143b9aSmrg
1073fe567363Smrg    prmsg (2, "SocketUNIXCreateListener(%s)\n",
1074fe567363Smrg	port ? port : "NULL");
107573143b9aSmrg
107673143b9aSmrg    /* Make sure the directory is created */
107773143b9aSmrg
107873143b9aSmrg    oldUmask = umask (0);
107973143b9aSmrg
108073143b9aSmrg#ifdef UNIX_DIR
108173143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
108273143b9aSmrg    mode = 01777;
108373143b9aSmrg#else
108473143b9aSmrg    mode = 0777;
108573143b9aSmrg#endif
10868d4c0f7bSmrg    if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
1087fe567363Smrg	prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
1088fe567363Smrg	       UNIX_DIR, errno);
108973143b9aSmrg	(void) umask (oldUmask);
109073143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
109173143b9aSmrg    }
109273143b9aSmrg#endif
109373143b9aSmrg
109473143b9aSmrg    memset(&sockname, 0, sizeof(sockname));
109573143b9aSmrg    sockname.sun_family = AF_UNIX;
109673143b9aSmrg
109773143b9aSmrg    if (!(port && *port)) {
109873143b9aSmrg	snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
109973143b9aSmrg	port = tmpport;
110073143b9aSmrg    }
110173143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1102fe567363Smrg	prmsg (1, "SocketUNIXCreateListener: path too long\n");
110373143b9aSmrg	return TRANS_CREATE_LISTENER_FAILED;
110473143b9aSmrg    }
110573143b9aSmrg
1106fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
110773143b9aSmrg    sockname.sun_len = strlen(sockname.sun_path);
110873143b9aSmrg#endif
110973143b9aSmrg
111073143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
111173143b9aSmrg    namelen = SUN_LEN(&sockname);
111273143b9aSmrg#else
111373143b9aSmrg    namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
111473143b9aSmrg#endif
111573143b9aSmrg
111673143b9aSmrg    if (abstract) {
111773143b9aSmrg	sockname.sun_path[0] = '\0';
111873143b9aSmrg	namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
111973143b9aSmrg    }
112073143b9aSmrg    else
112173143b9aSmrg	unlink (sockname.sun_path);
112273143b9aSmrg
112373143b9aSmrg    if ((status = TRANS(SocketCreateListener) (ciptr,
112473143b9aSmrg	(struct sockaddr *) &sockname, namelen, flags)) < 0)
112573143b9aSmrg    {
1126fe567363Smrg	prmsg (1,
1127fe567363Smrg    "SocketUNIXCreateListener: ...SocketCreateListener() failed\n");
112873143b9aSmrg	(void) umask (oldUmask);
112973143b9aSmrg	return status;
113073143b9aSmrg    }
113173143b9aSmrg
113273143b9aSmrg    /*
113373143b9aSmrg     * Now that the listener is esablished, create the addr info for
113473143b9aSmrg     * this connection. getpeername() doesn't work for UNIX Domain Sockets
113573143b9aSmrg     * on some systems (hpux at least), so we will just do it manually, instead
113673143b9aSmrg     * of calling something like TRANS(SocketUNIXGetAddr).
113773143b9aSmrg     */
113873143b9aSmrg
113973143b9aSmrg    namelen = sizeof (sockname); /* this will always make it the same size */
114073143b9aSmrg
1141fe567363Smrg    if ((ciptr->addr = malloc (namelen)) == NULL)
114273143b9aSmrg    {
1143fe567363Smrg        prmsg (1,
1144fe567363Smrg        "SocketUNIXCreateListener: Can't allocate space for the addr\n");
114573143b9aSmrg	(void) umask (oldUmask);
114673143b9aSmrg        return TRANS_CREATE_LISTENER_FAILED;
114773143b9aSmrg    }
114873143b9aSmrg
114973143b9aSmrg    if (abstract)
115073143b9aSmrg	sockname.sun_path[0] = '@';
115173143b9aSmrg
115273143b9aSmrg    ciptr->family = sockname.sun_family;
115373143b9aSmrg    ciptr->addrlen = namelen;
115473143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
115573143b9aSmrg
115673143b9aSmrg    (void) umask (oldUmask);
115773143b9aSmrg
115873143b9aSmrg    return 0;
115973143b9aSmrg}
116073143b9aSmrg
116173143b9aSmrg
116273143b9aSmrgstatic int
116373143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
116473143b9aSmrg
116573143b9aSmrg{
116673143b9aSmrg    /*
116773143b9aSmrg     * See if the unix domain socket has disappeared.  If it has, recreate it.
116873143b9aSmrg     */
116973143b9aSmrg
117073143b9aSmrg    struct sockaddr_un 	*unsock = (struct sockaddr_un *) ciptr->addr;
117173143b9aSmrg    struct stat		statb;
117273143b9aSmrg    int 		status = TRANS_RESET_NOOP;
117373143b9aSmrg    unsigned int	mode;
117473143b9aSmrg    int abstract = 0;
117573143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
117673143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
117773143b9aSmrg#endif
117873143b9aSmrg
1179fe567363Smrg    prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd);
118073143b9aSmrg
118173143b9aSmrg    if (!abstract && (
118273143b9aSmrg	stat (unsock->sun_path, &statb) == -1 ||
118373143b9aSmrg        ((statb.st_mode & S_IFMT) !=
1184e8a71cdfSmrg#if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
118573143b9aSmrg	  		S_IFIFO
118673143b9aSmrg#else
118773143b9aSmrg			S_IFSOCK
118873143b9aSmrg#endif
118973143b9aSmrg				)))
119073143b9aSmrg    {
119173143b9aSmrg	int oldUmask = umask (0);
119273143b9aSmrg
119373143b9aSmrg#ifdef UNIX_DIR
119473143b9aSmrg#ifdef HAS_STICKY_DIR_BIT
119573143b9aSmrg	mode = 01777;
119673143b9aSmrg#else
119773143b9aSmrg	mode = 0777;
119873143b9aSmrg#endif
119973143b9aSmrg        if (trans_mkdir(UNIX_DIR, mode) == -1) {
1200fe567363Smrg            prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
1201fe567363Smrg	    UNIX_DIR, errno);
120273143b9aSmrg	    (void) umask (oldUmask);
120373143b9aSmrg	    return TRANS_RESET_FAILURE;
120473143b9aSmrg        }
120573143b9aSmrg#endif
120673143b9aSmrg
120773143b9aSmrg	close (ciptr->fd);
120873143b9aSmrg	unlink (unsock->sun_path);
120973143b9aSmrg
121073143b9aSmrg	if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
121173143b9aSmrg	{
121273143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
121373143b9aSmrg	    (void) umask (oldUmask);
121473143b9aSmrg	    return TRANS_RESET_FAILURE;
121573143b9aSmrg	}
121673143b9aSmrg
121773143b9aSmrg	if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
121873143b9aSmrg	{
121973143b9aSmrg	    close (ciptr->fd);
122073143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
122173143b9aSmrg	    return TRANS_RESET_FAILURE;
122273143b9aSmrg	}
122373143b9aSmrg
122473143b9aSmrg	if (listen (ciptr->fd, BACKLOG) < 0)
122573143b9aSmrg	{
122673143b9aSmrg	    close (ciptr->fd);
122773143b9aSmrg	    TRANS(FreeConnInfo) (ciptr);
122873143b9aSmrg	    (void) umask (oldUmask);
122973143b9aSmrg	    return TRANS_RESET_FAILURE;
123073143b9aSmrg	}
123173143b9aSmrg
123273143b9aSmrg	umask (oldUmask);
123373143b9aSmrg
123473143b9aSmrg	status = TRANS_RESET_NEW_FD;
123573143b9aSmrg    }
123673143b9aSmrg
123773143b9aSmrg    return status;
123873143b9aSmrg}
123973143b9aSmrg
124073143b9aSmrg#endif /* UNIXCONN */
124173143b9aSmrg
124273143b9aSmrg
124373143b9aSmrg#ifdef TCPCONN
124473143b9aSmrg
124573143b9aSmrgstatic XtransConnInfo
124673143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
124773143b9aSmrg
124873143b9aSmrg{
124973143b9aSmrg    XtransConnInfo	newciptr;
125073143b9aSmrg    struct sockaddr_in	sockname;
125173143b9aSmrg    SOCKLEN_T		namelen = sizeof(sockname);
125273143b9aSmrg
1253fe567363Smrg    prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd);
125473143b9aSmrg
1255fe567363Smrg    if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
125673143b9aSmrg    {
1257fe567363Smrg	prmsg (1, "SocketINETAccept: malloc failed\n");
125873143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
125973143b9aSmrg	return NULL;
126073143b9aSmrg    }
126173143b9aSmrg
126273143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
126373143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
126473143b9aSmrg    {
126573143b9aSmrg#ifdef WIN32
126673143b9aSmrg	errno = WSAGetLastError();
126773143b9aSmrg#endif
1268fe567363Smrg	prmsg (1, "SocketINETAccept: accept() failed\n");
1269fe567363Smrg	free (newciptr);
127073143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
127173143b9aSmrg	return NULL;
127273143b9aSmrg    }
127373143b9aSmrg
127473143b9aSmrg#ifdef TCP_NODELAY
127573143b9aSmrg    {
127673143b9aSmrg	/*
127773143b9aSmrg	 * turn off TCP coalescence for INET sockets
127873143b9aSmrg	 */
127973143b9aSmrg
128073143b9aSmrg	int tmp = 1;
128173143b9aSmrg	setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
128273143b9aSmrg	    (char *) &tmp, sizeof (int));
128373143b9aSmrg    }
128473143b9aSmrg#endif
128573143b9aSmrg
128673143b9aSmrg    /*
1287fe567363Smrg     * Get this address again because the transport may give a more
128873143b9aSmrg     * specific address now that a connection is established.
128973143b9aSmrg     */
129073143b9aSmrg
129173143b9aSmrg    if (TRANS(SocketINETGetAddr) (newciptr) < 0)
129273143b9aSmrg    {
1293fe567363Smrg	prmsg (1,
1294fe567363Smrg	    "SocketINETAccept: ...SocketINETGetAddr() failed:\n");
129573143b9aSmrg	close (newciptr->fd);
1296fe567363Smrg	free (newciptr);
129773143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
129873143b9aSmrg        return NULL;
129973143b9aSmrg    }
130073143b9aSmrg
130173143b9aSmrg    if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
130273143b9aSmrg    {
1303fe567363Smrg	prmsg (1,
1304fe567363Smrg	  "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n");
130573143b9aSmrg	close (newciptr->fd);
1306fe567363Smrg	if (newciptr->addr) free (newciptr->addr);
1307fe567363Smrg	free (newciptr);
130873143b9aSmrg	*status = TRANS_ACCEPT_MISC_ERROR;
130973143b9aSmrg        return NULL;
131073143b9aSmrg    }
131173143b9aSmrg
131273143b9aSmrg    *status = 0;
131373143b9aSmrg
131473143b9aSmrg    return newciptr;
131573143b9aSmrg}
131673143b9aSmrg
131773143b9aSmrg#endif /* TCPCONN */
131873143b9aSmrg
131973143b9aSmrg
132073143b9aSmrg#ifdef UNIXCONN
132173143b9aSmrgstatic XtransConnInfo
132273143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
132373143b9aSmrg
132473143b9aSmrg{
132573143b9aSmrg    XtransConnInfo	newciptr;
132673143b9aSmrg    struct sockaddr_un	sockname;
132773143b9aSmrg    SOCKLEN_T 		namelen = sizeof sockname;
132873143b9aSmrg
1329fe567363Smrg    prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd);
133073143b9aSmrg
1331fe567363Smrg    if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL)
133273143b9aSmrg    {
1333fe567363Smrg	prmsg (1, "SocketUNIXAccept: malloc() failed\n");
133473143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
133573143b9aSmrg	return NULL;
133673143b9aSmrg    }
133773143b9aSmrg
133873143b9aSmrg    if ((newciptr->fd = accept (ciptr->fd,
133973143b9aSmrg	(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
134073143b9aSmrg    {
1341fe567363Smrg	prmsg (1, "SocketUNIXAccept: accept() failed\n");
1342fe567363Smrg	free (newciptr);
134373143b9aSmrg	*status = TRANS_ACCEPT_FAILED;
134473143b9aSmrg	return NULL;
134573143b9aSmrg    }
134673143b9aSmrg
134773143b9aSmrg	ciptr->addrlen = namelen;
134873143b9aSmrg    /*
134973143b9aSmrg     * Get the socket name and the peer name from the listener socket,
135073143b9aSmrg     * since this is unix domain.
135173143b9aSmrg     */
135273143b9aSmrg
1353fe567363Smrg    if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL)
135473143b9aSmrg    {
1355fe567363Smrg        prmsg (1,
1356fe567363Smrg        "SocketUNIXAccept: Can't allocate space for the addr\n");
135773143b9aSmrg	close (newciptr->fd);
1358fe567363Smrg	free (newciptr);
135973143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
136073143b9aSmrg        return NULL;
136173143b9aSmrg    }
136273143b9aSmrg
136373143b9aSmrg    /*
136473143b9aSmrg     * if the socket is abstract, we already modified the address to have a
136573143b9aSmrg     * @ instead of the initial NUL, so no need to do that again here.
136673143b9aSmrg     */
136773143b9aSmrg
136873143b9aSmrg    newciptr->addrlen = ciptr->addrlen;
136973143b9aSmrg    memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
137073143b9aSmrg
1371fe567363Smrg    if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL)
137273143b9aSmrg    {
1373fe567363Smrg        prmsg (1,
1374fe567363Smrg	      "SocketUNIXAccept: Can't allocate space for the addr\n");
137573143b9aSmrg	close (newciptr->fd);
1376fe567363Smrg	if (newciptr->addr) free (newciptr->addr);
1377fe567363Smrg	free (newciptr);
137873143b9aSmrg	*status = TRANS_ACCEPT_BAD_MALLOC;
137973143b9aSmrg        return NULL;
138073143b9aSmrg    }
1381fe567363Smrg
138273143b9aSmrg    newciptr->peeraddrlen = ciptr->addrlen;
138373143b9aSmrg    memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
138473143b9aSmrg
138573143b9aSmrg    newciptr->family = AF_UNIX;
138673143b9aSmrg
138773143b9aSmrg    *status = 0;
138873143b9aSmrg
138973143b9aSmrg    return newciptr;
139073143b9aSmrg}
139173143b9aSmrg
139273143b9aSmrg#endif /* UNIXCONN */
139373143b9aSmrg
139473143b9aSmrg#endif /* TRANS_SERVER */
139573143b9aSmrg
139673143b9aSmrg
139773143b9aSmrg#ifdef TRANS_CLIENT
139873143b9aSmrg
139973143b9aSmrg#ifdef TCPCONN
140073143b9aSmrg
140173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
140273143b9aSmrgstruct addrlist {
140373143b9aSmrg    struct addrinfo *	addr;
1404fe567363Smrg    struct addrinfo *	firstaddr;
140573143b9aSmrg    char 		port[PORTBUFSIZE];
140673143b9aSmrg    char 		host[MAXHOSTNAMELEN];
140773143b9aSmrg};
140873143b9aSmrgstatic struct addrlist  *addrlist = NULL;
140973143b9aSmrg#endif
141073143b9aSmrg
141173143b9aSmrg
141273143b9aSmrgstatic int
141373143b9aSmrgTRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
141473143b9aSmrg
141573143b9aSmrg{
141673143b9aSmrg    struct sockaddr *	socketaddr = NULL;
141773143b9aSmrg    int			socketaddrlen = 0;
141873143b9aSmrg    int			res;
141973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
142073143b9aSmrg    struct addrinfo 	hints;
142173143b9aSmrg    char		ntopbuf[INET6_ADDRSTRLEN];
142273143b9aSmrg    int			resetonce = 0;
1423fe567363Smrg#else
142473143b9aSmrg    struct sockaddr_in	sockname;
1425fe567363Smrg    struct hostent	*hostp;
1426fe567363Smrg    struct servent	*servp;
1427fe567363Smrg    unsigned long 	tmpaddr;
1428fe567363Smrg#endif
142973143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
143073143b9aSmrg    _Xgethostbynameparams hparams;
143173143b9aSmrg    _Xgetservbynameparams sparams;
143273143b9aSmrg#endif
143373143b9aSmrg#ifdef X11_t
143473143b9aSmrg    char	portbuf[PORTBUFSIZE];
143573143b9aSmrg#endif
143673143b9aSmrg
143773143b9aSmrg    char 		hostnamebuf[256];		/* tmp space */
143873143b9aSmrg
1439fe567363Smrg    prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
144073143b9aSmrg
144173143b9aSmrg    if (!host)
144273143b9aSmrg    {
144373143b9aSmrg	hostnamebuf[0] = '\0';
144473143b9aSmrg	(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
144573143b9aSmrg	host = hostnamebuf;
144673143b9aSmrg    }
144773143b9aSmrg
144873143b9aSmrg#ifdef X11_t
144973143b9aSmrg    /*
145073143b9aSmrg     * X has a well known port, that is transport dependent. It is easier
145173143b9aSmrg     * to handle it here, than try and come up with a transport independent
145273143b9aSmrg     * representation that can be passed in and resolved the usual way.
145373143b9aSmrg     *
145473143b9aSmrg     * The port that is passed here is really a string containing the idisplay
145573143b9aSmrg     * from ConnectDisplay().
145673143b9aSmrg     */
145773143b9aSmrg
145873143b9aSmrg    if (is_numeric (port))
145973143b9aSmrg    {
1460fe567363Smrg	long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1461fe567363Smrg	snprintf (portbuf, sizeof(portbuf), "%lu", tmpport);
146273143b9aSmrg	port = portbuf;
146373143b9aSmrg    }
146473143b9aSmrg#endif
146573143b9aSmrg
146673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1467b53e5eeaSmrg    {
146873143b9aSmrg	if (addrlist != NULL) {
146973143b9aSmrg	    if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
147073143b9aSmrg		if (addrlist->firstaddr)
147173143b9aSmrg		    freeaddrinfo(addrlist->firstaddr);
147273143b9aSmrg		addrlist->firstaddr = NULL;
147373143b9aSmrg	    }
147473143b9aSmrg	} else {
147573143b9aSmrg	    addrlist = malloc(sizeof(struct addrlist));
147673143b9aSmrg	    addrlist->firstaddr = NULL;
147773143b9aSmrg	}
147873143b9aSmrg
147973143b9aSmrg	if (addrlist->firstaddr == NULL) {
148073143b9aSmrg	    strncpy(addrlist->port, port, sizeof(addrlist->port));
148173143b9aSmrg	    addrlist->port[sizeof(addrlist->port) - 1] = '\0';
148273143b9aSmrg	    strncpy(addrlist->host, host, sizeof(addrlist->host));
148373143b9aSmrg	    addrlist->host[sizeof(addrlist->host) - 1] = '\0';
148473143b9aSmrg
148573143b9aSmrg	    bzero(&hints,sizeof(hints));
148673143b9aSmrg	    hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
148773143b9aSmrg
148873143b9aSmrg	    res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
148973143b9aSmrg	    if (res != 0) {
1490fe567363Smrg		prmsg (1, "SocketINETConnect() can't get address "
149173143b9aSmrg			"for %s:%s: %s\n", host, port, gai_strerror(res));
149273143b9aSmrg		ESET(EINVAL);
149373143b9aSmrg		return TRANS_CONNECT_FAILED;
149473143b9aSmrg	    }
149573143b9aSmrg	    for (res = 0, addrlist->addr = addrlist->firstaddr;
149673143b9aSmrg		 addrlist->addr ; res++) {
149773143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
149873143b9aSmrg	    }
1499fe567363Smrg	    prmsg(4,"Got New Address list with %d addresses\n", res);
150073143b9aSmrg	    res = 0;
150173143b9aSmrg	    addrlist->addr = NULL;
150273143b9aSmrg	}
150373143b9aSmrg
150473143b9aSmrg	while (socketaddr == NULL) {
150573143b9aSmrg	    if (addrlist->addr == NULL) {
1506fe567363Smrg		if (resetonce) {
150773143b9aSmrg		    /* Already checked entire list - no usable addresses */
1508fe567363Smrg		    prmsg (1, "SocketINETConnect() no usable address "
1509fe567363Smrg			   "for %s:%s\n", host, port);
151073143b9aSmrg		    return TRANS_CONNECT_FAILED;
151173143b9aSmrg		} else {
151273143b9aSmrg		    /* Go back to beginning of list */
151373143b9aSmrg		    resetonce = 1;
151473143b9aSmrg		    addrlist->addr = addrlist->firstaddr;
151573143b9aSmrg		}
1516fe567363Smrg	    }
151773143b9aSmrg
151873143b9aSmrg	    socketaddr = addrlist->addr->ai_addr;
151973143b9aSmrg	    socketaddrlen = addrlist->addr->ai_addrlen;
152073143b9aSmrg
152173143b9aSmrg	    if (addrlist->addr->ai_family == AF_INET) {
152273143b9aSmrg		struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
152373143b9aSmrg
1524fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n",
152573143b9aSmrg			inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
1526fe567363Smrg			ntopbuf,sizeof(ntopbuf)));
152773143b9aSmrg
1528fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n",
1529fe567363Smrg			ntohs(sin->sin_port));
153073143b9aSmrg
153173143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
153273143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
153373143b9aSmrg				"tcp") == 0) {
153473143b9aSmrg			XtransConnInfo newciptr;
153573143b9aSmrg
153673143b9aSmrg			/*
153773143b9aSmrg			 * Our socket is an IPv6 socket, but the address is
153873143b9aSmrg			 * IPv4.  Close it and get an IPv4 socket.  This is
153973143b9aSmrg			 * needed for IPv4 connections to work on platforms
154073143b9aSmrg			 * that don't allow IPv4 over IPv6 sockets.
154173143b9aSmrg			 */
154273143b9aSmrg			TRANS(SocketINETClose)(ciptr);
154373143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
154473143b9aSmrg					"tcp", "tcp", host, port, ciptr->index);
154573143b9aSmrg			if (newciptr)
154673143b9aSmrg			    ciptr->fd = newciptr->fd;
154773143b9aSmrg			if (!newciptr ||
154873143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
154973143b9aSmrg				AF_INET) {
155073143b9aSmrg			    socketaddr = NULL;
1551fe567363Smrg			    prmsg (4,"SocketINETConnect() Cannot get IPv4 "
1552fe567363Smrg					" socketfor IPv4 address\n");
155373143b9aSmrg			}
155473143b9aSmrg			if (newciptr)
1555fe567363Smrg			    free(newciptr);
155673143b9aSmrg		    } else {
155773143b9aSmrg			socketaddr = NULL;
1558fe567363Smrg			prmsg (4,"SocketINETConnect Skipping IPv4 address\n");
155973143b9aSmrg		    }
156073143b9aSmrg		}
156173143b9aSmrg	    } else if (addrlist->addr->ai_family == AF_INET6) {
156273143b9aSmrg		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
1563fe567363Smrg
1564fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
156573143b9aSmrg			inet_ntop(addrlist->addr->ai_family,
1566fe567363Smrg				  &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)));
1567fe567363Smrg		prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n",
1568fe567363Smrg			ntohs(sin6->sin6_port));
156973143b9aSmrg
157073143b9aSmrg		if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
157173143b9aSmrg		    if (strcmp(Sockettrans2devtab[ciptr->index].transname,
157273143b9aSmrg				"tcp") == 0) {
157373143b9aSmrg			XtransConnInfo newciptr;
157473143b9aSmrg
157573143b9aSmrg			/*
157673143b9aSmrg			 * Close the IPv4 socket and try to open an IPv6 socket.
157773143b9aSmrg			 */
157873143b9aSmrg			TRANS(SocketINETClose)(ciptr);
157973143b9aSmrg			newciptr = TRANS(SocketOpenCOTSClientBase)(
158073143b9aSmrg					"tcp", "tcp", host, port, -1);
158173143b9aSmrg			if (newciptr)
158273143b9aSmrg			    ciptr->fd = newciptr->fd;
158373143b9aSmrg			if (!newciptr ||
158473143b9aSmrg			    Sockettrans2devtab[newciptr->index].family !=
158573143b9aSmrg					AF_INET6) {
158673143b9aSmrg			    socketaddr = NULL;
1587fe567363Smrg			    prmsg (4,"SocketINETConnect() Cannot get IPv6 "
1588fe567363Smrg				   "socket for IPv6 address\n");
158973143b9aSmrg			}
159073143b9aSmrg			if (newciptr)
1591fe567363Smrg			    free(newciptr);
159273143b9aSmrg		    }
159373143b9aSmrg		    else
159473143b9aSmrg		    {
159573143b9aSmrg			socketaddr = NULL;
1596fe567363Smrg			prmsg (4,"SocketINETConnect() Skipping IPv6 address\n");
159773143b9aSmrg		    }
159873143b9aSmrg		}
159973143b9aSmrg	    } else {
160073143b9aSmrg		socketaddr = NULL; /* Unsupported address type */
160173143b9aSmrg	    }
160273143b9aSmrg	    if (socketaddr == NULL) {
160373143b9aSmrg		addrlist->addr = addrlist->addr->ai_next;
160473143b9aSmrg	    }
1605fe567363Smrg	}
1606b53e5eeaSmrg    }
1607b53e5eeaSmrg#else
160873143b9aSmrg    {
160973143b9aSmrg	/*
161073143b9aSmrg	 * Build the socket name.
161173143b9aSmrg	 */
161273143b9aSmrg
161373143b9aSmrg#ifdef BSD44SOCKETS
161473143b9aSmrg	sockname.sin_len = sizeof (struct sockaddr_in);
161573143b9aSmrg#endif
161673143b9aSmrg	sockname.sin_family = AF_INET;
161773143b9aSmrg
161873143b9aSmrg	/*
161973143b9aSmrg	 * fill in sin_addr
162073143b9aSmrg	 */
162173143b9aSmrg
162273143b9aSmrg#ifndef INADDR_NONE
162373143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff)
162473143b9aSmrg#endif
162573143b9aSmrg
162673143b9aSmrg	/* check for ww.xx.yy.zz host string */
162773143b9aSmrg
162873143b9aSmrg	if (isascii (host[0]) && isdigit (host[0])) {
162973143b9aSmrg	    tmpaddr = inet_addr (host); /* returns network byte order */
163073143b9aSmrg	} else {
163173143b9aSmrg	    tmpaddr = INADDR_NONE;
163273143b9aSmrg	}
163373143b9aSmrg
1634fe567363Smrg	prmsg (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr);
163573143b9aSmrg
163673143b9aSmrg	if (tmpaddr == INADDR_NONE) {
163773143b9aSmrg	    if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
1638fe567363Smrg		prmsg (1,"SocketINETConnect: Can't get address for %s\n",
1639fe567363Smrg			host);
164073143b9aSmrg		ESET(EINVAL);
164173143b9aSmrg		return TRANS_CONNECT_FAILED;
164273143b9aSmrg	    }
164373143b9aSmrg	    if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
1644fe567363Smrg		prmsg (1,"SocketINETConnect: not INET host%s\n", host);
164573143b9aSmrg		ESET(EPROTOTYPE);
164673143b9aSmrg		return TRANS_CONNECT_FAILED;
164773143b9aSmrg	    }
1648fe567363Smrg
164973143b9aSmrg	    memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
165073143b9aSmrg		    sizeof (sockname.sin_addr));
165173143b9aSmrg
165273143b9aSmrg	} else {
165373143b9aSmrg	    sockname.sin_addr.s_addr = tmpaddr;
165473143b9aSmrg        }
165573143b9aSmrg
165673143b9aSmrg	/*
165773143b9aSmrg	 * fill in sin_port
165873143b9aSmrg	 */
165973143b9aSmrg
166073143b9aSmrg	/* Check for number in the port string */
166173143b9aSmrg
166273143b9aSmrg	if (!is_numeric (port)) {
166373143b9aSmrg	    if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
1664fe567363Smrg		prmsg (1,"SocketINETConnect: can't get service for %s\n",
1665fe567363Smrg			port);
166673143b9aSmrg		return TRANS_CONNECT_FAILED;
166773143b9aSmrg	    }
166873143b9aSmrg	    sockname.sin_port = htons (servp->s_port);
166973143b9aSmrg	} else {
1670fe567363Smrg	    long tmpport = strtol (port, (char**)NULL, 10);
167173143b9aSmrg	    if (tmpport < 1024 || tmpport > USHRT_MAX)
167273143b9aSmrg		return TRANS_CONNECT_FAILED;
167373143b9aSmrg	    sockname.sin_port = htons (((unsigned short) tmpport));
167473143b9aSmrg	}
167573143b9aSmrg
1676fe567363Smrg	prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n",
1677fe567363Smrg		ntohs(sockname.sin_port));
167873143b9aSmrg	socketaddr = (struct sockaddr *) &sockname;
167973143b9aSmrg	socketaddrlen = sizeof(sockname);
168073143b9aSmrg    }
1681b53e5eeaSmrg#endif
168273143b9aSmrg
168373143b9aSmrg    /*
168473143b9aSmrg     * Turn on socket keepalive so the client process will eventually
168573143b9aSmrg     * be notified with a SIGPIPE signal if the display server fails
168673143b9aSmrg     * to respond to a periodic transmission of messages
168773143b9aSmrg     * on the connected socket.
168873143b9aSmrg     * This is useful to avoid hung application processes when the
168973143b9aSmrg     * processes are not spawned from the xdm session and
169073143b9aSmrg     * the display server terminates abnormally.
169173143b9aSmrg     * (Someone turned off the power switch.)
169273143b9aSmrg     */
169373143b9aSmrg
169473143b9aSmrg    {
169573143b9aSmrg	int tmp = 1;
169673143b9aSmrg	setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
169773143b9aSmrg		(char *) &tmp, sizeof (int));
169873143b9aSmrg    }
169973143b9aSmrg
170073143b9aSmrg    /*
170173143b9aSmrg     * Do the connect()
170273143b9aSmrg     */
170373143b9aSmrg
170473143b9aSmrg    if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
170573143b9aSmrg    {
170673143b9aSmrg#ifdef WIN32
170773143b9aSmrg	int olderrno = WSAGetLastError();
170873143b9aSmrg#else
170973143b9aSmrg	int olderrno = errno;
171073143b9aSmrg#endif
171173143b9aSmrg
171273143b9aSmrg	/*
171373143b9aSmrg	 * If the error was ECONNREFUSED, the server may be overloaded
171473143b9aSmrg	 * and we should try again.
171573143b9aSmrg	 *
171673143b9aSmrg	 * If the error was EWOULDBLOCK or EINPROGRESS then the socket
171773143b9aSmrg	 * was non-blocking and we should poll using select
171873143b9aSmrg	 *
171973143b9aSmrg	 * If the error was EINTR, the connect was interrupted and we
172073143b9aSmrg	 * should try again.
172173143b9aSmrg	 *
172273143b9aSmrg	 * If multiple addresses are found for a host then we should
172373143b9aSmrg	 * try to connect again with a different address for a larger
172473143b9aSmrg	 * number of errors that made us quit before, since those
172573143b9aSmrg	 * could be caused by trying to use an IPv6 address to contact
172673143b9aSmrg	 * a machine with an IPv4-only server or other reasons that
1727fe567363Smrg	 * only affect one of a set of addresses.
172873143b9aSmrg	 */
172973143b9aSmrg
173073143b9aSmrg	if (olderrno == ECONNREFUSED || olderrno == EINTR
173173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1732b53e5eeaSmrg	  || (((addrlist->addr->ai_next != NULL) ||
173373143b9aSmrg	        (addrlist->addr != addrlist->firstaddr)) &&
173473143b9aSmrg               (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
173573143b9aSmrg		 olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
173673143b9aSmrg#if defined(EHOSTDOWN)
173773143b9aSmrg		   || olderrno == EHOSTDOWN
173873143b9aSmrg#endif
173973143b9aSmrg	       ))
174073143b9aSmrg#endif
174173143b9aSmrg	    )
174273143b9aSmrg	    res = TRANS_TRY_CONNECT_AGAIN;
174373143b9aSmrg	else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
174473143b9aSmrg	    res = TRANS_IN_PROGRESS;
174573143b9aSmrg	else
174673143b9aSmrg	{
1747fe567363Smrg	    prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n",
1748fe567363Smrg		   olderrno);
174973143b9aSmrg
1750fe567363Smrg	    res = TRANS_CONNECT_FAILED;
175173143b9aSmrg	}
175273143b9aSmrg    } else {
175373143b9aSmrg	res = 0;
1754fe567363Smrg
175573143b9aSmrg
175673143b9aSmrg	/*
175773143b9aSmrg	 * Sync up the address fields of ciptr.
175873143b9aSmrg	 */
1759fe567363Smrg
176073143b9aSmrg	if (TRANS(SocketINETGetAddr) (ciptr) < 0)
176173143b9aSmrg	{
1762fe567363Smrg	    prmsg (1,
1763fe567363Smrg	     "SocketINETConnect: ...SocketINETGetAddr() failed:\n");
176473143b9aSmrg	    res = TRANS_CONNECT_FAILED;
176573143b9aSmrg	}
176673143b9aSmrg
176773143b9aSmrg	else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
176873143b9aSmrg	{
1769fe567363Smrg	    prmsg (1,
1770fe567363Smrg	      "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n");
177173143b9aSmrg	    res = TRANS_CONNECT_FAILED;
177273143b9aSmrg	}
177373143b9aSmrg    }
177473143b9aSmrg
177573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
1776b53e5eeaSmrg   if (res != 0) {
177773143b9aSmrg	addrlist->addr = addrlist->addr->ai_next;
177873143b9aSmrg   }
177973143b9aSmrg#endif
178073143b9aSmrg
178173143b9aSmrg    return res;
178273143b9aSmrg}
178373143b9aSmrg
178473143b9aSmrg#endif /* TCPCONN */
178573143b9aSmrg
178673143b9aSmrg
178773143b9aSmrg
178873143b9aSmrg#ifdef UNIXCONN
178973143b9aSmrg
179073143b9aSmrg/*
179173143b9aSmrg * Make sure 'host' is really local.
179273143b9aSmrg */
179373143b9aSmrg
179473143b9aSmrgstatic int
179573143b9aSmrgUnixHostReallyLocal (char *host)
179673143b9aSmrg
179773143b9aSmrg{
179873143b9aSmrg    char hostnamebuf[256];
179973143b9aSmrg
180073143b9aSmrg    TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
180173143b9aSmrg
180273143b9aSmrg    if (strcmp (hostnamebuf, host) == 0)
180373143b9aSmrg    {
180473143b9aSmrg	return (1);
1805b53e5eeaSmrg    } else {
180673143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
180773143b9aSmrg	struct addrinfo *localhostaddr;
180873143b9aSmrg	struct addrinfo *otherhostaddr;
180973143b9aSmrg	struct addrinfo *i, *j;
181073143b9aSmrg	int equiv = 0;
181173143b9aSmrg
181273143b9aSmrg	if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
181373143b9aSmrg	    return 0;
181473143b9aSmrg	if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
181573143b9aSmrg	    freeaddrinfo(localhostaddr);
181673143b9aSmrg	    return 0;
181773143b9aSmrg	}
181873143b9aSmrg
181973143b9aSmrg	for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
182073143b9aSmrg	    for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
182173143b9aSmrg		if (i->ai_family == j->ai_family) {
182273143b9aSmrg		    if (i->ai_family == AF_INET) {
1823fe567363Smrg			struct sockaddr_in *sinA
182473143b9aSmrg			  = (struct sockaddr_in *) i->ai_addr;
182573143b9aSmrg			struct sockaddr_in *sinB
182673143b9aSmrg			  = (struct sockaddr_in *) j->ai_addr;
182773143b9aSmrg			struct in_addr *A = &sinA->sin_addr;
182873143b9aSmrg			struct in_addr *B = &sinB->sin_addr;
182973143b9aSmrg
183073143b9aSmrg			if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
183173143b9aSmrg			    equiv = 1;
183273143b9aSmrg			}
183373143b9aSmrg		    } else if (i->ai_family == AF_INET6) {
1834fe567363Smrg			struct sockaddr_in6 *sinA
183573143b9aSmrg			  = (struct sockaddr_in6 *) i->ai_addr;
1836fe567363Smrg			struct sockaddr_in6 *sinB
183773143b9aSmrg			  = (struct sockaddr_in6 *) j->ai_addr;
183873143b9aSmrg			struct in6_addr *A = &sinA->sin6_addr;
183973143b9aSmrg			struct in6_addr *B = &sinB->sin6_addr;
184073143b9aSmrg
184173143b9aSmrg			if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
184273143b9aSmrg			    equiv = 1;
184373143b9aSmrg			}
184473143b9aSmrg		    }
184573143b9aSmrg		}
184673143b9aSmrg	    }
184773143b9aSmrg	}
1848fe567363Smrg
184973143b9aSmrg	freeaddrinfo(localhostaddr);
185073143b9aSmrg	freeaddrinfo(otherhostaddr);
185173143b9aSmrg	return equiv;
1852b53e5eeaSmrg#else
185373143b9aSmrg	/*
185473143b9aSmrg	 * A host may have more than one network address.  If any of the
185573143b9aSmrg	 * network addresses of 'host' (specified to the connect call)
185673143b9aSmrg	 * match any of the network addresses of 'hostname' (determined
185773143b9aSmrg	 * by TRANS(GetHostname)), then the two hostnames are equivalent,
185873143b9aSmrg	 * and we know that 'host' is really a local host.
185973143b9aSmrg	 */
186073143b9aSmrg	char specified_local_addr_list[10][4];
186173143b9aSmrg	int scount, equiv, i, j;
186273143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
186373143b9aSmrg	_Xgethostbynameparams hparams;
186473143b9aSmrg#endif
186573143b9aSmrg	struct hostent *hostp;
186673143b9aSmrg
186773143b9aSmrg	if ((hostp = _XGethostbyname (host,hparams)) == NULL)
186873143b9aSmrg	    return (0);
186973143b9aSmrg
187073143b9aSmrg	scount = 0;
187173143b9aSmrg	while (hostp->h_addr_list[scount] && scount <= 8)
187273143b9aSmrg	{
187373143b9aSmrg	    /*
187473143b9aSmrg	     * The 2nd call to gethostname() overrides the data
187573143b9aSmrg	     * from the 1st call, so we must save the address list.
187673143b9aSmrg	     */
187773143b9aSmrg
1878fe567363Smrg	    specified_local_addr_list[scount][0] =
187973143b9aSmrg				hostp->h_addr_list[scount][0];
1880fe567363Smrg	    specified_local_addr_list[scount][1] =
188173143b9aSmrg				hostp->h_addr_list[scount][1];
1882fe567363Smrg	    specified_local_addr_list[scount][2] =
188373143b9aSmrg				hostp->h_addr_list[scount][2];
1884fe567363Smrg	    specified_local_addr_list[scount][3] =
188573143b9aSmrg				hostp->h_addr_list[scount][3];
188673143b9aSmrg	    scount++;
188773143b9aSmrg	}
188873143b9aSmrg	if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
188973143b9aSmrg	    return (0);
189073143b9aSmrg
189173143b9aSmrg	equiv = 0;
189273143b9aSmrg	i = 0;
189373143b9aSmrg
189473143b9aSmrg	while (i < scount && !equiv)
189573143b9aSmrg	{
189673143b9aSmrg	    j = 0;
189773143b9aSmrg
189873143b9aSmrg	    while (hostp->h_addr_list[j])
189973143b9aSmrg	    {
1900fe567363Smrg		if ((specified_local_addr_list[i][0] ==
190173143b9aSmrg					hostp->h_addr_list[j][0]) &&
1902fe567363Smrg		    (specified_local_addr_list[i][1] ==
190373143b9aSmrg					hostp->h_addr_list[j][1]) &&
1904fe567363Smrg		    (specified_local_addr_list[i][2] ==
190573143b9aSmrg					hostp->h_addr_list[j][2]) &&
1906fe567363Smrg		    (specified_local_addr_list[i][3] ==
190773143b9aSmrg					hostp->h_addr_list[j][3]))
190873143b9aSmrg		{
190973143b9aSmrg		    /* They're equal, so we're done */
1910fe567363Smrg
191173143b9aSmrg		    equiv = 1;
191273143b9aSmrg		    break;
191373143b9aSmrg		}
191473143b9aSmrg
191573143b9aSmrg		j++;
191673143b9aSmrg	    }
191773143b9aSmrg
191873143b9aSmrg	    i++;
191973143b9aSmrg	}
192073143b9aSmrg	return (equiv);
1921b53e5eeaSmrg#endif
192273143b9aSmrg    }
192373143b9aSmrg}
192473143b9aSmrg
192573143b9aSmrgstatic int
192673143b9aSmrgTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
192773143b9aSmrg
192873143b9aSmrg{
192973143b9aSmrg    struct sockaddr_un	sockname;
193073143b9aSmrg    SOCKLEN_T		namelen;
193173143b9aSmrg
193273143b9aSmrg
193373143b9aSmrg    int abstract = 0;
193473143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
193573143b9aSmrg    abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
193673143b9aSmrg#endif
193773143b9aSmrg
1938fe567363Smrg    prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
1939fe567363Smrg
194073143b9aSmrg    /*
194173143b9aSmrg     * Make sure 'host' is really local.  If not, we return failure.
194273143b9aSmrg     * The reason we make this check is because a process may advertise
194373143b9aSmrg     * a "local" network ID for which it can accept connections, but if
194473143b9aSmrg     * a process on a remote machine tries to connect to this network ID,
194573143b9aSmrg     * we know for sure it will fail.
194673143b9aSmrg     */
194773143b9aSmrg
194873143b9aSmrg    if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
194973143b9aSmrg    {
1950fe567363Smrg	prmsg (1,
195173143b9aSmrg	   "SocketUNIXConnect: Cannot connect to non-local host %s\n",
1952fe567363Smrg	       host);
195373143b9aSmrg	return TRANS_CONNECT_FAILED;
195473143b9aSmrg    }
195573143b9aSmrg
195673143b9aSmrg
195773143b9aSmrg    /*
195873143b9aSmrg     * Check the port.
195973143b9aSmrg     */
196073143b9aSmrg
196173143b9aSmrg    if (!port || !*port)
196273143b9aSmrg    {
1963fe567363Smrg	prmsg (1,"SocketUNIXConnect: Missing port specification\n");
196473143b9aSmrg	return TRANS_CONNECT_FAILED;
196573143b9aSmrg    }
196673143b9aSmrg
196773143b9aSmrg    /*
196873143b9aSmrg     * Build the socket name.
196973143b9aSmrg     */
1970fe567363Smrg
197173143b9aSmrg    sockname.sun_family = AF_UNIX;
197273143b9aSmrg
197373143b9aSmrg    if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
1974fe567363Smrg	prmsg (1, "SocketUNIXConnect: path too long\n");
197573143b9aSmrg	return TRANS_CONNECT_FAILED;
197673143b9aSmrg    }
197773143b9aSmrg
1978fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
197973143b9aSmrg    sockname.sun_len = strlen (sockname.sun_path);
198073143b9aSmrg#endif
198173143b9aSmrg
198273143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN)
198373143b9aSmrg    namelen = SUN_LEN (&sockname);
198473143b9aSmrg#else
198573143b9aSmrg    namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
198673143b9aSmrg#endif
198773143b9aSmrg
198873143b9aSmrg
198973143b9aSmrg
199073143b9aSmrg    /*
199173143b9aSmrg     * Adjust the socket path if using abstract sockets.
199273143b9aSmrg     * Done here because otherwise all the strlen() calls above would fail.
199373143b9aSmrg     */
199473143b9aSmrg
199573143b9aSmrg    if (abstract) {
199673143b9aSmrg	sockname.sun_path[0] = '\0';
199773143b9aSmrg    }
199873143b9aSmrg
199973143b9aSmrg    /*
200073143b9aSmrg     * Do the connect()
200173143b9aSmrg     */
200273143b9aSmrg
200373143b9aSmrg    if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
200473143b9aSmrg    {
200573143b9aSmrg	int olderrno = errno;
200673143b9aSmrg	int connected = 0;
2007fe567363Smrg
200873143b9aSmrg	if (!connected)
200973143b9aSmrg	{
201073143b9aSmrg	    errno = olderrno;
2011fe567363Smrg
201273143b9aSmrg	    /*
201373143b9aSmrg	     * If the error was ENOENT, the server may be starting up; we used
201473143b9aSmrg	     * to suggest to try again in this case with
201573143b9aSmrg	     * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
201673143b9aSmrg	     * processes still referencing stale sockets in their environment.
201773143b9aSmrg	     * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
201873143b9aSmrg	     * is suggested that higher level stacks handle retries on their
201973143b9aSmrg	     * level when they face a slow starting server.
202073143b9aSmrg	     *
202173143b9aSmrg	     * If the error was EWOULDBLOCK or EINPROGRESS then the socket
202273143b9aSmrg	     * was non-blocking and we should poll using select
202373143b9aSmrg	     *
202473143b9aSmrg	     * If the error was EINTR, the connect was interrupted and we
202573143b9aSmrg	     * should try again.
202673143b9aSmrg	     */
202773143b9aSmrg
202873143b9aSmrg	    if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
202973143b9aSmrg		return TRANS_IN_PROGRESS;
203073143b9aSmrg	    else if (olderrno == EINTR)
203173143b9aSmrg		return TRANS_TRY_CONNECT_AGAIN;
20328d4c0f7bSmrg	    else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
203373143b9aSmrg		/* If opening as abstract socket failed, try again normally */
203473143b9aSmrg		if (abstract) {
203573143b9aSmrg		    ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
203673143b9aSmrg		    return TRANS_TRY_CONNECT_AGAIN;
203773143b9aSmrg		} else {
203873143b9aSmrg		    return TRANS_CONNECT_FAILED;
203973143b9aSmrg		}
204073143b9aSmrg	    } else {
2041fe567363Smrg		prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
2042fe567363Smrg		       EGET());
204373143b9aSmrg
204473143b9aSmrg		return TRANS_CONNECT_FAILED;
204573143b9aSmrg	    }
204673143b9aSmrg	}
204773143b9aSmrg    }
204873143b9aSmrg
204973143b9aSmrg    /*
205073143b9aSmrg     * Get the socket name and the peer name from the connect socket,
205173143b9aSmrg     * since this is unix domain.
205273143b9aSmrg     */
205373143b9aSmrg
2054fe567363Smrg    if ((ciptr->addr = malloc(namelen)) == NULL ||
2055fe567363Smrg       (ciptr->peeraddr = malloc(namelen)) == NULL)
205673143b9aSmrg    {
2057fe567363Smrg        prmsg (1,
2058fe567363Smrg	"SocketUNIXCreateListener: Can't allocate space for the addr\n");
205973143b9aSmrg        return TRANS_CONNECT_FAILED;
206073143b9aSmrg    }
206173143b9aSmrg
206273143b9aSmrg    if (abstract)
206373143b9aSmrg	sockname.sun_path[0] = '@';
206473143b9aSmrg
206573143b9aSmrg    ciptr->family = AF_UNIX;
206673143b9aSmrg    ciptr->addrlen = namelen;
206773143b9aSmrg    ciptr->peeraddrlen = namelen;
206873143b9aSmrg    memcpy (ciptr->addr, &sockname, ciptr->addrlen);
206973143b9aSmrg    memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
207073143b9aSmrg
207173143b9aSmrg    return 0;
207273143b9aSmrg}
207373143b9aSmrg
207473143b9aSmrg#endif /* UNIXCONN */
207573143b9aSmrg
207673143b9aSmrg#endif /* TRANS_CLIENT */
207773143b9aSmrg
207873143b9aSmrg
207973143b9aSmrgstatic int
208073143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
208173143b9aSmrg
208273143b9aSmrg{
2083fe567363Smrg    prmsg (2,"SocketBytesReadable(%p,%d,%p)\n",
208473143b9aSmrg	ciptr, ciptr->fd, pend);
208573143b9aSmrg#ifdef WIN32
208673143b9aSmrg    {
208773143b9aSmrg	int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
208873143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
208973143b9aSmrg	return ret;
209073143b9aSmrg    }
209173143b9aSmrg#else
2092fe567363Smrg#if defined(__i386__) && defined(SYSV) && !defined(SCO325)
209373143b9aSmrg    return ioctl (ciptr->fd, I_NREAD, (char *) pend);
209473143b9aSmrg#else
209573143b9aSmrg    return ioctl (ciptr->fd, FIONREAD, (char *) pend);
209673143b9aSmrg#endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
209773143b9aSmrg#endif /* WIN32 */
209873143b9aSmrg}
209973143b9aSmrg
210073143b9aSmrg
210173143b9aSmrgstatic int
210273143b9aSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
210373143b9aSmrg
210473143b9aSmrg{
2105fe567363Smrg    prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
210673143b9aSmrg
2107fe567363Smrg#if defined(WIN32)
210873143b9aSmrg    {
210973143b9aSmrg	int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
211073143b9aSmrg#ifdef WIN32
211173143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
211273143b9aSmrg#endif
211373143b9aSmrg	return ret;
211473143b9aSmrg    }
211573143b9aSmrg#else
211673143b9aSmrg    return read (ciptr->fd, buf, size);
211773143b9aSmrg#endif /* WIN32 */
211873143b9aSmrg}
211973143b9aSmrg
212073143b9aSmrg
212173143b9aSmrgstatic int
212273143b9aSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
212373143b9aSmrg
212473143b9aSmrg{
2125fe567363Smrg    prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
212673143b9aSmrg
2127fe567363Smrg#if defined(WIN32)
212873143b9aSmrg    {
212973143b9aSmrg	int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
213073143b9aSmrg#ifdef WIN32
213173143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
213273143b9aSmrg#endif
213373143b9aSmrg	return ret;
213473143b9aSmrg    }
213573143b9aSmrg#else
213673143b9aSmrg    return write (ciptr->fd, buf, size);
213773143b9aSmrg#endif /* WIN32 */
213873143b9aSmrg}
213973143b9aSmrg
214073143b9aSmrg
214173143b9aSmrgstatic int
214273143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
214373143b9aSmrg
214473143b9aSmrg{
2145fe567363Smrg    prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
214673143b9aSmrg
214773143b9aSmrg    return READV (ciptr, buf, size);
214873143b9aSmrg}
214973143b9aSmrg
215073143b9aSmrg
215173143b9aSmrgstatic int
215273143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
215373143b9aSmrg
215473143b9aSmrg{
2155fe567363Smrg    prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
215673143b9aSmrg
215773143b9aSmrg    return WRITEV (ciptr, buf, size);
215873143b9aSmrg}
215973143b9aSmrg
216073143b9aSmrg
216173143b9aSmrgstatic int
216273143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr)
216373143b9aSmrg
216473143b9aSmrg{
2165fe567363Smrg    prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd);
216673143b9aSmrg
216773143b9aSmrg#ifdef WIN32
2168fe567363Smrg    {
216973143b9aSmrg	int ret = shutdown (ciptr->fd, 2);
217073143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
217173143b9aSmrg	return ret;
217273143b9aSmrg    }
217373143b9aSmrg#else
217473143b9aSmrg    return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
217573143b9aSmrg#endif
217673143b9aSmrg}
217773143b9aSmrg
217873143b9aSmrg
217973143b9aSmrg#ifdef TCPCONN
218073143b9aSmrgstatic int
218173143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr)
218273143b9aSmrg
218373143b9aSmrg{
2184fe567363Smrg    prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd);
218573143b9aSmrg
218673143b9aSmrg#ifdef WIN32
218773143b9aSmrg    {
218873143b9aSmrg	int ret = close (ciptr->fd);
218973143b9aSmrg	if (ret == SOCKET_ERROR) errno = WSAGetLastError();
219073143b9aSmrg	return ret;
219173143b9aSmrg    }
219273143b9aSmrg#else
219373143b9aSmrg    return close (ciptr->fd);
219473143b9aSmrg#endif
219573143b9aSmrg}
219673143b9aSmrg
219773143b9aSmrg#endif /* TCPCONN */
219873143b9aSmrg
219973143b9aSmrg
220073143b9aSmrg#ifdef UNIXCONN
220173143b9aSmrgstatic int
220273143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr)
220373143b9aSmrg{
220473143b9aSmrg    /*
220573143b9aSmrg     * If this is the server side, then once the socket is closed,
220673143b9aSmrg     * it must be unlinked to completely close it
220773143b9aSmrg     */
220873143b9aSmrg
220973143b9aSmrg    struct sockaddr_un	*sockname = (struct sockaddr_un *) ciptr->addr;
221073143b9aSmrg    int ret;
221173143b9aSmrg
2212fe567363Smrg    prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd);
221373143b9aSmrg
221473143b9aSmrg    ret = close(ciptr->fd);
221573143b9aSmrg
221673143b9aSmrg    if (ciptr->flags
221773143b9aSmrg       && sockname
221873143b9aSmrg       && sockname->sun_family == AF_UNIX
221973143b9aSmrg       && sockname->sun_path[0])
222073143b9aSmrg    {
222173143b9aSmrg	if (!(ciptr->flags & TRANS_NOUNLINK
222273143b9aSmrg	    || ciptr->transptr->flags & TRANS_ABSTRACT))
222373143b9aSmrg		unlink (sockname->sun_path);
222473143b9aSmrg    }
222573143b9aSmrg
222673143b9aSmrg    return ret;
222773143b9aSmrg}
222873143b9aSmrg
222973143b9aSmrgstatic int
223073143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
223173143b9aSmrg
223273143b9aSmrg{
223373143b9aSmrg    /*
223473143b9aSmrg     * Don't unlink path.
223573143b9aSmrg     */
223673143b9aSmrg
223773143b9aSmrg    int ret;
223873143b9aSmrg
2239fe567363Smrg    prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n",
2240fe567363Smrg	ciptr, ciptr->fd);
224173143b9aSmrg
224273143b9aSmrg    ret = close(ciptr->fd);
224373143b9aSmrg
224473143b9aSmrg    return ret;
224573143b9aSmrg}
224673143b9aSmrg
224773143b9aSmrg#endif /* UNIXCONN */
224873143b9aSmrg
224973143b9aSmrg
225073143b9aSmrg#ifdef TCPCONN
225173143b9aSmrg# ifdef TRANS_SERVER
2252fe567363Smrgstatic const char* tcp_nolisten[] = {
225373143b9aSmrg	"inet",
225473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
225573143b9aSmrg	"inet6",
225673143b9aSmrg#endif
225773143b9aSmrg	NULL
225873143b9aSmrg};
225973143b9aSmrg# endif
226073143b9aSmrg
226173143b9aSmrgXtransport	TRANS(SocketTCPFuncs) = {
226273143b9aSmrg	/* Socket Interface */
226373143b9aSmrg	"tcp",
226473143b9aSmrg        TRANS_ALIAS,
226573143b9aSmrg#ifdef TRANS_CLIENT
226673143b9aSmrg	TRANS(SocketOpenCOTSClient),
226773143b9aSmrg#endif /* TRANS_CLIENT */
226873143b9aSmrg#ifdef TRANS_SERVER
226973143b9aSmrg	tcp_nolisten,
227073143b9aSmrg	TRANS(SocketOpenCOTSServer),
227173143b9aSmrg#endif /* TRANS_SERVER */
227273143b9aSmrg#ifdef TRANS_CLIENT
227373143b9aSmrg	TRANS(SocketOpenCLTSClient),
227473143b9aSmrg#endif /* TRANS_CLIENT */
227573143b9aSmrg#ifdef TRANS_SERVER
227673143b9aSmrg	TRANS(SocketOpenCLTSServer),
227773143b9aSmrg#endif /* TRANS_SERVER */
227873143b9aSmrg#ifdef TRANS_REOPEN
227973143b9aSmrg	TRANS(SocketReopenCOTSServer),
228073143b9aSmrg	TRANS(SocketReopenCLTSServer),
228173143b9aSmrg#endif
228273143b9aSmrg	TRANS(SocketSetOption),
228373143b9aSmrg#ifdef TRANS_SERVER
228473143b9aSmrg	TRANS(SocketINETCreateListener),
228573143b9aSmrg	NULL,		       			/* ResetListener */
228673143b9aSmrg	TRANS(SocketINETAccept),
228773143b9aSmrg#endif /* TRANS_SERVER */
228873143b9aSmrg#ifdef TRANS_CLIENT
228973143b9aSmrg	TRANS(SocketINETConnect),
229073143b9aSmrg#endif /* TRANS_CLIENT */
229173143b9aSmrg	TRANS(SocketBytesReadable),
229273143b9aSmrg	TRANS(SocketRead),
229373143b9aSmrg	TRANS(SocketWrite),
229473143b9aSmrg	TRANS(SocketReadv),
229573143b9aSmrg	TRANS(SocketWritev),
229673143b9aSmrg	TRANS(SocketDisconnect),
229773143b9aSmrg	TRANS(SocketINETClose),
229873143b9aSmrg	TRANS(SocketINETClose),
229973143b9aSmrg	};
230073143b9aSmrg
230173143b9aSmrgXtransport	TRANS(SocketINETFuncs) = {
230273143b9aSmrg	/* Socket Interface */
230373143b9aSmrg	"inet",
230473143b9aSmrg	0,
230573143b9aSmrg#ifdef TRANS_CLIENT
230673143b9aSmrg	TRANS(SocketOpenCOTSClient),
230773143b9aSmrg#endif /* TRANS_CLIENT */
230873143b9aSmrg#ifdef TRANS_SERVER
230973143b9aSmrg	NULL,
231073143b9aSmrg	TRANS(SocketOpenCOTSServer),
231173143b9aSmrg#endif /* TRANS_SERVER */
231273143b9aSmrg#ifdef TRANS_CLIENT
231373143b9aSmrg	TRANS(SocketOpenCLTSClient),
231473143b9aSmrg#endif /* TRANS_CLIENT */
231573143b9aSmrg#ifdef TRANS_SERVER
231673143b9aSmrg	TRANS(SocketOpenCLTSServer),
231773143b9aSmrg#endif /* TRANS_SERVER */
231873143b9aSmrg#ifdef TRANS_REOPEN
231973143b9aSmrg	TRANS(SocketReopenCOTSServer),
232073143b9aSmrg	TRANS(SocketReopenCLTSServer),
232173143b9aSmrg#endif
232273143b9aSmrg	TRANS(SocketSetOption),
232373143b9aSmrg#ifdef TRANS_SERVER
232473143b9aSmrg	TRANS(SocketINETCreateListener),
232573143b9aSmrg	NULL,		       			/* ResetListener */
232673143b9aSmrg	TRANS(SocketINETAccept),
232773143b9aSmrg#endif /* TRANS_SERVER */
232873143b9aSmrg#ifdef TRANS_CLIENT
232973143b9aSmrg	TRANS(SocketINETConnect),
233073143b9aSmrg#endif /* TRANS_CLIENT */
233173143b9aSmrg	TRANS(SocketBytesReadable),
233273143b9aSmrg	TRANS(SocketRead),
233373143b9aSmrg	TRANS(SocketWrite),
233473143b9aSmrg	TRANS(SocketReadv),
233573143b9aSmrg	TRANS(SocketWritev),
233673143b9aSmrg	TRANS(SocketDisconnect),
233773143b9aSmrg	TRANS(SocketINETClose),
233873143b9aSmrg	TRANS(SocketINETClose),
233973143b9aSmrg	};
234073143b9aSmrg
234173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
234273143b9aSmrgXtransport     TRANS(SocketINET6Funcs) = {
234373143b9aSmrg	/* Socket Interface */
234473143b9aSmrg	"inet6",
234573143b9aSmrg	0,
234673143b9aSmrg#ifdef TRANS_CLIENT
234773143b9aSmrg	TRANS(SocketOpenCOTSClient),
234873143b9aSmrg#endif /* TRANS_CLIENT */
234973143b9aSmrg#ifdef TRANS_SERVER
235073143b9aSmrg	NULL,
235173143b9aSmrg	TRANS(SocketOpenCOTSServer),
235273143b9aSmrg#endif /* TRANS_SERVER */
235373143b9aSmrg#ifdef TRANS_CLIENT
235473143b9aSmrg	TRANS(SocketOpenCLTSClient),
235573143b9aSmrg#endif /* TRANS_CLIENT */
235673143b9aSmrg#ifdef TRANS_SERVER
235773143b9aSmrg	TRANS(SocketOpenCLTSServer),
235873143b9aSmrg#endif /* TRANS_SERVER */
235973143b9aSmrg#ifdef TRANS_REOPEN
236073143b9aSmrg	TRANS(SocketReopenCOTSServer),
236173143b9aSmrg	TRANS(SocketReopenCLTSServer),
236273143b9aSmrg#endif
236373143b9aSmrg	TRANS(SocketSetOption),
236473143b9aSmrg#ifdef TRANS_SERVER
236573143b9aSmrg	TRANS(SocketINETCreateListener),
236673143b9aSmrg	NULL,					/* ResetListener */
236773143b9aSmrg	TRANS(SocketINETAccept),
236873143b9aSmrg#endif /* TRANS_SERVER */
236973143b9aSmrg#ifdef TRANS_CLIENT
237073143b9aSmrg	TRANS(SocketINETConnect),
237173143b9aSmrg#endif /* TRANS_CLIENT */
237273143b9aSmrg	TRANS(SocketBytesReadable),
237373143b9aSmrg	TRANS(SocketRead),
237473143b9aSmrg	TRANS(SocketWrite),
237573143b9aSmrg	TRANS(SocketReadv),
237673143b9aSmrg	TRANS(SocketWritev),
237773143b9aSmrg	TRANS(SocketDisconnect),
237873143b9aSmrg	TRANS(SocketINETClose),
237973143b9aSmrg	TRANS(SocketINETClose),
238073143b9aSmrg	};
238173143b9aSmrg#endif /* IPv6 */
238273143b9aSmrg#endif /* TCPCONN */
238373143b9aSmrg
238473143b9aSmrg#ifdef UNIXCONN
238573143b9aSmrg#if !defined(LOCALCONN)
238673143b9aSmrgXtransport	TRANS(SocketLocalFuncs) = {
238773143b9aSmrg	/* Socket Interface */
238873143b9aSmrg	"local",
238973143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS
239073143b9aSmrg	TRANS_ABSTRACT,
239173143b9aSmrg#else
239273143b9aSmrg	0,
239373143b9aSmrg#endif
239473143b9aSmrg#ifdef TRANS_CLIENT
239573143b9aSmrg	TRANS(SocketOpenCOTSClient),
239673143b9aSmrg#endif /* TRANS_CLIENT */
239773143b9aSmrg#ifdef TRANS_SERVER
239873143b9aSmrg	NULL,
239973143b9aSmrg	TRANS(SocketOpenCOTSServer),
240073143b9aSmrg#endif /* TRANS_SERVER */
240173143b9aSmrg#ifdef TRANS_CLIENT
240273143b9aSmrg	TRANS(SocketOpenCLTSClient),
240373143b9aSmrg#endif /* TRANS_CLIENT */
240473143b9aSmrg#ifdef TRANS_SERVER
240573143b9aSmrg	TRANS(SocketOpenCLTSServer),
240673143b9aSmrg#endif /* TRANS_SERVER */
240773143b9aSmrg#ifdef TRANS_REOPEN
240873143b9aSmrg	TRANS(SocketReopenCOTSServer),
240973143b9aSmrg	TRANS(SocketReopenCLTSServer),
241073143b9aSmrg#endif
241173143b9aSmrg	TRANS(SocketSetOption),
241273143b9aSmrg#ifdef TRANS_SERVER
241373143b9aSmrg	TRANS(SocketUNIXCreateListener),
241473143b9aSmrg	TRANS(SocketUNIXResetListener),
241573143b9aSmrg	TRANS(SocketUNIXAccept),
241673143b9aSmrg#endif /* TRANS_SERVER */
241773143b9aSmrg#ifdef TRANS_CLIENT
241873143b9aSmrg	TRANS(SocketUNIXConnect),
241973143b9aSmrg#endif /* TRANS_CLIENT */
242073143b9aSmrg	TRANS(SocketBytesReadable),
242173143b9aSmrg	TRANS(SocketRead),
242273143b9aSmrg	TRANS(SocketWrite),
242373143b9aSmrg	TRANS(SocketReadv),
242473143b9aSmrg	TRANS(SocketWritev),
242573143b9aSmrg	TRANS(SocketDisconnect),
242673143b9aSmrg	TRANS(SocketUNIXClose),
242773143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
242873143b9aSmrg	};
242973143b9aSmrg#endif /* !LOCALCONN */
243073143b9aSmrg# ifdef TRANS_SERVER
243173143b9aSmrg#  if !defined(LOCALCONN)
243273143b9aSmrgstatic char* unix_nolisten[] = { "local" , NULL };
243373143b9aSmrg#  endif
243473143b9aSmrg# endif
2435fe567363Smrg
243673143b9aSmrgXtransport	TRANS(SocketUNIXFuncs) = {
243773143b9aSmrg	/* Socket Interface */
243873143b9aSmrg	"unix",
243973143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
244073143b9aSmrg        TRANS_ALIAS,
244173143b9aSmrg#else
244273143b9aSmrg	0,
244373143b9aSmrg#endif
244473143b9aSmrg#ifdef TRANS_CLIENT
244573143b9aSmrg	TRANS(SocketOpenCOTSClient),
244673143b9aSmrg#endif /* TRANS_CLIENT */
244773143b9aSmrg#ifdef TRANS_SERVER
244873143b9aSmrg#if !defined(LOCALCONN)
244973143b9aSmrg	unix_nolisten,
245073143b9aSmrg#else
245173143b9aSmrg	NULL,
245273143b9aSmrg#endif
245373143b9aSmrg	TRANS(SocketOpenCOTSServer),
245473143b9aSmrg#endif /* TRANS_SERVER */
245573143b9aSmrg#ifdef TRANS_CLIENT
245673143b9aSmrg	TRANS(SocketOpenCLTSClient),
245773143b9aSmrg#endif /* TRANS_CLIENT */
245873143b9aSmrg#ifdef TRANS_SERVER
245973143b9aSmrg	TRANS(SocketOpenCLTSServer),
246073143b9aSmrg#endif /* TRANS_SERVER */
246173143b9aSmrg#ifdef TRANS_REOPEN
246273143b9aSmrg	TRANS(SocketReopenCOTSServer),
246373143b9aSmrg	TRANS(SocketReopenCLTSServer),
246473143b9aSmrg#endif
246573143b9aSmrg	TRANS(SocketSetOption),
246673143b9aSmrg#ifdef TRANS_SERVER
246773143b9aSmrg	TRANS(SocketUNIXCreateListener),
246873143b9aSmrg	TRANS(SocketUNIXResetListener),
246973143b9aSmrg	TRANS(SocketUNIXAccept),
247073143b9aSmrg#endif /* TRANS_SERVER */
247173143b9aSmrg#ifdef TRANS_CLIENT
247273143b9aSmrg	TRANS(SocketUNIXConnect),
247373143b9aSmrg#endif /* TRANS_CLIENT */
247473143b9aSmrg	TRANS(SocketBytesReadable),
247573143b9aSmrg	TRANS(SocketRead),
247673143b9aSmrg	TRANS(SocketWrite),
247773143b9aSmrg	TRANS(SocketReadv),
247873143b9aSmrg	TRANS(SocketWritev),
247973143b9aSmrg	TRANS(SocketDisconnect),
248073143b9aSmrg	TRANS(SocketUNIXClose),
248173143b9aSmrg	TRANS(SocketUNIXCloseForCloning),
248273143b9aSmrg	};
248373143b9aSmrg
248473143b9aSmrg#endif /* UNIXCONN */
2485