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