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