Xtranssock.c revision 81d6fa61
1af928962Smrg/* 2af928962Smrg * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. 3af928962Smrg * 4af928962Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5af928962Smrg * copy of this software and associated documentation files (the "Software"), 6af928962Smrg * to deal in the Software without restriction, including without limitation 7af928962Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af928962Smrg * and/or sell copies of the Software, and to permit persons to whom the 9af928962Smrg * Software is furnished to do so, subject to the following conditions: 10af928962Smrg * 11af928962Smrg * The above copyright notice and this permission notice (including the next 12af928962Smrg * paragraph) shall be included in all copies or substantial portions of the 13af928962Smrg * Software. 14af928962Smrg * 15af928962Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af928962Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af928962Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af928962Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af928962Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20af928962Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21af928962Smrg * DEALINGS IN THE SOFTWARE. 22af928962Smrg */ 2373143b9aSmrg/* 2473143b9aSmrg 2573143b9aSmrgCopyright 1993, 1994, 1998 The Open Group 2673143b9aSmrg 2773143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its 2873143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that 2973143b9aSmrgthe above copyright notice appear in all copies and that both that 3073143b9aSmrgcopyright notice and this permission notice appear in supporting 3173143b9aSmrgdocumentation. 3273143b9aSmrg 3373143b9aSmrgThe above copyright notice and this permission notice shall be included 3473143b9aSmrgin all copies or substantial portions of the Software. 3573143b9aSmrg 3673143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 3773143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3873143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 3973143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 4073143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 4173143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 4273143b9aSmrgOTHER DEALINGS IN THE SOFTWARE. 4373143b9aSmrg 4473143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall 4573143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or 4673143b9aSmrgother dealings in this Software without prior written authorization 4773143b9aSmrgfrom the copyright holders. 4873143b9aSmrg 4973143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA 5073143b9aSmrg * 5173143b9aSmrg * All Rights Reserved 5273143b9aSmrg * 5373143b9aSmrg * Permission to use, copy, modify, and distribute this software and its 5473143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided 5573143b9aSmrg * that the above copyright notice appear in all copies and that both that 5673143b9aSmrg * copyright notice and this permission notice appear in supporting 5773143b9aSmrg * documentation, and that the name NCR not be used in advertising 5873143b9aSmrg * or publicity pertaining to distribution of the software without specific, 5973143b9aSmrg * written prior permission. NCR makes no representations about the 6073143b9aSmrg * suitability of this software for any purpose. It is provided "as is" 6173143b9aSmrg * without express or implied warranty. 6273143b9aSmrg * 6373143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 6473143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 6573143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR 6673143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 6773143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 6873143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 6973143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 7073143b9aSmrg */ 7173143b9aSmrg 7273143b9aSmrg#include <ctype.h> 7373143b9aSmrg#ifdef XTHREADS 7473143b9aSmrg#include <X11/Xthreads.h> 7573143b9aSmrg#endif 7673143b9aSmrg 7773143b9aSmrg#ifndef WIN32 7873143b9aSmrg 7973143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8073143b9aSmrg#include <sys/socket.h> 8173143b9aSmrg#include <netinet/in.h> 8273143b9aSmrg#include <arpa/inet.h> 8373143b9aSmrg#endif 8473143b9aSmrg 8573143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8673143b9aSmrg#define X_INCLUDE_NETDB_H 8773143b9aSmrg#define XOS_USE_NO_LOCKING 8873143b9aSmrg#include <X11/Xos_r.h> 8973143b9aSmrg#endif 9073143b9aSmrg 9173143b9aSmrg#ifdef UNIXCONN 9273143b9aSmrg#ifndef X_NO_SYS_UN 9373143b9aSmrg#include <sys/un.h> 9473143b9aSmrg#endif 9573143b9aSmrg#include <sys/stat.h> 9673143b9aSmrg#endif 9773143b9aSmrg 9873143b9aSmrg 9973143b9aSmrg#ifndef NO_TCP_H 100fe567363Smrg#if defined(linux) || defined(__GLIBC__) 10173143b9aSmrg#include <sys/param.h> 10273143b9aSmrg#endif /* osf */ 10373143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 10473143b9aSmrg#include <sys/param.h> 10573143b9aSmrg#include <machine/endian.h> 10673143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */ 10773143b9aSmrg#include <netinet/tcp.h> 10873143b9aSmrg#endif /* !NO_TCP_H */ 10973143b9aSmrg 11073143b9aSmrg#include <sys/ioctl.h> 111e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 11273143b9aSmrg#include <sys/filio.h> 11373143b9aSmrg#endif 11473143b9aSmrg 11573143b9aSmrg#if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun) 11673143b9aSmrg#include <net/errno.h> 117fe567363Smrg#endif 11873143b9aSmrg 119fe567363Smrg#if defined(__i386__) && defined(SYSV) 12073143b9aSmrg#include <sys/stropts.h> 121fe567363Smrg#endif 12273143b9aSmrg 1238d4c0f7bSmrg#include <unistd.h> 1248d4c0f7bSmrg 12573143b9aSmrg#else /* !WIN32 */ 12673143b9aSmrg 12773143b9aSmrg#include <X11/Xwinsock.h> 12873143b9aSmrg#include <X11/Xwindows.h> 12973143b9aSmrg#include <X11/Xw32defs.h> 13073143b9aSmrg#undef close 13173143b9aSmrg#define close closesocket 13273143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED 13373143b9aSmrg#define EADDRINUSE WSAEADDRINUSE 13473143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE 13573143b9aSmrg#undef EWOULDBLOCK 13673143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK 13773143b9aSmrg#define EINPROGRESS WSAEINPROGRESS 13873143b9aSmrg#undef EINTR 13973143b9aSmrg#define EINTR WSAEINTR 14073143b9aSmrg#define X_INCLUDE_NETDB_H 14173143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI 14273143b9aSmrg#include <X11/Xos_r.h> 14373143b9aSmrg#endif /* WIN32 */ 14473143b9aSmrg 14573143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER) 14673143b9aSmrg#undef SO_DONTLINGER 14773143b9aSmrg#endif 14873143b9aSmrg 14973143b9aSmrg/* others don't need this */ 15073143b9aSmrg#define SocketInitOnce() /**/ 15173143b9aSmrg 15273143b9aSmrg#ifdef linux 15373143b9aSmrg#define HAVE_ABSTRACT_SOCKETS 15473143b9aSmrg#endif 15573143b9aSmrg 15673143b9aSmrg#define MIN_BACKLOG 128 15773143b9aSmrg#ifdef SOMAXCONN 15873143b9aSmrg#if SOMAXCONN > MIN_BACKLOG 15973143b9aSmrg#define BACKLOG SOMAXCONN 16073143b9aSmrg#endif 16173143b9aSmrg#endif 16273143b9aSmrg#ifndef BACKLOG 16373143b9aSmrg#define BACKLOG MIN_BACKLOG 16473143b9aSmrg#endif 16573143b9aSmrg 16673143b9aSmrg/* 16773143b9aSmrg * This is the Socket implementation of the X Transport service layer 16873143b9aSmrg * 16973143b9aSmrg * This file contains the implementation for both the UNIX and INET domains, 17073143b9aSmrg * and can be built for either one, or both. 17173143b9aSmrg * 17273143b9aSmrg */ 17373143b9aSmrg 174fe567363Smrgtypedef struct _Sockettrans2dev { 175fe567363Smrg const char *transname; 17673143b9aSmrg int family; 17773143b9aSmrg int devcotsname; 17873143b9aSmrg int devcltsname; 17973143b9aSmrg int protocol; 18073143b9aSmrg} Sockettrans2dev; 18173143b9aSmrg 18273143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = { 18373143b9aSmrg#ifdef TCPCONN 18473143b9aSmrg {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 18573143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6) 18673143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 18773143b9aSmrg#else /* IPv6 */ 18873143b9aSmrg {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 18973143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ 19073143b9aSmrg {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 19173143b9aSmrg#endif 19273143b9aSmrg#endif /* TCPCONN */ 19373143b9aSmrg#ifdef UNIXCONN 19473143b9aSmrg {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 19573143b9aSmrg#if !defined(LOCALCONN) 19673143b9aSmrg {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 19773143b9aSmrg#endif /* !LOCALCONN */ 19873143b9aSmrg#endif /* UNIXCONN */ 19973143b9aSmrg}; 20073143b9aSmrg 20173143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev)) 20273143b9aSmrg 20373143b9aSmrg#ifdef TCPCONN 20473143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr); 20573143b9aSmrg#endif 20673143b9aSmrg 20773143b9aSmrg#ifdef UNIXCONN 20873143b9aSmrg 20973143b9aSmrg 21073143b9aSmrg#if defined(X11_t) 21173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 21273143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 21373143b9aSmrg#endif /* X11_t */ 21473143b9aSmrg#if defined(XIM_t) 21573143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM" 21673143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix" 21773143b9aSmrg#endif /* XIM_t */ 21873143b9aSmrg#if defined(FS_t) || defined(FONT_t) 21973143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs" 22073143b9aSmrg#define UNIX_DIR "/tmp/.font-unix" 22173143b9aSmrg#endif /* FS_t || FONT_t */ 22273143b9aSmrg#if defined(ICE_t) 22373143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/" 22473143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix" 22573143b9aSmrg#endif /* ICE_t */ 22673143b9aSmrg#if defined(TEST_t) 22773143b9aSmrg#define UNIX_PATH "/tmp/.Test-unix/test" 22873143b9aSmrg#define UNIX_DIR "/tmp/.Test-unix" 22973143b9aSmrg#endif 23073143b9aSmrg#if defined(LBXPROXY_t) 23173143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 23273143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 23373143b9aSmrg#endif 23473143b9aSmrg 23573143b9aSmrg 23673143b9aSmrg#endif /* UNIXCONN */ 23773143b9aSmrg 23873143b9aSmrg#define PORTBUFSIZE 32 23973143b9aSmrg 24073143b9aSmrg#ifndef MAXHOSTNAMELEN 24173143b9aSmrg#define MAXHOSTNAMELEN 255 24273143b9aSmrg#endif 24373143b9aSmrg 24473143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6)) 24573143b9aSmrg# define SOCKLEN_T socklen_t 246e8a71cdfSmrg#elif defined(SVR4) || defined(__SVR4) || defined(__SCO__) 247fe567363Smrg# define SOCKLEN_T size_t 24873143b9aSmrg#else 24973143b9aSmrg# define SOCKLEN_T int 25073143b9aSmrg#endif 25173143b9aSmrg 25273143b9aSmrg/* 25373143b9aSmrg * These are some utility function used by the real interface function below. 25473143b9aSmrg */ 25573143b9aSmrg 25673143b9aSmrgstatic int 257fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family) 25873143b9aSmrg 25973143b9aSmrg{ 26073143b9aSmrg int i; 26173143b9aSmrg 262fe567363Smrg prmsg (3,"SocketSelectFamily(%s)\n", family); 26373143b9aSmrg 26473143b9aSmrg for (i = first + 1; i < NUMSOCKETFAMILIES;i++) 26573143b9aSmrg { 26673143b9aSmrg if (!strcmp (family, Sockettrans2devtab[i].transname)) 26773143b9aSmrg return i; 26873143b9aSmrg } 26973143b9aSmrg 27073143b9aSmrg return (first == -1 ? -2 : -1); 27173143b9aSmrg} 27273143b9aSmrg 27373143b9aSmrg 27473143b9aSmrg/* 27573143b9aSmrg * This function gets the local address of the socket and stores it in the 27673143b9aSmrg * XtransConnInfo structure for the connection. 27773143b9aSmrg */ 27873143b9aSmrg 27973143b9aSmrgstatic int 28073143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr) 28173143b9aSmrg 28273143b9aSmrg{ 28373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 28473143b9aSmrg struct sockaddr_storage socknamev6; 285b53e5eeaSmrg#else 28673143b9aSmrg struct sockaddr_in socknamev4; 287b53e5eeaSmrg#endif 28873143b9aSmrg void *socknamePtr; 28973143b9aSmrg SOCKLEN_T namelen; 29073143b9aSmrg 291fe567363Smrg prmsg (3,"SocketINETGetAddr(%p)\n", ciptr); 29273143b9aSmrg 29373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 294b53e5eeaSmrg namelen = sizeof(socknamev6); 295b53e5eeaSmrg socknamePtr = &socknamev6; 296b53e5eeaSmrg#else 297b53e5eeaSmrg namelen = sizeof(socknamev4); 298b53e5eeaSmrg socknamePtr = &socknamev4; 29973143b9aSmrg#endif 30073143b9aSmrg 30173143b9aSmrg bzero(socknamePtr, namelen); 302fe567363Smrg 30373143b9aSmrg if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, 30473143b9aSmrg (void *)&namelen) < 0) 30573143b9aSmrg { 30673143b9aSmrg#ifdef WIN32 30773143b9aSmrg errno = WSAGetLastError(); 30873143b9aSmrg#endif 309fe567363Smrg prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n", 310fe567363Smrg EGET()); 31173143b9aSmrg return -1; 31273143b9aSmrg } 31373143b9aSmrg 31473143b9aSmrg /* 31573143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 31673143b9aSmrg */ 31773143b9aSmrg 318fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 31973143b9aSmrg { 320fe567363Smrg prmsg (1, 321fe567363Smrg "SocketINETGetAddr: Can't allocate space for the addr\n"); 32273143b9aSmrg return -1; 32373143b9aSmrg } 32473143b9aSmrg 32573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 326b53e5eeaSmrg ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; 327b53e5eeaSmrg#else 328b53e5eeaSmrg ciptr->family = socknamev4.sin_family; 32973143b9aSmrg#endif 33073143b9aSmrg ciptr->addrlen = namelen; 33173143b9aSmrg memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); 33273143b9aSmrg 33373143b9aSmrg return 0; 33473143b9aSmrg} 33573143b9aSmrg 33673143b9aSmrg 33773143b9aSmrg/* 33873143b9aSmrg * This function gets the remote address of the socket and stores it in the 33973143b9aSmrg * XtransConnInfo structure for the connection. 34073143b9aSmrg */ 34173143b9aSmrg 34273143b9aSmrgstatic int 34373143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) 34473143b9aSmrg 34573143b9aSmrg{ 34673143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 34773143b9aSmrg struct sockaddr_storage socknamev6; 34873143b9aSmrg#endif 34973143b9aSmrg struct sockaddr_in socknamev4; 35073143b9aSmrg void *socknamePtr; 35173143b9aSmrg SOCKLEN_T namelen; 35273143b9aSmrg 35373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 354b53e5eeaSmrg if (ciptr->family == AF_INET6) 35573143b9aSmrg { 35673143b9aSmrg namelen = sizeof(socknamev6); 35773143b9aSmrg socknamePtr = &socknamev6; 35873143b9aSmrg } 35973143b9aSmrg else 36073143b9aSmrg#endif 36173143b9aSmrg { 36273143b9aSmrg namelen = sizeof(socknamev4); 36373143b9aSmrg socknamePtr = &socknamev4; 36473143b9aSmrg } 36573143b9aSmrg 36673143b9aSmrg bzero(socknamePtr, namelen); 367fe567363Smrg 368fe567363Smrg prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr); 36973143b9aSmrg 37073143b9aSmrg if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, 37173143b9aSmrg (void *)&namelen) < 0) 37273143b9aSmrg { 37373143b9aSmrg#ifdef WIN32 37473143b9aSmrg errno = WSAGetLastError(); 37573143b9aSmrg#endif 376fe567363Smrg prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", 377fe567363Smrg EGET()); 37873143b9aSmrg return -1; 37973143b9aSmrg } 38073143b9aSmrg 38173143b9aSmrg /* 38273143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 38373143b9aSmrg */ 38473143b9aSmrg 385fe567363Smrg if ((ciptr->peeraddr = malloc (namelen)) == NULL) 38673143b9aSmrg { 387fe567363Smrg prmsg (1, 388fe567363Smrg "SocketINETGetPeerAddr: Can't allocate space for the addr\n"); 38973143b9aSmrg return -1; 39073143b9aSmrg } 39173143b9aSmrg 39273143b9aSmrg ciptr->peeraddrlen = namelen; 39373143b9aSmrg memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); 39473143b9aSmrg 39573143b9aSmrg return 0; 39673143b9aSmrg} 39773143b9aSmrg 39873143b9aSmrg 39973143b9aSmrgstatic XtransConnInfo 40073143b9aSmrgTRANS(SocketOpen) (int i, int type) 40173143b9aSmrg 40273143b9aSmrg{ 40373143b9aSmrg XtransConnInfo ciptr; 40473143b9aSmrg 405fe567363Smrg prmsg (3,"SocketOpen(%d,%d)\n", i, type); 40673143b9aSmrg 407fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 40873143b9aSmrg { 409fe567363Smrg prmsg (1, "SocketOpen: malloc failed\n"); 41073143b9aSmrg return NULL; 41173143b9aSmrg } 41273143b9aSmrg 41373143b9aSmrg if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type, 41473143b9aSmrg Sockettrans2devtab[i].protocol)) < 0 41573143b9aSmrg#ifndef WIN32 41673143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) 4178d4c0f7bSmrg || ciptr->fd >= sysconf(_SC_OPEN_MAX) 41873143b9aSmrg#endif 41973143b9aSmrg#endif 42073143b9aSmrg ) { 42173143b9aSmrg#ifdef WIN32 42273143b9aSmrg errno = WSAGetLastError(); 42373143b9aSmrg#endif 424fe567363Smrg prmsg (2, "SocketOpen: socket() failed for %s\n", 425fe567363Smrg Sockettrans2devtab[i].transname); 42673143b9aSmrg 427fe567363Smrg free (ciptr); 42873143b9aSmrg return NULL; 42973143b9aSmrg } 43073143b9aSmrg 43173143b9aSmrg#ifdef TCP_NODELAY 43273143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 43373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 43473143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 43573143b9aSmrg#endif 43673143b9aSmrg ) 43773143b9aSmrg { 43873143b9aSmrg /* 43973143b9aSmrg * turn off TCP coalescence for INET sockets 44073143b9aSmrg */ 44173143b9aSmrg 44273143b9aSmrg int tmp = 1; 44373143b9aSmrg setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, 44473143b9aSmrg (char *) &tmp, sizeof (int)); 44573143b9aSmrg } 44673143b9aSmrg#endif 44773143b9aSmrg 4488a0d9095Smrg /* 4498a0d9095Smrg * Some systems provide a really small default buffer size for 4508a0d9095Smrg * UNIX sockets. Bump it up a bit such that large transfers don't 4518a0d9095Smrg * proceed at glacial speed. 4528a0d9095Smrg */ 4538a0d9095Smrg#ifdef SO_SNDBUF 4548a0d9095Smrg if (Sockettrans2devtab[i].family == AF_UNIX) 4558a0d9095Smrg { 4568a0d9095Smrg SOCKLEN_T len = sizeof (int); 4578a0d9095Smrg int val; 4588a0d9095Smrg 4598a0d9095Smrg if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4608a0d9095Smrg (char *) &val, &len) == 0 && val < 64 * 1024) 4618a0d9095Smrg { 4628a0d9095Smrg val = 64 * 1024; 4638a0d9095Smrg setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4648a0d9095Smrg (char *) &val, sizeof (int)); 4658a0d9095Smrg } 4668a0d9095Smrg } 4678a0d9095Smrg#endif 4688a0d9095Smrg 46973143b9aSmrg return ciptr; 47073143b9aSmrg} 47173143b9aSmrg 47273143b9aSmrg 47373143b9aSmrg#ifdef TRANS_REOPEN 47473143b9aSmrg 47573143b9aSmrgstatic XtransConnInfo 4766a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port) 47773143b9aSmrg 47873143b9aSmrg{ 47973143b9aSmrg XtransConnInfo ciptr; 48073143b9aSmrg int portlen; 48173143b9aSmrg struct sockaddr *addr; 482fe567363Smrg size_t addrlen; 48373143b9aSmrg 484fe567363Smrg prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); 48573143b9aSmrg 48673143b9aSmrg if (port == NULL) { 487fe567363Smrg prmsg (1, "SocketReopen: port was null!\n"); 48873143b9aSmrg return NULL; 48973143b9aSmrg } 49073143b9aSmrg 49173143b9aSmrg portlen = strlen(port) + 1; // include space for trailing null 49273143b9aSmrg#ifdef SOCK_MAXADDRLEN 49373143b9aSmrg if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { 494fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 49573143b9aSmrg return NULL; 49673143b9aSmrg } 49773143b9aSmrg if (portlen < 14) portlen = 14; 49873143b9aSmrg#else 49973143b9aSmrg if (portlen < 0 || portlen > 14) { 500fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 50173143b9aSmrg return NULL; 50273143b9aSmrg } 50373143b9aSmrg#endif /*SOCK_MAXADDRLEN*/ 50473143b9aSmrg 505fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 50673143b9aSmrg { 507fe567363Smrg prmsg (1, "SocketReopen: malloc(ciptr) failed\n"); 50873143b9aSmrg return NULL; 50973143b9aSmrg } 51073143b9aSmrg 51173143b9aSmrg ciptr->fd = fd; 51273143b9aSmrg 513fe567363Smrg addrlen = portlen + offsetof(struct sockaddr, sa_data); 514fe567363Smrg if ((addr = calloc (1, addrlen)) == NULL) { 515fe567363Smrg prmsg (1, "SocketReopen: malloc(addr) failed\n"); 516fe567363Smrg free (ciptr); 51773143b9aSmrg return NULL; 51873143b9aSmrg } 5198d4c0f7bSmrg ciptr->addr = (char *) addr; 520fe567363Smrg ciptr->addrlen = addrlen; 52173143b9aSmrg 522fe567363Smrg if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { 523fe567363Smrg prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); 524fe567363Smrg free (addr); 525fe567363Smrg free (ciptr); 52673143b9aSmrg return NULL; 52773143b9aSmrg } 528fe567363Smrg ciptr->peeraddrlen = addrlen; 52973143b9aSmrg 53073143b9aSmrg /* Initialize ciptr structure as if it were a normally-opened unix socket */ 53173143b9aSmrg ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; 53273143b9aSmrg#ifdef BSD44SOCKETS 533fe567363Smrg addr->sa_len = addrlen; 53473143b9aSmrg#endif 53573143b9aSmrg addr->sa_family = AF_UNIX; 53673143b9aSmrg#ifdef HAS_STRLCPY 53773143b9aSmrg strlcpy(addr->sa_data, port, portlen); 53873143b9aSmrg#else 53973143b9aSmrg strncpy(addr->sa_data, port, portlen); 54073143b9aSmrg#endif 54173143b9aSmrg ciptr->family = AF_UNIX; 542fe567363Smrg memcpy(ciptr->peeraddr, ciptr->addr, addrlen); 54373143b9aSmrg ciptr->port = rindex(addr->sa_data, ':'); 544e8a71cdfSmrg if (ciptr->port == NULL) { 545e8a71cdfSmrg if (is_numeric(addr->sa_data)) { 546e8a71cdfSmrg ciptr->port = addr->sa_data; 547e8a71cdfSmrg } 548e8a71cdfSmrg } else if (ciptr->port[0] == ':') { 549e8a71cdfSmrg ciptr->port++; 550e8a71cdfSmrg } 551e8a71cdfSmrg /* port should now point to portnum or NULL */ 55273143b9aSmrg return ciptr; 55373143b9aSmrg} 55473143b9aSmrg 55573143b9aSmrg#endif /* TRANS_REOPEN */ 55673143b9aSmrg 55773143b9aSmrg 55873143b9aSmrg/* 55973143b9aSmrg * These functions are the interface supplied in the Xtransport structure 56073143b9aSmrg */ 56173143b9aSmrg 56273143b9aSmrg#ifdef TRANS_CLIENT 56373143b9aSmrg 56473143b9aSmrgstatic XtransConnInfo 565fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol, 566fe567363Smrg const char *host, const char *port, int previndex) 56773143b9aSmrg{ 56873143b9aSmrg XtransConnInfo ciptr; 56973143b9aSmrg int i = previndex; 57073143b9aSmrg 571fe567363Smrg prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n", 57273143b9aSmrg protocol, host, port); 57373143b9aSmrg 57473143b9aSmrg SocketInitOnce(); 57573143b9aSmrg 57673143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { 57773143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 578e8a71cdfSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) { 579e8a71cdfSmrg /* Save the index for later use */ 580e8a71cdfSmrg 581e8a71cdfSmrg ciptr->index = i; 58273143b9aSmrg break; 583e8a71cdfSmrg } 58473143b9aSmrg } 58573143b9aSmrg if (i < 0) { 58673143b9aSmrg if (i == -1) 587fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", 588fe567363Smrg transname); 58973143b9aSmrg else 590fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", 591fe567363Smrg transname); 59273143b9aSmrg return NULL; 59373143b9aSmrg } 59473143b9aSmrg 59573143b9aSmrg return ciptr; 59673143b9aSmrg} 59773143b9aSmrg 59873143b9aSmrgstatic XtransConnInfo 5996a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol, 6006a3641a6Ssnj const char *host, const char *port) 60173143b9aSmrg{ 60273143b9aSmrg return TRANS(SocketOpenCOTSClientBase)( 60373143b9aSmrg thistrans->TransName, protocol, host, port, -1); 60473143b9aSmrg} 60573143b9aSmrg 60673143b9aSmrg 60773143b9aSmrg#endif /* TRANS_CLIENT */ 60873143b9aSmrg 60973143b9aSmrg 61073143b9aSmrg#ifdef TRANS_SERVER 61173143b9aSmrg 61273143b9aSmrgstatic XtransConnInfo 6136a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol, 6146a3641a6Ssnj const char *host, const char *port) 61573143b9aSmrg 61673143b9aSmrg{ 61773143b9aSmrg XtransConnInfo ciptr; 61873143b9aSmrg int i = -1; 61973143b9aSmrg 620fe567363Smrg prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); 62173143b9aSmrg 62273143b9aSmrg SocketInitOnce(); 62373143b9aSmrg 62473143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 62573143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 62673143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 62773143b9aSmrg break; 62873143b9aSmrg } 62973143b9aSmrg if (i < 0) { 63073143b9aSmrg if (i == -1) 631fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", 632fe567363Smrg thistrans->TransName); 63373143b9aSmrg else 634fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", 635fe567363Smrg thistrans->TransName); 63673143b9aSmrg return NULL; 63773143b9aSmrg } 63873143b9aSmrg 63973143b9aSmrg /* 64073143b9aSmrg * Using this prevents the bind() check for an existing server listening 64173143b9aSmrg * on the same port, but it is required for other reasons. 64273143b9aSmrg */ 64373143b9aSmrg#ifdef SO_REUSEADDR 64473143b9aSmrg 64573143b9aSmrg /* 64673143b9aSmrg * SO_REUSEADDR only applied to AF_INET && AF_INET6 64773143b9aSmrg */ 64873143b9aSmrg 64973143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 65073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 65173143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 65273143b9aSmrg#endif 65373143b9aSmrg ) 65473143b9aSmrg { 65573143b9aSmrg int one = 1; 65673143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, 65773143b9aSmrg (char *) &one, sizeof (int)); 65873143b9aSmrg } 65973143b9aSmrg#endif 66073143b9aSmrg#ifdef IPV6_V6ONLY 66173143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 66273143b9aSmrg { 66373143b9aSmrg int one = 1; 66473143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 66573143b9aSmrg } 66673143b9aSmrg#endif 66773143b9aSmrg /* Save the index for later use */ 66873143b9aSmrg 66973143b9aSmrg ciptr->index = i; 67073143b9aSmrg 67173143b9aSmrg return ciptr; 67273143b9aSmrg} 67373143b9aSmrg 67473143b9aSmrg#endif /* TRANS_SERVER */ 67573143b9aSmrg 67673143b9aSmrg 67773143b9aSmrg#ifdef TRANS_CLIENT 67873143b9aSmrg 67973143b9aSmrgstatic XtransConnInfo 6806a3641a6SsnjTRANS(SocketOpenCLTSClient) (Xtransport *thistrans, const char *protocol, 6816a3641a6Ssnj const char *host, const char *port) 68273143b9aSmrg 68373143b9aSmrg{ 68473143b9aSmrg XtransConnInfo ciptr; 68573143b9aSmrg int i = -1; 68673143b9aSmrg 687fe567363Smrg prmsg (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port); 68873143b9aSmrg 68973143b9aSmrg SocketInitOnce(); 69073143b9aSmrg 69173143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 69273143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 69373143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 69473143b9aSmrg break; 69573143b9aSmrg } 69673143b9aSmrg if (i < 0) { 69773143b9aSmrg if (i == -1) 698fe567363Smrg prmsg (1,"SocketOpenCLTSClient: Unable to open socket for %s\n", 699fe567363Smrg thistrans->TransName); 70073143b9aSmrg else 701fe567363Smrg prmsg (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n", 702fe567363Smrg thistrans->TransName); 70373143b9aSmrg return NULL; 70473143b9aSmrg } 70573143b9aSmrg 70673143b9aSmrg /* Save the index for later use */ 70773143b9aSmrg 70873143b9aSmrg ciptr->index = i; 70973143b9aSmrg 71073143b9aSmrg return ciptr; 71173143b9aSmrg} 71273143b9aSmrg 71373143b9aSmrg#endif /* TRANS_CLIENT */ 71473143b9aSmrg 71573143b9aSmrg 71673143b9aSmrg#ifdef TRANS_SERVER 71773143b9aSmrg 71873143b9aSmrgstatic XtransConnInfo 7196a3641a6SsnjTRANS(SocketOpenCLTSServer) (Xtransport *thistrans, const char *protocol, 7206a3641a6Ssnj const char *host, const char *port) 72173143b9aSmrg 72273143b9aSmrg{ 72373143b9aSmrg XtransConnInfo ciptr; 72473143b9aSmrg int i = -1; 72573143b9aSmrg 726fe567363Smrg prmsg (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port); 72773143b9aSmrg 72873143b9aSmrg SocketInitOnce(); 72973143b9aSmrg 73073143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 73173143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 73273143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 73373143b9aSmrg break; 73473143b9aSmrg } 73573143b9aSmrg if (i < 0) { 73673143b9aSmrg if (i == -1) 737fe567363Smrg prmsg (1,"SocketOpenCLTSServer: Unable to open socket for %s\n", 738fe567363Smrg thistrans->TransName); 73973143b9aSmrg else 740fe567363Smrg prmsg (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n", 741fe567363Smrg thistrans->TransName); 74273143b9aSmrg return NULL; 74373143b9aSmrg } 74473143b9aSmrg 74573143b9aSmrg#ifdef IPV6_V6ONLY 74673143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 74773143b9aSmrg { 74873143b9aSmrg int one = 1; 74973143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 75073143b9aSmrg } 75173143b9aSmrg#endif 75273143b9aSmrg /* Save the index for later use */ 75373143b9aSmrg 75473143b9aSmrg ciptr->index = i; 75573143b9aSmrg 75673143b9aSmrg return ciptr; 75773143b9aSmrg} 75873143b9aSmrg 75973143b9aSmrg#endif /* TRANS_SERVER */ 76073143b9aSmrg 76173143b9aSmrg 76273143b9aSmrg#ifdef TRANS_REOPEN 76373143b9aSmrg 76473143b9aSmrgstatic XtransConnInfo 7656a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port) 76673143b9aSmrg 76773143b9aSmrg{ 76873143b9aSmrg XtransConnInfo ciptr; 76973143b9aSmrg int i = -1; 77073143b9aSmrg 771fe567363Smrg prmsg (2, 772fe567363Smrg "SocketReopenCOTSServer(%d, %s)\n", fd, port); 77373143b9aSmrg 77473143b9aSmrg SocketInitOnce(); 77573143b9aSmrg 77673143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 77773143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 77873143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 77973143b9aSmrg break; 78073143b9aSmrg } 78173143b9aSmrg if (i < 0) { 78273143b9aSmrg if (i == -1) 783fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", 784fe567363Smrg thistrans->TransName); 78573143b9aSmrg else 786fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", 787fe567363Smrg thistrans->TransName); 78873143b9aSmrg return NULL; 78973143b9aSmrg } 79073143b9aSmrg 79173143b9aSmrg /* Save the index for later use */ 79273143b9aSmrg 79373143b9aSmrg ciptr->index = i; 79473143b9aSmrg 79573143b9aSmrg return ciptr; 79673143b9aSmrg} 79773143b9aSmrg 79873143b9aSmrgstatic XtransConnInfo 7996a3641a6SsnjTRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, const char *port) 80073143b9aSmrg 80173143b9aSmrg{ 80273143b9aSmrg XtransConnInfo ciptr; 80373143b9aSmrg int i = -1; 80473143b9aSmrg 805fe567363Smrg prmsg (2, 806fe567363Smrg "SocketReopenCLTSServer(%d, %s)\n", fd, port); 80773143b9aSmrg 80873143b9aSmrg SocketInitOnce(); 80973143b9aSmrg 81073143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 81173143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 81273143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 81373143b9aSmrg break; 81473143b9aSmrg } 81573143b9aSmrg if (i < 0) { 81673143b9aSmrg if (i == -1) 817fe567363Smrg prmsg (1,"SocketReopenCLTSServer: Unable to open socket for %s\n", 818fe567363Smrg thistrans->TransName); 81973143b9aSmrg else 820fe567363Smrg prmsg (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n", 821fe567363Smrg thistrans->TransName); 82273143b9aSmrg return NULL; 82373143b9aSmrg } 82473143b9aSmrg 82573143b9aSmrg /* Save the index for later use */ 82673143b9aSmrg 82773143b9aSmrg ciptr->index = i; 82873143b9aSmrg 82973143b9aSmrg return ciptr; 83073143b9aSmrg} 83173143b9aSmrg 83273143b9aSmrg#endif /* TRANS_REOPEN */ 83373143b9aSmrg 83473143b9aSmrg 83573143b9aSmrgstatic int 83673143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) 83773143b9aSmrg 83873143b9aSmrg{ 839fe567363Smrg prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); 84073143b9aSmrg 84173143b9aSmrg return -1; 84273143b9aSmrg} 84373143b9aSmrg 84473143b9aSmrg#ifdef UNIXCONN 84573143b9aSmrgstatic int 84673143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract) 84773143b9aSmrg{ 84873143b9aSmrg struct sockaddr_un s; 84973143b9aSmrg int maxlen = sizeof(s.sun_path) - 1; 85073143b9aSmrg const char *at = ""; 85173143b9aSmrg 85273143b9aSmrg if (!port || !*port || !path) 85373143b9aSmrg return -1; 85473143b9aSmrg 85573143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 85673143b9aSmrg if (port[0] == '@') 85773143b9aSmrg upath = ""; 85873143b9aSmrg else if (abstract) 85973143b9aSmrg at = "@"; 86073143b9aSmrg#endif 86173143b9aSmrg 86273143b9aSmrg if (*port == '/') /* a full pathname */ 86373143b9aSmrg upath = ""; 86473143b9aSmrg 86573143b9aSmrg if (strlen(port) + strlen(upath) > maxlen) 86673143b9aSmrg return -1; 867fe567363Smrg snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port); 86873143b9aSmrg return 0; 86973143b9aSmrg} 87073143b9aSmrg#endif 87173143b9aSmrg 87273143b9aSmrg#ifdef TRANS_SERVER 87373143b9aSmrg 87473143b9aSmrgstatic int 875fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr, 87673143b9aSmrg struct sockaddr *sockname, 87773143b9aSmrg int socknamelen, unsigned int flags) 87873143b9aSmrg 87973143b9aSmrg{ 88073143b9aSmrg SOCKLEN_T namelen = socknamelen; 88173143b9aSmrg int fd = ciptr->fd; 88273143b9aSmrg int retry; 88373143b9aSmrg 884fe567363Smrg prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd); 88573143b9aSmrg 88673143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 88773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 88873143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 88973143b9aSmrg#endif 89073143b9aSmrg ) 89173143b9aSmrg retry = 20; 89273143b9aSmrg else 89373143b9aSmrg retry = 0; 89473143b9aSmrg 89573143b9aSmrg while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) 89673143b9aSmrg { 89773143b9aSmrg if (errno == EADDRINUSE) { 89873143b9aSmrg if (flags & ADDR_IN_USE_ALLOWED) 89973143b9aSmrg break; 90073143b9aSmrg else 90173143b9aSmrg return TRANS_ADDR_IN_USE; 90273143b9aSmrg } 903fe567363Smrg 90473143b9aSmrg if (retry-- == 0) { 905fe567363Smrg prmsg (1, "SocketCreateListener: failed to bind listener\n"); 90673143b9aSmrg close (fd); 90773143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 90873143b9aSmrg } 90973143b9aSmrg#ifdef SO_REUSEADDR 91073143b9aSmrg sleep (1); 91173143b9aSmrg#else 91273143b9aSmrg sleep (10); 91373143b9aSmrg#endif /* SO_REUSEDADDR */ 91473143b9aSmrg } 91573143b9aSmrg 91673143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 91773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 91873143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 91973143b9aSmrg#endif 92073143b9aSmrg ) { 92173143b9aSmrg#ifdef SO_DONTLINGER 92273143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); 92373143b9aSmrg#else 92473143b9aSmrg#ifdef SO_LINGER 92573143b9aSmrg { 92673143b9aSmrg static int linger[2] = { 0, 0 }; 92773143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_LINGER, 92873143b9aSmrg (char *) linger, sizeof (linger)); 92973143b9aSmrg } 93073143b9aSmrg#endif 93173143b9aSmrg#endif 93273143b9aSmrg} 93373143b9aSmrg 93473143b9aSmrg if (listen (fd, BACKLOG) < 0) 93573143b9aSmrg { 936fe567363Smrg prmsg (1, "SocketCreateListener: listen() failed\n"); 93773143b9aSmrg close (fd); 93873143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 93973143b9aSmrg } 940fe567363Smrg 94173143b9aSmrg /* Set a flag to indicate that this connection is a listener */ 94273143b9aSmrg 94373143b9aSmrg ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 94473143b9aSmrg 94573143b9aSmrg return 0; 94673143b9aSmrg} 94773143b9aSmrg 94873143b9aSmrg#ifdef TCPCONN 94973143b9aSmrgstatic int 9506a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port, 9516a3641a6Ssnj unsigned int flags) 95273143b9aSmrg 95373143b9aSmrg{ 95473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 95573143b9aSmrg struct sockaddr_storage sockname; 95673143b9aSmrg#else 95773143b9aSmrg struct sockaddr_in sockname; 95873143b9aSmrg#endif 95973143b9aSmrg unsigned short sport; 96073143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 96173143b9aSmrg int status; 96273143b9aSmrg long tmpport; 96373143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 96473143b9aSmrg _Xgetservbynameparams sparams; 96573143b9aSmrg#endif 96673143b9aSmrg struct servent *servp; 96773143b9aSmrg 96873143b9aSmrg#ifdef X11_t 96973143b9aSmrg char portbuf[PORTBUFSIZE]; 97073143b9aSmrg#endif 971fe567363Smrg 972fe567363Smrg prmsg (2, "SocketINETCreateListener(%s)\n", port); 97373143b9aSmrg 97473143b9aSmrg#ifdef X11_t 97573143b9aSmrg /* 97673143b9aSmrg * X has a well known port, that is transport dependent. It is easier 97773143b9aSmrg * to handle it here, than try and come up with a transport independent 97873143b9aSmrg * representation that can be passed in and resolved the usual way. 97973143b9aSmrg * 98073143b9aSmrg * The port that is passed here is really a string containing the idisplay 98173143b9aSmrg * from ConnectDisplay(). 98273143b9aSmrg */ 98373143b9aSmrg 98473143b9aSmrg if (is_numeric (port)) 98573143b9aSmrg { 98673143b9aSmrg /* fixup the server port address */ 98773143b9aSmrg tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 988fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 98973143b9aSmrg port = portbuf; 99073143b9aSmrg } 99173143b9aSmrg#endif 99273143b9aSmrg 99373143b9aSmrg if (port && *port) 99473143b9aSmrg { 99573143b9aSmrg /* Check to see if the port string is just a number (handles X11) */ 99673143b9aSmrg 99773143b9aSmrg if (!is_numeric (port)) 99873143b9aSmrg { 99973143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) 100073143b9aSmrg { 1001fe567363Smrg prmsg (1, 100273143b9aSmrg "SocketINETCreateListener: Unable to get service for %s\n", 1003fe567363Smrg port); 100473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 100573143b9aSmrg } 100673143b9aSmrg /* we trust getservbyname to return a valid number */ 100773143b9aSmrg sport = servp->s_port; 100873143b9aSmrg } 100973143b9aSmrg else 101073143b9aSmrg { 101173143b9aSmrg tmpport = strtol (port, (char**)NULL, 10); 1012fe567363Smrg /* 101373143b9aSmrg * check that somehow the port address isn't negative or in 101473143b9aSmrg * the range of reserved port addresses. This can happen and 1015fe567363Smrg * be very bad if the server is suid-root and the user does 1016fe567363Smrg * something (dumb) like `X :60049`. 101773143b9aSmrg */ 101873143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 101973143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 102073143b9aSmrg 102173143b9aSmrg sport = (unsigned short) tmpport; 102273143b9aSmrg } 102373143b9aSmrg } 102473143b9aSmrg else 102573143b9aSmrg sport = 0; 102673143b9aSmrg 102773143b9aSmrg bzero(&sockname, sizeof(sockname)); 102873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 102973143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 103073143b9aSmrg namelen = sizeof (struct sockaddr_in); 103173143b9aSmrg#ifdef BSD44SOCKETS 103273143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_len = namelen; 103373143b9aSmrg#endif 103473143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; 103573143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); 103673143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); 103773143b9aSmrg } else { 103873143b9aSmrg namelen = sizeof (struct sockaddr_in6); 103973143b9aSmrg#ifdef SIN6_LEN 104073143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); 104173143b9aSmrg#endif 104273143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; 104373143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); 104473143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; 104573143b9aSmrg } 104673143b9aSmrg#else 104773143b9aSmrg#ifdef BSD44SOCKETS 104873143b9aSmrg sockname.sin_len = sizeof (sockname); 104973143b9aSmrg#endif 105073143b9aSmrg sockname.sin_family = AF_INET; 105173143b9aSmrg sockname.sin_port = htons (sport); 105273143b9aSmrg sockname.sin_addr.s_addr = htonl (INADDR_ANY); 105373143b9aSmrg#endif 105473143b9aSmrg 105573143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 105673143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 105773143b9aSmrg { 1058fe567363Smrg prmsg (1, 1059fe567363Smrg "SocketINETCreateListener: ...SocketCreateListener() failed\n"); 106073143b9aSmrg return status; 106173143b9aSmrg } 106273143b9aSmrg 106373143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 106473143b9aSmrg { 1065fe567363Smrg prmsg (1, 1066fe567363Smrg "SocketINETCreateListener: ...SocketINETGetAddr() failed\n"); 106773143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 106873143b9aSmrg } 106973143b9aSmrg 107073143b9aSmrg return 0; 107173143b9aSmrg} 107273143b9aSmrg 107373143b9aSmrg#endif /* TCPCONN */ 107473143b9aSmrg 107573143b9aSmrg 107673143b9aSmrg#ifdef UNIXCONN 107773143b9aSmrg 107873143b9aSmrgstatic int 10796a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port, 108073143b9aSmrg unsigned int flags) 108173143b9aSmrg 108273143b9aSmrg{ 108373143b9aSmrg struct sockaddr_un sockname; 108473143b9aSmrg int namelen; 108573143b9aSmrg int oldUmask; 108673143b9aSmrg int status; 108773143b9aSmrg unsigned int mode; 108873143b9aSmrg char tmpport[108]; 108973143b9aSmrg 109073143b9aSmrg int abstract = 0; 109173143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 109273143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 109373143b9aSmrg#endif 109473143b9aSmrg 1095fe567363Smrg prmsg (2, "SocketUNIXCreateListener(%s)\n", 1096fe567363Smrg port ? port : "NULL"); 109773143b9aSmrg 109873143b9aSmrg /* Make sure the directory is created */ 109973143b9aSmrg 110073143b9aSmrg oldUmask = umask (0); 110173143b9aSmrg 110273143b9aSmrg#ifdef UNIX_DIR 110373143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 110473143b9aSmrg mode = 01777; 110573143b9aSmrg#else 110673143b9aSmrg mode = 0777; 110773143b9aSmrg#endif 11088d4c0f7bSmrg if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) { 1109fe567363Smrg prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", 1110fe567363Smrg UNIX_DIR, errno); 111173143b9aSmrg (void) umask (oldUmask); 111273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 111373143b9aSmrg } 111473143b9aSmrg#endif 111573143b9aSmrg 111673143b9aSmrg memset(&sockname, 0, sizeof(sockname)); 111773143b9aSmrg sockname.sun_family = AF_UNIX; 111873143b9aSmrg 111973143b9aSmrg if (!(port && *port)) { 112073143b9aSmrg snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid()); 112173143b9aSmrg port = tmpport; 112273143b9aSmrg } 112373143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1124fe567363Smrg prmsg (1, "SocketUNIXCreateListener: path too long\n"); 112573143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 112673143b9aSmrg } 112773143b9aSmrg 1128fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 112973143b9aSmrg sockname.sun_len = strlen(sockname.sun_path); 113073143b9aSmrg#endif 113173143b9aSmrg 113273143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 113373143b9aSmrg namelen = SUN_LEN(&sockname); 113473143b9aSmrg#else 113573143b9aSmrg namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 113673143b9aSmrg#endif 113773143b9aSmrg 113873143b9aSmrg if (abstract) { 113973143b9aSmrg sockname.sun_path[0] = '\0'; 114073143b9aSmrg namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]); 114173143b9aSmrg } 114273143b9aSmrg else 114373143b9aSmrg unlink (sockname.sun_path); 114473143b9aSmrg 114573143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 114673143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 114773143b9aSmrg { 1148fe567363Smrg prmsg (1, 1149fe567363Smrg "SocketUNIXCreateListener: ...SocketCreateListener() failed\n"); 115073143b9aSmrg (void) umask (oldUmask); 115173143b9aSmrg return status; 115273143b9aSmrg } 115373143b9aSmrg 115473143b9aSmrg /* 115573143b9aSmrg * Now that the listener is esablished, create the addr info for 115673143b9aSmrg * this connection. getpeername() doesn't work for UNIX Domain Sockets 115773143b9aSmrg * on some systems (hpux at least), so we will just do it manually, instead 115873143b9aSmrg * of calling something like TRANS(SocketUNIXGetAddr). 115973143b9aSmrg */ 116073143b9aSmrg 116173143b9aSmrg namelen = sizeof (sockname); /* this will always make it the same size */ 116273143b9aSmrg 1163fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 116473143b9aSmrg { 1165fe567363Smrg prmsg (1, 1166fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 116773143b9aSmrg (void) umask (oldUmask); 116873143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 116973143b9aSmrg } 117073143b9aSmrg 117173143b9aSmrg if (abstract) 117273143b9aSmrg sockname.sun_path[0] = '@'; 117373143b9aSmrg 117473143b9aSmrg ciptr->family = sockname.sun_family; 117573143b9aSmrg ciptr->addrlen = namelen; 117673143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 117773143b9aSmrg 117873143b9aSmrg (void) umask (oldUmask); 117973143b9aSmrg 118073143b9aSmrg return 0; 118173143b9aSmrg} 118273143b9aSmrg 118373143b9aSmrg 118473143b9aSmrgstatic int 118573143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) 118673143b9aSmrg 118773143b9aSmrg{ 118873143b9aSmrg /* 118973143b9aSmrg * See if the unix domain socket has disappeared. If it has, recreate it. 119073143b9aSmrg */ 119173143b9aSmrg 119273143b9aSmrg struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; 119373143b9aSmrg struct stat statb; 119473143b9aSmrg int status = TRANS_RESET_NOOP; 119573143b9aSmrg unsigned int mode; 119673143b9aSmrg int abstract = 0; 119773143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 119873143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 119973143b9aSmrg#endif 120073143b9aSmrg 1201fe567363Smrg prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd); 120273143b9aSmrg 120373143b9aSmrg if (!abstract && ( 120473143b9aSmrg stat (unsock->sun_path, &statb) == -1 || 120573143b9aSmrg ((statb.st_mode & S_IFMT) != 1206e8a71cdfSmrg#if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK) 120773143b9aSmrg S_IFIFO 120873143b9aSmrg#else 120973143b9aSmrg S_IFSOCK 121073143b9aSmrg#endif 121173143b9aSmrg ))) 121273143b9aSmrg { 121373143b9aSmrg int oldUmask = umask (0); 121473143b9aSmrg 121573143b9aSmrg#ifdef UNIX_DIR 121673143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 121773143b9aSmrg mode = 01777; 121873143b9aSmrg#else 121973143b9aSmrg mode = 0777; 122073143b9aSmrg#endif 122173143b9aSmrg if (trans_mkdir(UNIX_DIR, mode) == -1) { 1222fe567363Smrg prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", 1223fe567363Smrg UNIX_DIR, errno); 122473143b9aSmrg (void) umask (oldUmask); 122573143b9aSmrg return TRANS_RESET_FAILURE; 122673143b9aSmrg } 122773143b9aSmrg#endif 122873143b9aSmrg 122973143b9aSmrg close (ciptr->fd); 123073143b9aSmrg unlink (unsock->sun_path); 123173143b9aSmrg 123273143b9aSmrg if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 123373143b9aSmrg { 123473143b9aSmrg TRANS(FreeConnInfo) (ciptr); 123573143b9aSmrg (void) umask (oldUmask); 123673143b9aSmrg return TRANS_RESET_FAILURE; 123773143b9aSmrg } 123873143b9aSmrg 123973143b9aSmrg if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) 124073143b9aSmrg { 124173143b9aSmrg close (ciptr->fd); 124273143b9aSmrg TRANS(FreeConnInfo) (ciptr); 124373143b9aSmrg return TRANS_RESET_FAILURE; 124473143b9aSmrg } 124573143b9aSmrg 124673143b9aSmrg if (listen (ciptr->fd, BACKLOG) < 0) 124773143b9aSmrg { 124873143b9aSmrg close (ciptr->fd); 124973143b9aSmrg TRANS(FreeConnInfo) (ciptr); 125073143b9aSmrg (void) umask (oldUmask); 125173143b9aSmrg return TRANS_RESET_FAILURE; 125273143b9aSmrg } 125373143b9aSmrg 125473143b9aSmrg umask (oldUmask); 125573143b9aSmrg 125673143b9aSmrg status = TRANS_RESET_NEW_FD; 125773143b9aSmrg } 125873143b9aSmrg 125973143b9aSmrg return status; 126073143b9aSmrg} 126173143b9aSmrg 126273143b9aSmrg#endif /* UNIXCONN */ 126373143b9aSmrg 126473143b9aSmrg 126573143b9aSmrg#ifdef TCPCONN 126673143b9aSmrg 126773143b9aSmrgstatic XtransConnInfo 126873143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) 126973143b9aSmrg 127073143b9aSmrg{ 127173143b9aSmrg XtransConnInfo newciptr; 127273143b9aSmrg struct sockaddr_in sockname; 127373143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 127473143b9aSmrg 1275fe567363Smrg prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd); 127673143b9aSmrg 1277fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 127873143b9aSmrg { 1279fe567363Smrg prmsg (1, "SocketINETAccept: malloc failed\n"); 128073143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 128173143b9aSmrg return NULL; 128273143b9aSmrg } 128373143b9aSmrg 128473143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 128573143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 128673143b9aSmrg { 128773143b9aSmrg#ifdef WIN32 128873143b9aSmrg errno = WSAGetLastError(); 128973143b9aSmrg#endif 1290fe567363Smrg prmsg (1, "SocketINETAccept: accept() failed\n"); 1291fe567363Smrg free (newciptr); 129273143b9aSmrg *status = TRANS_ACCEPT_FAILED; 129373143b9aSmrg return NULL; 129473143b9aSmrg } 129573143b9aSmrg 129673143b9aSmrg#ifdef TCP_NODELAY 129773143b9aSmrg { 129873143b9aSmrg /* 129973143b9aSmrg * turn off TCP coalescence for INET sockets 130073143b9aSmrg */ 130173143b9aSmrg 130273143b9aSmrg int tmp = 1; 130373143b9aSmrg setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, 130473143b9aSmrg (char *) &tmp, sizeof (int)); 130573143b9aSmrg } 130673143b9aSmrg#endif 130773143b9aSmrg 130873143b9aSmrg /* 1309fe567363Smrg * Get this address again because the transport may give a more 131073143b9aSmrg * specific address now that a connection is established. 131173143b9aSmrg */ 131273143b9aSmrg 131373143b9aSmrg if (TRANS(SocketINETGetAddr) (newciptr) < 0) 131473143b9aSmrg { 1315fe567363Smrg prmsg (1, 1316fe567363Smrg "SocketINETAccept: ...SocketINETGetAddr() failed:\n"); 131773143b9aSmrg close (newciptr->fd); 1318fe567363Smrg free (newciptr); 131973143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 132073143b9aSmrg return NULL; 132173143b9aSmrg } 132273143b9aSmrg 132373143b9aSmrg if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) 132473143b9aSmrg { 1325fe567363Smrg prmsg (1, 1326fe567363Smrg "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n"); 132773143b9aSmrg close (newciptr->fd); 1328fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1329fe567363Smrg free (newciptr); 133073143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 133173143b9aSmrg return NULL; 133273143b9aSmrg } 133373143b9aSmrg 133473143b9aSmrg *status = 0; 133573143b9aSmrg 133673143b9aSmrg return newciptr; 133773143b9aSmrg} 133873143b9aSmrg 133973143b9aSmrg#endif /* TCPCONN */ 134073143b9aSmrg 134173143b9aSmrg 134273143b9aSmrg#ifdef UNIXCONN 134373143b9aSmrgstatic XtransConnInfo 134473143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) 134573143b9aSmrg 134673143b9aSmrg{ 134773143b9aSmrg XtransConnInfo newciptr; 134873143b9aSmrg struct sockaddr_un sockname; 134973143b9aSmrg SOCKLEN_T namelen = sizeof sockname; 135073143b9aSmrg 1351fe567363Smrg prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd); 135273143b9aSmrg 1353fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 135473143b9aSmrg { 1355fe567363Smrg prmsg (1, "SocketUNIXAccept: malloc() failed\n"); 135673143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 135773143b9aSmrg return NULL; 135873143b9aSmrg } 135973143b9aSmrg 136073143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 136173143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 136273143b9aSmrg { 1363fe567363Smrg prmsg (1, "SocketUNIXAccept: accept() failed\n"); 1364fe567363Smrg free (newciptr); 136573143b9aSmrg *status = TRANS_ACCEPT_FAILED; 136673143b9aSmrg return NULL; 136773143b9aSmrg } 136873143b9aSmrg 136973143b9aSmrg ciptr->addrlen = namelen; 137073143b9aSmrg /* 137173143b9aSmrg * Get the socket name and the peer name from the listener socket, 137273143b9aSmrg * since this is unix domain. 137373143b9aSmrg */ 137473143b9aSmrg 1375fe567363Smrg if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL) 137673143b9aSmrg { 1377fe567363Smrg prmsg (1, 1378fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 137973143b9aSmrg close (newciptr->fd); 1380fe567363Smrg free (newciptr); 138173143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 138273143b9aSmrg return NULL; 138373143b9aSmrg } 138473143b9aSmrg 138573143b9aSmrg /* 138673143b9aSmrg * if the socket is abstract, we already modified the address to have a 138773143b9aSmrg * @ instead of the initial NUL, so no need to do that again here. 138873143b9aSmrg */ 138973143b9aSmrg 139073143b9aSmrg newciptr->addrlen = ciptr->addrlen; 139173143b9aSmrg memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); 139273143b9aSmrg 1393fe567363Smrg if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL) 139473143b9aSmrg { 1395fe567363Smrg prmsg (1, 1396fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 139773143b9aSmrg close (newciptr->fd); 1398fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1399fe567363Smrg free (newciptr); 140073143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 140173143b9aSmrg return NULL; 140273143b9aSmrg } 1403fe567363Smrg 140473143b9aSmrg newciptr->peeraddrlen = ciptr->addrlen; 140573143b9aSmrg memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); 140673143b9aSmrg 140773143b9aSmrg newciptr->family = AF_UNIX; 140873143b9aSmrg 140973143b9aSmrg *status = 0; 141073143b9aSmrg 141173143b9aSmrg return newciptr; 141273143b9aSmrg} 141373143b9aSmrg 141473143b9aSmrg#endif /* UNIXCONN */ 141573143b9aSmrg 141673143b9aSmrg#endif /* TRANS_SERVER */ 141773143b9aSmrg 141873143b9aSmrg 141973143b9aSmrg#ifdef TRANS_CLIENT 142073143b9aSmrg 142173143b9aSmrg#ifdef TCPCONN 142273143b9aSmrg 142373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 142473143b9aSmrgstruct addrlist { 142573143b9aSmrg struct addrinfo * addr; 1426fe567363Smrg struct addrinfo * firstaddr; 142773143b9aSmrg char port[PORTBUFSIZE]; 142873143b9aSmrg char host[MAXHOSTNAMELEN]; 142973143b9aSmrg}; 143073143b9aSmrgstatic struct addrlist *addrlist = NULL; 143173143b9aSmrg#endif 143273143b9aSmrg 143373143b9aSmrg 143473143b9aSmrgstatic int 14356a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr, 14366a3641a6Ssnj const char *host, const char *port) 143773143b9aSmrg 143873143b9aSmrg{ 143973143b9aSmrg struct sockaddr * socketaddr = NULL; 144073143b9aSmrg int socketaddrlen = 0; 144173143b9aSmrg int res; 144273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 144373143b9aSmrg struct addrinfo hints; 144473143b9aSmrg char ntopbuf[INET6_ADDRSTRLEN]; 144573143b9aSmrg int resetonce = 0; 1446fe567363Smrg#else 144773143b9aSmrg struct sockaddr_in sockname; 1448fe567363Smrg struct hostent *hostp; 1449fe567363Smrg struct servent *servp; 1450fe567363Smrg unsigned long tmpaddr; 1451fe567363Smrg#endif 145273143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 145373143b9aSmrg _Xgethostbynameparams hparams; 145473143b9aSmrg _Xgetservbynameparams sparams; 145573143b9aSmrg#endif 145673143b9aSmrg#ifdef X11_t 145773143b9aSmrg char portbuf[PORTBUFSIZE]; 145873143b9aSmrg#endif 145973143b9aSmrg 146073143b9aSmrg char hostnamebuf[256]; /* tmp space */ 146173143b9aSmrg 1462fe567363Smrg prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); 146373143b9aSmrg 146473143b9aSmrg if (!host) 146573143b9aSmrg { 146673143b9aSmrg hostnamebuf[0] = '\0'; 146773143b9aSmrg (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); 146873143b9aSmrg host = hostnamebuf; 146973143b9aSmrg } 147073143b9aSmrg 147173143b9aSmrg#ifdef X11_t 147273143b9aSmrg /* 147373143b9aSmrg * X has a well known port, that is transport dependent. It is easier 147473143b9aSmrg * to handle it here, than try and come up with a transport independent 147573143b9aSmrg * representation that can be passed in and resolved the usual way. 147673143b9aSmrg * 147773143b9aSmrg * The port that is passed here is really a string containing the idisplay 147873143b9aSmrg * from ConnectDisplay(). 147973143b9aSmrg */ 148073143b9aSmrg 148173143b9aSmrg if (is_numeric (port)) 148273143b9aSmrg { 1483fe567363Smrg long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 1484fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 148573143b9aSmrg port = portbuf; 148673143b9aSmrg } 148773143b9aSmrg#endif 148873143b9aSmrg 148973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1490b53e5eeaSmrg { 149173143b9aSmrg if (addrlist != NULL) { 149273143b9aSmrg if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { 149373143b9aSmrg if (addrlist->firstaddr) 149473143b9aSmrg freeaddrinfo(addrlist->firstaddr); 149573143b9aSmrg addrlist->firstaddr = NULL; 149673143b9aSmrg } 149773143b9aSmrg } else { 149873143b9aSmrg addrlist = malloc(sizeof(struct addrlist)); 149973143b9aSmrg addrlist->firstaddr = NULL; 150073143b9aSmrg } 150173143b9aSmrg 150273143b9aSmrg if (addrlist->firstaddr == NULL) { 150373143b9aSmrg strncpy(addrlist->port, port, sizeof(addrlist->port)); 150473143b9aSmrg addrlist->port[sizeof(addrlist->port) - 1] = '\0'; 150573143b9aSmrg strncpy(addrlist->host, host, sizeof(addrlist->host)); 150673143b9aSmrg addrlist->host[sizeof(addrlist->host) - 1] = '\0'; 150773143b9aSmrg 150873143b9aSmrg bzero(&hints,sizeof(hints)); 150973143b9aSmrg hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; 151073143b9aSmrg 151173143b9aSmrg res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); 151273143b9aSmrg if (res != 0) { 1513fe567363Smrg prmsg (1, "SocketINETConnect() can't get address " 151473143b9aSmrg "for %s:%s: %s\n", host, port, gai_strerror(res)); 151573143b9aSmrg ESET(EINVAL); 151673143b9aSmrg return TRANS_CONNECT_FAILED; 151773143b9aSmrg } 151873143b9aSmrg for (res = 0, addrlist->addr = addrlist->firstaddr; 151973143b9aSmrg addrlist->addr ; res++) { 152073143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 152173143b9aSmrg } 1522fe567363Smrg prmsg(4,"Got New Address list with %d addresses\n", res); 152373143b9aSmrg res = 0; 152473143b9aSmrg addrlist->addr = NULL; 152573143b9aSmrg } 152673143b9aSmrg 152773143b9aSmrg while (socketaddr == NULL) { 152873143b9aSmrg if (addrlist->addr == NULL) { 1529fe567363Smrg if (resetonce) { 153073143b9aSmrg /* Already checked entire list - no usable addresses */ 1531fe567363Smrg prmsg (1, "SocketINETConnect() no usable address " 1532fe567363Smrg "for %s:%s\n", host, port); 153373143b9aSmrg return TRANS_CONNECT_FAILED; 153473143b9aSmrg } else { 153573143b9aSmrg /* Go back to beginning of list */ 153673143b9aSmrg resetonce = 1; 153773143b9aSmrg addrlist->addr = addrlist->firstaddr; 153873143b9aSmrg } 1539fe567363Smrg } 154073143b9aSmrg 154173143b9aSmrg socketaddr = addrlist->addr->ai_addr; 154273143b9aSmrg socketaddrlen = addrlist->addr->ai_addrlen; 154373143b9aSmrg 154473143b9aSmrg if (addrlist->addr->ai_family == AF_INET) { 154573143b9aSmrg struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; 154673143b9aSmrg 1547fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n", 154873143b9aSmrg inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, 1549fe567363Smrg ntopbuf,sizeof(ntopbuf))); 155073143b9aSmrg 1551fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n", 1552fe567363Smrg ntohs(sin->sin_port)); 155373143b9aSmrg 155473143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { 155573143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 155673143b9aSmrg "tcp") == 0) { 155773143b9aSmrg XtransConnInfo newciptr; 155873143b9aSmrg 155973143b9aSmrg /* 156073143b9aSmrg * Our socket is an IPv6 socket, but the address is 156173143b9aSmrg * IPv4. Close it and get an IPv4 socket. This is 156273143b9aSmrg * needed for IPv4 connections to work on platforms 156373143b9aSmrg * that don't allow IPv4 over IPv6 sockets. 156473143b9aSmrg */ 156573143b9aSmrg TRANS(SocketINETClose)(ciptr); 156673143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 156773143b9aSmrg "tcp", "tcp", host, port, ciptr->index); 156873143b9aSmrg if (newciptr) 156973143b9aSmrg ciptr->fd = newciptr->fd; 157073143b9aSmrg if (!newciptr || 157173143b9aSmrg Sockettrans2devtab[newciptr->index].family != 157273143b9aSmrg AF_INET) { 157373143b9aSmrg socketaddr = NULL; 1574fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv4 " 1575fe567363Smrg " socketfor IPv4 address\n"); 157673143b9aSmrg } 157773143b9aSmrg if (newciptr) 1578fe567363Smrg free(newciptr); 157973143b9aSmrg } else { 158073143b9aSmrg socketaddr = NULL; 1581fe567363Smrg prmsg (4,"SocketINETConnect Skipping IPv4 address\n"); 158273143b9aSmrg } 158373143b9aSmrg } 158473143b9aSmrg } else if (addrlist->addr->ai_family == AF_INET6) { 158573143b9aSmrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; 1586fe567363Smrg 1587fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n", 158873143b9aSmrg inet_ntop(addrlist->addr->ai_family, 1589fe567363Smrg &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf))); 1590fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n", 1591fe567363Smrg ntohs(sin6->sin6_port)); 159273143b9aSmrg 159373143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 159473143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 159573143b9aSmrg "tcp") == 0) { 159673143b9aSmrg XtransConnInfo newciptr; 159773143b9aSmrg 159873143b9aSmrg /* 159973143b9aSmrg * Close the IPv4 socket and try to open an IPv6 socket. 160073143b9aSmrg */ 160173143b9aSmrg TRANS(SocketINETClose)(ciptr); 160273143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 160373143b9aSmrg "tcp", "tcp", host, port, -1); 160473143b9aSmrg if (newciptr) 160573143b9aSmrg ciptr->fd = newciptr->fd; 160673143b9aSmrg if (!newciptr || 160773143b9aSmrg Sockettrans2devtab[newciptr->index].family != 160873143b9aSmrg AF_INET6) { 160973143b9aSmrg socketaddr = NULL; 1610fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv6 " 1611fe567363Smrg "socket for IPv6 address\n"); 161273143b9aSmrg } 161373143b9aSmrg if (newciptr) 1614fe567363Smrg free(newciptr); 161573143b9aSmrg } 161673143b9aSmrg else 161773143b9aSmrg { 161873143b9aSmrg socketaddr = NULL; 1619fe567363Smrg prmsg (4,"SocketINETConnect() Skipping IPv6 address\n"); 162073143b9aSmrg } 162173143b9aSmrg } 162273143b9aSmrg } else { 162373143b9aSmrg socketaddr = NULL; /* Unsupported address type */ 162473143b9aSmrg } 162573143b9aSmrg if (socketaddr == NULL) { 162673143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 162773143b9aSmrg } 1628fe567363Smrg } 1629b53e5eeaSmrg } 1630b53e5eeaSmrg#else 163173143b9aSmrg { 163273143b9aSmrg /* 163373143b9aSmrg * Build the socket name. 163473143b9aSmrg */ 163573143b9aSmrg 163673143b9aSmrg#ifdef BSD44SOCKETS 163773143b9aSmrg sockname.sin_len = sizeof (struct sockaddr_in); 163873143b9aSmrg#endif 163973143b9aSmrg sockname.sin_family = AF_INET; 164073143b9aSmrg 164173143b9aSmrg /* 164273143b9aSmrg * fill in sin_addr 164373143b9aSmrg */ 164473143b9aSmrg 164573143b9aSmrg#ifndef INADDR_NONE 164673143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff) 164773143b9aSmrg#endif 164873143b9aSmrg 164973143b9aSmrg /* check for ww.xx.yy.zz host string */ 165073143b9aSmrg 165173143b9aSmrg if (isascii (host[0]) && isdigit (host[0])) { 165273143b9aSmrg tmpaddr = inet_addr (host); /* returns network byte order */ 165373143b9aSmrg } else { 165473143b9aSmrg tmpaddr = INADDR_NONE; 165573143b9aSmrg } 165673143b9aSmrg 165781d6fa61Srin prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr); 165873143b9aSmrg 165973143b9aSmrg if (tmpaddr == INADDR_NONE) { 166073143b9aSmrg if ((hostp = _XGethostbyname(host,hparams)) == NULL) { 1661fe567363Smrg prmsg (1,"SocketINETConnect: Can't get address for %s\n", 1662fe567363Smrg host); 166373143b9aSmrg ESET(EINVAL); 166473143b9aSmrg return TRANS_CONNECT_FAILED; 166573143b9aSmrg } 166673143b9aSmrg if (hostp->h_addrtype != AF_INET) { /* is IP host? */ 1667fe567363Smrg prmsg (1,"SocketINETConnect: not INET host%s\n", host); 166873143b9aSmrg ESET(EPROTOTYPE); 166973143b9aSmrg return TRANS_CONNECT_FAILED; 167073143b9aSmrg } 1671fe567363Smrg 167273143b9aSmrg memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, 167373143b9aSmrg sizeof (sockname.sin_addr)); 167473143b9aSmrg 167573143b9aSmrg } else { 167673143b9aSmrg sockname.sin_addr.s_addr = tmpaddr; 167773143b9aSmrg } 167873143b9aSmrg 167973143b9aSmrg /* 168073143b9aSmrg * fill in sin_port 168173143b9aSmrg */ 168273143b9aSmrg 168373143b9aSmrg /* Check for number in the port string */ 168473143b9aSmrg 168573143b9aSmrg if (!is_numeric (port)) { 168673143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) { 1687fe567363Smrg prmsg (1,"SocketINETConnect: can't get service for %s\n", 1688fe567363Smrg port); 168973143b9aSmrg return TRANS_CONNECT_FAILED; 169073143b9aSmrg } 169173143b9aSmrg sockname.sin_port = htons (servp->s_port); 169273143b9aSmrg } else { 1693fe567363Smrg long tmpport = strtol (port, (char**)NULL, 10); 169473143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 169573143b9aSmrg return TRANS_CONNECT_FAILED; 169673143b9aSmrg sockname.sin_port = htons (((unsigned short) tmpport)); 169773143b9aSmrg } 169873143b9aSmrg 1699fe567363Smrg prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n", 1700fe567363Smrg ntohs(sockname.sin_port)); 170173143b9aSmrg socketaddr = (struct sockaddr *) &sockname; 170273143b9aSmrg socketaddrlen = sizeof(sockname); 170373143b9aSmrg } 1704b53e5eeaSmrg#endif 170573143b9aSmrg 170673143b9aSmrg /* 170773143b9aSmrg * Turn on socket keepalive so the client process will eventually 170873143b9aSmrg * be notified with a SIGPIPE signal if the display server fails 170973143b9aSmrg * to respond to a periodic transmission of messages 171073143b9aSmrg * on the connected socket. 171173143b9aSmrg * This is useful to avoid hung application processes when the 171273143b9aSmrg * processes are not spawned from the xdm session and 171373143b9aSmrg * the display server terminates abnormally. 171473143b9aSmrg * (Someone turned off the power switch.) 171573143b9aSmrg */ 171673143b9aSmrg 171773143b9aSmrg { 171873143b9aSmrg int tmp = 1; 171973143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE, 172073143b9aSmrg (char *) &tmp, sizeof (int)); 172173143b9aSmrg } 172273143b9aSmrg 172373143b9aSmrg /* 172473143b9aSmrg * Do the connect() 172573143b9aSmrg */ 172673143b9aSmrg 172773143b9aSmrg if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) 172873143b9aSmrg { 172973143b9aSmrg#ifdef WIN32 173073143b9aSmrg int olderrno = WSAGetLastError(); 173173143b9aSmrg#else 173273143b9aSmrg int olderrno = errno; 173373143b9aSmrg#endif 173473143b9aSmrg 173573143b9aSmrg /* 173673143b9aSmrg * If the error was ECONNREFUSED, the server may be overloaded 173773143b9aSmrg * and we should try again. 173873143b9aSmrg * 173973143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 174073143b9aSmrg * was non-blocking and we should poll using select 174173143b9aSmrg * 174273143b9aSmrg * If the error was EINTR, the connect was interrupted and we 174373143b9aSmrg * should try again. 174473143b9aSmrg * 174573143b9aSmrg * If multiple addresses are found for a host then we should 174673143b9aSmrg * try to connect again with a different address for a larger 174773143b9aSmrg * number of errors that made us quit before, since those 174873143b9aSmrg * could be caused by trying to use an IPv6 address to contact 174973143b9aSmrg * a machine with an IPv4-only server or other reasons that 1750fe567363Smrg * only affect one of a set of addresses. 175173143b9aSmrg */ 175273143b9aSmrg 175373143b9aSmrg if (olderrno == ECONNREFUSED || olderrno == EINTR 175473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1755b53e5eeaSmrg || (((addrlist->addr->ai_next != NULL) || 175673143b9aSmrg (addrlist->addr != addrlist->firstaddr)) && 175773143b9aSmrg (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT || 175873143b9aSmrg olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT 175973143b9aSmrg#if defined(EHOSTDOWN) 176073143b9aSmrg || olderrno == EHOSTDOWN 176173143b9aSmrg#endif 176273143b9aSmrg )) 176373143b9aSmrg#endif 176473143b9aSmrg ) 176573143b9aSmrg res = TRANS_TRY_CONNECT_AGAIN; 176673143b9aSmrg else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 176773143b9aSmrg res = TRANS_IN_PROGRESS; 176873143b9aSmrg else 176973143b9aSmrg { 1770fe567363Smrg prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n", 1771fe567363Smrg olderrno); 177273143b9aSmrg 1773fe567363Smrg res = TRANS_CONNECT_FAILED; 177473143b9aSmrg } 177573143b9aSmrg } else { 177673143b9aSmrg res = 0; 1777fe567363Smrg 177873143b9aSmrg 177973143b9aSmrg /* 178073143b9aSmrg * Sync up the address fields of ciptr. 178173143b9aSmrg */ 1782fe567363Smrg 178373143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 178473143b9aSmrg { 1785fe567363Smrg prmsg (1, 1786fe567363Smrg "SocketINETConnect: ...SocketINETGetAddr() failed:\n"); 178773143b9aSmrg res = TRANS_CONNECT_FAILED; 178873143b9aSmrg } 178973143b9aSmrg 179073143b9aSmrg else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) 179173143b9aSmrg { 1792fe567363Smrg prmsg (1, 1793fe567363Smrg "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n"); 179473143b9aSmrg res = TRANS_CONNECT_FAILED; 179573143b9aSmrg } 179673143b9aSmrg } 179773143b9aSmrg 179873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1799b53e5eeaSmrg if (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 18186a3641a6SsnjUnixHostReallyLocal (const char *host) 181973143b9aSmrg 182073143b9aSmrg{ 182173143b9aSmrg char hostnamebuf[256]; 182273143b9aSmrg 182373143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 182473143b9aSmrg 182573143b9aSmrg if (strcmp (hostnamebuf, host) == 0) 182673143b9aSmrg { 182773143b9aSmrg return (1); 1828b53e5eeaSmrg } else { 182973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 183073143b9aSmrg struct addrinfo *localhostaddr; 183173143b9aSmrg struct addrinfo *otherhostaddr; 183273143b9aSmrg struct addrinfo *i, *j; 183373143b9aSmrg int equiv = 0; 183473143b9aSmrg 183573143b9aSmrg if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0) 183673143b9aSmrg return 0; 183773143b9aSmrg if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) { 183873143b9aSmrg freeaddrinfo(localhostaddr); 183973143b9aSmrg return 0; 184073143b9aSmrg } 184173143b9aSmrg 184273143b9aSmrg for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) { 184373143b9aSmrg for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) { 184473143b9aSmrg if (i->ai_family == j->ai_family) { 184573143b9aSmrg if (i->ai_family == AF_INET) { 1846fe567363Smrg struct sockaddr_in *sinA 184773143b9aSmrg = (struct sockaddr_in *) i->ai_addr; 184873143b9aSmrg struct sockaddr_in *sinB 184973143b9aSmrg = (struct sockaddr_in *) j->ai_addr; 185073143b9aSmrg struct in_addr *A = &sinA->sin_addr; 185173143b9aSmrg struct in_addr *B = &sinB->sin_addr; 185273143b9aSmrg 185373143b9aSmrg if (memcmp(A,B,sizeof(struct in_addr)) == 0) { 185473143b9aSmrg equiv = 1; 185573143b9aSmrg } 185673143b9aSmrg } else if (i->ai_family == AF_INET6) { 1857fe567363Smrg struct sockaddr_in6 *sinA 185873143b9aSmrg = (struct sockaddr_in6 *) i->ai_addr; 1859fe567363Smrg struct sockaddr_in6 *sinB 186073143b9aSmrg = (struct sockaddr_in6 *) j->ai_addr; 186173143b9aSmrg struct in6_addr *A = &sinA->sin6_addr; 186273143b9aSmrg struct in6_addr *B = &sinB->sin6_addr; 186373143b9aSmrg 186473143b9aSmrg if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { 186573143b9aSmrg equiv = 1; 186673143b9aSmrg } 186773143b9aSmrg } 186873143b9aSmrg } 186973143b9aSmrg } 187073143b9aSmrg } 1871fe567363Smrg 187273143b9aSmrg freeaddrinfo(localhostaddr); 187373143b9aSmrg freeaddrinfo(otherhostaddr); 187473143b9aSmrg return equiv; 1875b53e5eeaSmrg#else 187673143b9aSmrg /* 187773143b9aSmrg * A host may have more than one network address. If any of the 187873143b9aSmrg * network addresses of 'host' (specified to the connect call) 187973143b9aSmrg * match any of the network addresses of 'hostname' (determined 188073143b9aSmrg * by TRANS(GetHostname)), then the two hostnames are equivalent, 188173143b9aSmrg * and we know that 'host' is really a local host. 188273143b9aSmrg */ 188373143b9aSmrg char specified_local_addr_list[10][4]; 188473143b9aSmrg int scount, equiv, i, j; 188573143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 188673143b9aSmrg _Xgethostbynameparams hparams; 188773143b9aSmrg#endif 188873143b9aSmrg struct hostent *hostp; 188973143b9aSmrg 189073143b9aSmrg if ((hostp = _XGethostbyname (host,hparams)) == NULL) 189173143b9aSmrg return (0); 189273143b9aSmrg 189373143b9aSmrg scount = 0; 189473143b9aSmrg while (hostp->h_addr_list[scount] && scount <= 8) 189573143b9aSmrg { 189673143b9aSmrg /* 189773143b9aSmrg * The 2nd call to gethostname() overrides the data 189873143b9aSmrg * from the 1st call, so we must save the address list. 189973143b9aSmrg */ 190073143b9aSmrg 1901fe567363Smrg specified_local_addr_list[scount][0] = 190273143b9aSmrg hostp->h_addr_list[scount][0]; 1903fe567363Smrg specified_local_addr_list[scount][1] = 190473143b9aSmrg hostp->h_addr_list[scount][1]; 1905fe567363Smrg specified_local_addr_list[scount][2] = 190673143b9aSmrg hostp->h_addr_list[scount][2]; 1907fe567363Smrg specified_local_addr_list[scount][3] = 190873143b9aSmrg hostp->h_addr_list[scount][3]; 190973143b9aSmrg scount++; 191073143b9aSmrg } 191173143b9aSmrg if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) 191273143b9aSmrg return (0); 191373143b9aSmrg 191473143b9aSmrg equiv = 0; 191573143b9aSmrg i = 0; 191673143b9aSmrg 191773143b9aSmrg while (i < scount && !equiv) 191873143b9aSmrg { 191973143b9aSmrg j = 0; 192073143b9aSmrg 192173143b9aSmrg while (hostp->h_addr_list[j]) 192273143b9aSmrg { 1923fe567363Smrg if ((specified_local_addr_list[i][0] == 192473143b9aSmrg hostp->h_addr_list[j][0]) && 1925fe567363Smrg (specified_local_addr_list[i][1] == 192673143b9aSmrg hostp->h_addr_list[j][1]) && 1927fe567363Smrg (specified_local_addr_list[i][2] == 192873143b9aSmrg hostp->h_addr_list[j][2]) && 1929fe567363Smrg (specified_local_addr_list[i][3] == 193073143b9aSmrg hostp->h_addr_list[j][3])) 193173143b9aSmrg { 193273143b9aSmrg /* They're equal, so we're done */ 1933fe567363Smrg 193473143b9aSmrg equiv = 1; 193573143b9aSmrg break; 193673143b9aSmrg } 193773143b9aSmrg 193873143b9aSmrg j++; 193973143b9aSmrg } 194073143b9aSmrg 194173143b9aSmrg i++; 194273143b9aSmrg } 194373143b9aSmrg return (equiv); 1944b53e5eeaSmrg#endif 194573143b9aSmrg } 194673143b9aSmrg} 194773143b9aSmrg 194873143b9aSmrgstatic int 19496a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, 19506a3641a6Ssnj const char *host, const char *port) 195173143b9aSmrg 195273143b9aSmrg{ 195373143b9aSmrg struct sockaddr_un sockname; 195473143b9aSmrg SOCKLEN_T namelen; 195573143b9aSmrg 195673143b9aSmrg 195773143b9aSmrg int abstract = 0; 195873143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 195973143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 196073143b9aSmrg#endif 196173143b9aSmrg 1962fe567363Smrg prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); 1963fe567363Smrg 196473143b9aSmrg /* 196573143b9aSmrg * Make sure 'host' is really local. If not, we return failure. 196673143b9aSmrg * The reason we make this check is because a process may advertise 196773143b9aSmrg * a "local" network ID for which it can accept connections, but if 196873143b9aSmrg * a process on a remote machine tries to connect to this network ID, 196973143b9aSmrg * we know for sure it will fail. 197073143b9aSmrg */ 197173143b9aSmrg 197273143b9aSmrg if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) 197373143b9aSmrg { 1974fe567363Smrg prmsg (1, 197573143b9aSmrg "SocketUNIXConnect: Cannot connect to non-local host %s\n", 1976fe567363Smrg host); 197773143b9aSmrg return TRANS_CONNECT_FAILED; 197873143b9aSmrg } 197973143b9aSmrg 198073143b9aSmrg 198173143b9aSmrg /* 198273143b9aSmrg * Check the port. 198373143b9aSmrg */ 198473143b9aSmrg 198573143b9aSmrg if (!port || !*port) 198673143b9aSmrg { 1987fe567363Smrg prmsg (1,"SocketUNIXConnect: Missing port specification\n"); 198873143b9aSmrg return TRANS_CONNECT_FAILED; 198973143b9aSmrg } 199073143b9aSmrg 199173143b9aSmrg /* 199273143b9aSmrg * Build the socket name. 199373143b9aSmrg */ 1994fe567363Smrg 199573143b9aSmrg sockname.sun_family = AF_UNIX; 199673143b9aSmrg 199773143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1998fe567363Smrg prmsg (1, "SocketUNIXConnect: path too long\n"); 199973143b9aSmrg return TRANS_CONNECT_FAILED; 200073143b9aSmrg } 200173143b9aSmrg 2002fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 200373143b9aSmrg sockname.sun_len = strlen (sockname.sun_path); 200473143b9aSmrg#endif 200573143b9aSmrg 200673143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 200773143b9aSmrg namelen = SUN_LEN (&sockname); 200873143b9aSmrg#else 200973143b9aSmrg namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 201073143b9aSmrg#endif 201173143b9aSmrg 201273143b9aSmrg 201373143b9aSmrg 201473143b9aSmrg /* 201573143b9aSmrg * Adjust the socket path if using abstract sockets. 201673143b9aSmrg * Done here because otherwise all the strlen() calls above would fail. 201773143b9aSmrg */ 201873143b9aSmrg 201973143b9aSmrg if (abstract) { 202073143b9aSmrg sockname.sun_path[0] = '\0'; 202173143b9aSmrg } 202273143b9aSmrg 202373143b9aSmrg /* 202473143b9aSmrg * Do the connect() 202573143b9aSmrg */ 202673143b9aSmrg 202773143b9aSmrg if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) 202873143b9aSmrg { 202973143b9aSmrg int olderrno = errno; 203073143b9aSmrg int connected = 0; 2031fe567363Smrg 203273143b9aSmrg if (!connected) 203373143b9aSmrg { 203473143b9aSmrg errno = olderrno; 2035fe567363Smrg 203673143b9aSmrg /* 203773143b9aSmrg * If the error was ENOENT, the server may be starting up; we used 203873143b9aSmrg * to suggest to try again in this case with 203973143b9aSmrg * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for 204073143b9aSmrg * processes still referencing stale sockets in their environment. 204173143b9aSmrg * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it 204273143b9aSmrg * is suggested that higher level stacks handle retries on their 204373143b9aSmrg * level when they face a slow starting server. 204473143b9aSmrg * 204573143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 204673143b9aSmrg * was non-blocking and we should poll using select 204773143b9aSmrg * 204873143b9aSmrg * If the error was EINTR, the connect was interrupted and we 204973143b9aSmrg * should try again. 205073143b9aSmrg */ 205173143b9aSmrg 205273143b9aSmrg if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 205373143b9aSmrg return TRANS_IN_PROGRESS; 205473143b9aSmrg else if (olderrno == EINTR) 205573143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 20568d4c0f7bSmrg else if (olderrno == ENOENT || olderrno == ECONNREFUSED) { 205773143b9aSmrg /* If opening as abstract socket failed, try again normally */ 205873143b9aSmrg if (abstract) { 205973143b9aSmrg ciptr->transptr->flags &= ~(TRANS_ABSTRACT); 206073143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 206173143b9aSmrg } else { 206273143b9aSmrg return TRANS_CONNECT_FAILED; 206373143b9aSmrg } 206473143b9aSmrg } else { 2065fe567363Smrg prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n", 2066fe567363Smrg EGET()); 206773143b9aSmrg 206873143b9aSmrg return TRANS_CONNECT_FAILED; 206973143b9aSmrg } 207073143b9aSmrg } 207173143b9aSmrg } 207273143b9aSmrg 207373143b9aSmrg /* 207473143b9aSmrg * Get the socket name and the peer name from the connect socket, 207573143b9aSmrg * since this is unix domain. 207673143b9aSmrg */ 207773143b9aSmrg 2078fe567363Smrg if ((ciptr->addr = malloc(namelen)) == NULL || 2079fe567363Smrg (ciptr->peeraddr = malloc(namelen)) == NULL) 208073143b9aSmrg { 2081fe567363Smrg prmsg (1, 2082fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 208373143b9aSmrg return TRANS_CONNECT_FAILED; 208473143b9aSmrg } 208573143b9aSmrg 208673143b9aSmrg if (abstract) 208773143b9aSmrg sockname.sun_path[0] = '@'; 208873143b9aSmrg 208973143b9aSmrg ciptr->family = AF_UNIX; 209073143b9aSmrg ciptr->addrlen = namelen; 209173143b9aSmrg ciptr->peeraddrlen = namelen; 209273143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 209373143b9aSmrg memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); 209473143b9aSmrg 209573143b9aSmrg return 0; 209673143b9aSmrg} 209773143b9aSmrg 209873143b9aSmrg#endif /* UNIXCONN */ 209973143b9aSmrg 210073143b9aSmrg#endif /* TRANS_CLIENT */ 210173143b9aSmrg 210273143b9aSmrg 210373143b9aSmrgstatic int 210473143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 210573143b9aSmrg 210673143b9aSmrg{ 2107fe567363Smrg prmsg (2,"SocketBytesReadable(%p,%d,%p)\n", 210873143b9aSmrg ciptr, ciptr->fd, pend); 210973143b9aSmrg#ifdef WIN32 211073143b9aSmrg { 211173143b9aSmrg int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); 211273143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 211373143b9aSmrg return ret; 211473143b9aSmrg } 211573143b9aSmrg#else 2116fe567363Smrg#if defined(__i386__) && defined(SYSV) && !defined(SCO325) 211773143b9aSmrg return ioctl (ciptr->fd, I_NREAD, (char *) pend); 211873143b9aSmrg#else 211973143b9aSmrg return ioctl (ciptr->fd, FIONREAD, (char *) pend); 212073143b9aSmrg#endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */ 212173143b9aSmrg#endif /* WIN32 */ 212273143b9aSmrg} 212373143b9aSmrg 212475ebec6dSmrg#if XTRANS_SEND_FDS 212575ebec6dSmrg 212675ebec6dSmrgstatic void 212775ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close) 212875ebec6dSmrg{ 212975ebec6dSmrg struct _XtransConnFd *cf, *new; 213075ebec6dSmrg 213175ebec6dSmrg new = malloc (sizeof (struct _XtransConnFd)); 213275ebec6dSmrg if (!new) { 213375ebec6dSmrg /* XXX mark connection as broken */ 213475ebec6dSmrg close(fd); 213575ebec6dSmrg return; 213675ebec6dSmrg } 213775ebec6dSmrg new->next = 0; 213875ebec6dSmrg new->fd = fd; 213975ebec6dSmrg new->do_close = do_close; 214075ebec6dSmrg /* search to end of list */ 214175ebec6dSmrg for (; (cf = *prev); prev = &(cf->next)); 214275ebec6dSmrg *prev = new; 214375ebec6dSmrg} 214473143b9aSmrg 214573143b9aSmrgstatic int 214675ebec6dSmrgremoveFd(struct _XtransConnFd **prev) 214775ebec6dSmrg{ 214875ebec6dSmrg struct _XtransConnFd *cf; 214975ebec6dSmrg int fd; 215075ebec6dSmrg 215175ebec6dSmrg if ((cf = *prev)) { 215275ebec6dSmrg *prev = cf->next; 215375ebec6dSmrg fd = cf->fd; 215475ebec6dSmrg free(cf); 215575ebec6dSmrg } else 215675ebec6dSmrg fd = -1; 215775ebec6dSmrg return fd; 215875ebec6dSmrg} 215973143b9aSmrg 216075ebec6dSmrgstatic void 216175ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) 216273143b9aSmrg{ 216375ebec6dSmrg struct _XtransConnFd *cf, *next; 216473143b9aSmrg 216575ebec6dSmrg for (cf = *prev; cf != upto; cf = next) { 216675ebec6dSmrg next = cf->next; 216775ebec6dSmrg if (do_close || cf->do_close) 216875ebec6dSmrg close(cf->fd); 216975ebec6dSmrg free(cf); 217073143b9aSmrg } 217175ebec6dSmrg *prev = upto; 217273143b9aSmrg} 217373143b9aSmrg 217475ebec6dSmrgstatic void 217575ebec6dSmrgcleanupFds(XtransConnInfo ciptr) 217675ebec6dSmrg{ 217775ebec6dSmrg /* Clean up the send list but don't close the fds */ 217875ebec6dSmrg discardFd(&ciptr->send_fds, NULL, 0); 217975ebec6dSmrg /* Clean up the recv list and *do* close the fds */ 218075ebec6dSmrg discardFd(&ciptr->recv_fds, NULL, 1); 218175ebec6dSmrg} 218273143b9aSmrg 218373143b9aSmrgstatic int 218475ebec6dSmrgnFd(struct _XtransConnFd **prev) 218575ebec6dSmrg{ 218675ebec6dSmrg struct _XtransConnFd *cf; 218775ebec6dSmrg int n = 0; 218875ebec6dSmrg 218975ebec6dSmrg for (cf = *prev; cf; cf = cf->next) 219075ebec6dSmrg n++; 219175ebec6dSmrg return n; 219275ebec6dSmrg} 219373143b9aSmrg 219475ebec6dSmrgstatic int 219575ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr) 219673143b9aSmrg{ 219775ebec6dSmrg prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); 219875ebec6dSmrg return removeFd(&ciptr->recv_fds); 219975ebec6dSmrg} 220075ebec6dSmrg 220175ebec6dSmrgstatic int 220275ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) 220375ebec6dSmrg{ 220475ebec6dSmrg appendFd(&ciptr->send_fds, fd, do_close); 220575ebec6dSmrg return 0; 220675ebec6dSmrg} 220775ebec6dSmrg 220875ebec6dSmrgstatic int 220975ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) 221075ebec6dSmrg{ 221175ebec6dSmrg errno = EINVAL; 221275ebec6dSmrg return -1; 221375ebec6dSmrg} 221475ebec6dSmrg 221575ebec6dSmrgstatic int 221675ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) 221775ebec6dSmrg{ 221875ebec6dSmrg errno = EINVAL; 221975ebec6dSmrg return -1; 222075ebec6dSmrg} 222175ebec6dSmrg 222275ebec6dSmrg#define MAX_FDS 128 222375ebec6dSmrg 222475ebec6dSmrgunion fd_pass { 222575ebec6dSmrg struct cmsghdr cmsghdr; 222675ebec6dSmrg char buf[CMSG_SPACE(MAX_FDS * sizeof(int))]; 222775ebec6dSmrg}; 222875ebec6dSmrg 222975ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 223075ebec6dSmrg 223175ebec6dSmrgstatic int 223275ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) 223375ebec6dSmrg 223475ebec6dSmrg{ 223575ebec6dSmrg prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); 223673143b9aSmrg 2237fe567363Smrg#if defined(WIN32) 223873143b9aSmrg { 223975ebec6dSmrg int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); 224073143b9aSmrg#ifdef WIN32 224173143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 224273143b9aSmrg#endif 224373143b9aSmrg return ret; 224473143b9aSmrg } 224573143b9aSmrg#else 224675ebec6dSmrg#if XTRANS_SEND_FDS 224775ebec6dSmrg { 224875ebec6dSmrg struct iovec iov = { 224975ebec6dSmrg .iov_base = buf, 225075ebec6dSmrg .iov_len = size 225175ebec6dSmrg }; 225275ebec6dSmrg union fd_pass cmsgbuf; 225375ebec6dSmrg struct msghdr msg = { 225475ebec6dSmrg .msg_name = NULL, 225575ebec6dSmrg .msg_namelen = 0, 225675ebec6dSmrg .msg_iov = &iov, 225775ebec6dSmrg .msg_iovlen = 1, 225875ebec6dSmrg .msg_control = cmsgbuf.buf, 225975ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 226075ebec6dSmrg }; 226175ebec6dSmrg 226275ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 226375ebec6dSmrg if (size >= 0) { 226475ebec6dSmrg struct cmsghdr *hdr; 226575ebec6dSmrg 226675ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 226775ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 226875ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 226975ebec6dSmrg int i; 227075ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 227175ebec6dSmrg 227275ebec6dSmrg for (i = 0; i < nfd; i++) 227375ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 227475ebec6dSmrg } 227575ebec6dSmrg } 227675ebec6dSmrg } 227775ebec6dSmrg return size; 227875ebec6dSmrg } 227975ebec6dSmrg#else 228075ebec6dSmrg return read(ciptr->fd, buf, size); 228175ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 228273143b9aSmrg#endif /* WIN32 */ 228373143b9aSmrg} 228473143b9aSmrg 228573143b9aSmrgstatic int 228673143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) 228773143b9aSmrg 228873143b9aSmrg{ 2289fe567363Smrg prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); 229073143b9aSmrg 229175ebec6dSmrg#if XTRANS_SEND_FDS 229275ebec6dSmrg { 229375ebec6dSmrg union fd_pass cmsgbuf; 229475ebec6dSmrg struct msghdr msg = { 229575ebec6dSmrg .msg_name = NULL, 229675ebec6dSmrg .msg_namelen = 0, 229775ebec6dSmrg .msg_iov = buf, 229875ebec6dSmrg .msg_iovlen = size, 229975ebec6dSmrg .msg_control = cmsgbuf.buf, 230075ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 230175ebec6dSmrg }; 230275ebec6dSmrg 230375ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 230475ebec6dSmrg if (size >= 0) { 230575ebec6dSmrg struct cmsghdr *hdr; 230675ebec6dSmrg 230775ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 230875ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 230975ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 231075ebec6dSmrg int i; 231175ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 231275ebec6dSmrg 231375ebec6dSmrg for (i = 0; i < nfd; i++) 231475ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 231575ebec6dSmrg } 231675ebec6dSmrg } 231775ebec6dSmrg } 231875ebec6dSmrg return size; 231975ebec6dSmrg } 232075ebec6dSmrg#else 232173143b9aSmrg return READV (ciptr, buf, size); 232275ebec6dSmrg#endif 232373143b9aSmrg} 232473143b9aSmrg 232573143b9aSmrg 232673143b9aSmrgstatic int 232773143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) 232873143b9aSmrg 232973143b9aSmrg{ 2330fe567363Smrg prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); 233173143b9aSmrg 233275ebec6dSmrg#if XTRANS_SEND_FDS 233375ebec6dSmrg if (ciptr->send_fds) 233475ebec6dSmrg { 233575ebec6dSmrg union fd_pass cmsgbuf; 233675ebec6dSmrg int nfd = nFd(&ciptr->send_fds); 233775ebec6dSmrg struct _XtransConnFd *cf = ciptr->send_fds; 233875ebec6dSmrg struct msghdr msg = { 233975ebec6dSmrg .msg_name = NULL, 234075ebec6dSmrg .msg_namelen = 0, 234175ebec6dSmrg .msg_iov = buf, 234275ebec6dSmrg .msg_iovlen = size, 234375ebec6dSmrg .msg_control = cmsgbuf.buf, 234475ebec6dSmrg .msg_controllen = CMSG_LEN(nfd * sizeof(int)) 234575ebec6dSmrg }; 234675ebec6dSmrg struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 234775ebec6dSmrg int i; 234875ebec6dSmrg int *fds; 234975ebec6dSmrg 235075ebec6dSmrg hdr->cmsg_len = msg.msg_controllen; 235175ebec6dSmrg hdr->cmsg_level = SOL_SOCKET; 235275ebec6dSmrg hdr->cmsg_type = SCM_RIGHTS; 235375ebec6dSmrg 235475ebec6dSmrg fds = (int *) CMSG_DATA(hdr); 235575ebec6dSmrg /* Set up fds */ 235675ebec6dSmrg for (i = 0; i < nfd; i++) { 235775ebec6dSmrg fds[i] = cf->fd; 235875ebec6dSmrg cf = cf->next; 235975ebec6dSmrg } 236075ebec6dSmrg 236175ebec6dSmrg i = sendmsg(ciptr->fd, &msg, 0); 236275ebec6dSmrg if (i > 0) 236375ebec6dSmrg discardFd(&ciptr->send_fds, cf, 0); 236475ebec6dSmrg return i; 236575ebec6dSmrg } 236675ebec6dSmrg#endif 236773143b9aSmrg return WRITEV (ciptr, buf, size); 236873143b9aSmrg} 236973143b9aSmrg 237073143b9aSmrg 237175ebec6dSmrgstatic int 237275ebec6dSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) 237375ebec6dSmrg 237475ebec6dSmrg{ 237575ebec6dSmrg prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); 237675ebec6dSmrg 237775ebec6dSmrg#if defined(WIN32) 237875ebec6dSmrg { 237975ebec6dSmrg int ret = send ((SOCKET)ciptr->fd, buf, size, 0); 238075ebec6dSmrg#ifdef WIN32 238175ebec6dSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 238275ebec6dSmrg#endif 238375ebec6dSmrg return ret; 238475ebec6dSmrg } 238575ebec6dSmrg#else 238675ebec6dSmrg#if XTRANS_SEND_FDS 238775ebec6dSmrg if (ciptr->send_fds) 238875ebec6dSmrg { 238975ebec6dSmrg struct iovec iov; 239075ebec6dSmrg 239175ebec6dSmrg iov.iov_base = buf; 239275ebec6dSmrg iov.iov_len = size; 239375ebec6dSmrg return TRANS(SocketWritev)(ciptr, &iov, 1); 239475ebec6dSmrg } 239575ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 239675ebec6dSmrg return write (ciptr->fd, buf, size); 239775ebec6dSmrg#endif /* WIN32 */ 239875ebec6dSmrg} 239975ebec6dSmrg 240073143b9aSmrgstatic int 240173143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr) 240273143b9aSmrg 240373143b9aSmrg{ 2404fe567363Smrg prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd); 240573143b9aSmrg 240673143b9aSmrg#ifdef WIN32 2407fe567363Smrg { 240873143b9aSmrg int ret = shutdown (ciptr->fd, 2); 240973143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 241073143b9aSmrg return ret; 241173143b9aSmrg } 241273143b9aSmrg#else 241373143b9aSmrg return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ 241473143b9aSmrg#endif 241573143b9aSmrg} 241673143b9aSmrg 241773143b9aSmrg 241873143b9aSmrg#ifdef TCPCONN 241973143b9aSmrgstatic int 242073143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr) 242173143b9aSmrg 242273143b9aSmrg{ 2423fe567363Smrg prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd); 242473143b9aSmrg 242573143b9aSmrg#ifdef WIN32 242673143b9aSmrg { 242773143b9aSmrg int ret = close (ciptr->fd); 242873143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 242973143b9aSmrg return ret; 243073143b9aSmrg } 243173143b9aSmrg#else 243273143b9aSmrg return close (ciptr->fd); 243373143b9aSmrg#endif 243473143b9aSmrg} 243573143b9aSmrg 243673143b9aSmrg#endif /* TCPCONN */ 243773143b9aSmrg 243873143b9aSmrg 243973143b9aSmrg#ifdef UNIXCONN 244073143b9aSmrgstatic int 244173143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr) 244273143b9aSmrg{ 244373143b9aSmrg /* 244473143b9aSmrg * If this is the server side, then once the socket is closed, 244573143b9aSmrg * it must be unlinked to completely close it 244673143b9aSmrg */ 244773143b9aSmrg 244873143b9aSmrg struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; 244973143b9aSmrg int ret; 245073143b9aSmrg 2451fe567363Smrg prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd); 245273143b9aSmrg 245375ebec6dSmrg#if XTRANS_SEND_FDS 245475ebec6dSmrg cleanupFds(ciptr); 245575ebec6dSmrg#endif 245673143b9aSmrg ret = close(ciptr->fd); 245773143b9aSmrg 245873143b9aSmrg if (ciptr->flags 245973143b9aSmrg && sockname 246073143b9aSmrg && sockname->sun_family == AF_UNIX 246173143b9aSmrg && sockname->sun_path[0]) 246273143b9aSmrg { 246373143b9aSmrg if (!(ciptr->flags & TRANS_NOUNLINK 246473143b9aSmrg || ciptr->transptr->flags & TRANS_ABSTRACT)) 246573143b9aSmrg unlink (sockname->sun_path); 246673143b9aSmrg } 246773143b9aSmrg 246873143b9aSmrg return ret; 246973143b9aSmrg} 247073143b9aSmrg 247173143b9aSmrgstatic int 247273143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) 247373143b9aSmrg 247473143b9aSmrg{ 247573143b9aSmrg /* 247673143b9aSmrg * Don't unlink path. 247773143b9aSmrg */ 247873143b9aSmrg 247973143b9aSmrg int ret; 248073143b9aSmrg 2481fe567363Smrg prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", 2482fe567363Smrg ciptr, ciptr->fd); 248373143b9aSmrg 248475ebec6dSmrg#if XTRANS_SEND_FDS 248575ebec6dSmrg cleanupFds(ciptr); 248675ebec6dSmrg#endif 248773143b9aSmrg ret = close(ciptr->fd); 248873143b9aSmrg 248973143b9aSmrg return ret; 249073143b9aSmrg} 249173143b9aSmrg 249273143b9aSmrg#endif /* UNIXCONN */ 249373143b9aSmrg 249473143b9aSmrg 249573143b9aSmrg#ifdef TCPCONN 249673143b9aSmrg# ifdef TRANS_SERVER 2497fe567363Smrgstatic const char* tcp_nolisten[] = { 249873143b9aSmrg "inet", 249973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 250073143b9aSmrg "inet6", 250173143b9aSmrg#endif 250273143b9aSmrg NULL 250373143b9aSmrg}; 250473143b9aSmrg# endif 250573143b9aSmrg 250673143b9aSmrgXtransport TRANS(SocketTCPFuncs) = { 250773143b9aSmrg /* Socket Interface */ 250873143b9aSmrg "tcp", 250973143b9aSmrg TRANS_ALIAS, 251073143b9aSmrg#ifdef TRANS_CLIENT 251173143b9aSmrg TRANS(SocketOpenCOTSClient), 251273143b9aSmrg#endif /* TRANS_CLIENT */ 251373143b9aSmrg#ifdef TRANS_SERVER 251473143b9aSmrg tcp_nolisten, 251573143b9aSmrg TRANS(SocketOpenCOTSServer), 251673143b9aSmrg#endif /* TRANS_SERVER */ 251773143b9aSmrg#ifdef TRANS_CLIENT 251873143b9aSmrg TRANS(SocketOpenCLTSClient), 251973143b9aSmrg#endif /* TRANS_CLIENT */ 252073143b9aSmrg#ifdef TRANS_SERVER 252173143b9aSmrg TRANS(SocketOpenCLTSServer), 252273143b9aSmrg#endif /* TRANS_SERVER */ 252373143b9aSmrg#ifdef TRANS_REOPEN 252473143b9aSmrg TRANS(SocketReopenCOTSServer), 252573143b9aSmrg TRANS(SocketReopenCLTSServer), 252673143b9aSmrg#endif 252773143b9aSmrg TRANS(SocketSetOption), 252873143b9aSmrg#ifdef TRANS_SERVER 252973143b9aSmrg TRANS(SocketINETCreateListener), 253073143b9aSmrg NULL, /* ResetListener */ 253173143b9aSmrg TRANS(SocketINETAccept), 253273143b9aSmrg#endif /* TRANS_SERVER */ 253373143b9aSmrg#ifdef TRANS_CLIENT 253473143b9aSmrg TRANS(SocketINETConnect), 253573143b9aSmrg#endif /* TRANS_CLIENT */ 253673143b9aSmrg TRANS(SocketBytesReadable), 253773143b9aSmrg TRANS(SocketRead), 253873143b9aSmrg TRANS(SocketWrite), 253973143b9aSmrg TRANS(SocketReadv), 254073143b9aSmrg TRANS(SocketWritev), 254175ebec6dSmrg#if XTRANS_SEND_FDS 254275ebec6dSmrg TRANS(SocketSendFdInvalid), 254375ebec6dSmrg TRANS(SocketRecvFdInvalid), 254475ebec6dSmrg#endif 254573143b9aSmrg TRANS(SocketDisconnect), 254673143b9aSmrg TRANS(SocketINETClose), 254773143b9aSmrg TRANS(SocketINETClose), 254873143b9aSmrg }; 254973143b9aSmrg 255073143b9aSmrgXtransport TRANS(SocketINETFuncs) = { 255173143b9aSmrg /* Socket Interface */ 255273143b9aSmrg "inet", 255373143b9aSmrg 0, 255473143b9aSmrg#ifdef TRANS_CLIENT 255573143b9aSmrg TRANS(SocketOpenCOTSClient), 255673143b9aSmrg#endif /* TRANS_CLIENT */ 255773143b9aSmrg#ifdef TRANS_SERVER 255873143b9aSmrg NULL, 255973143b9aSmrg TRANS(SocketOpenCOTSServer), 256073143b9aSmrg#endif /* TRANS_SERVER */ 256173143b9aSmrg#ifdef TRANS_CLIENT 256273143b9aSmrg TRANS(SocketOpenCLTSClient), 256373143b9aSmrg#endif /* TRANS_CLIENT */ 256473143b9aSmrg#ifdef TRANS_SERVER 256573143b9aSmrg TRANS(SocketOpenCLTSServer), 256673143b9aSmrg#endif /* TRANS_SERVER */ 256773143b9aSmrg#ifdef TRANS_REOPEN 256873143b9aSmrg TRANS(SocketReopenCOTSServer), 256973143b9aSmrg TRANS(SocketReopenCLTSServer), 257073143b9aSmrg#endif 257173143b9aSmrg TRANS(SocketSetOption), 257273143b9aSmrg#ifdef TRANS_SERVER 257373143b9aSmrg TRANS(SocketINETCreateListener), 257473143b9aSmrg NULL, /* ResetListener */ 257573143b9aSmrg TRANS(SocketINETAccept), 257673143b9aSmrg#endif /* TRANS_SERVER */ 257773143b9aSmrg#ifdef TRANS_CLIENT 257873143b9aSmrg TRANS(SocketINETConnect), 257973143b9aSmrg#endif /* TRANS_CLIENT */ 258073143b9aSmrg TRANS(SocketBytesReadable), 258173143b9aSmrg TRANS(SocketRead), 258273143b9aSmrg TRANS(SocketWrite), 258373143b9aSmrg TRANS(SocketReadv), 258473143b9aSmrg TRANS(SocketWritev), 258575ebec6dSmrg#if XTRANS_SEND_FDS 258675ebec6dSmrg TRANS(SocketSendFdInvalid), 258775ebec6dSmrg TRANS(SocketRecvFdInvalid), 258875ebec6dSmrg#endif 258973143b9aSmrg TRANS(SocketDisconnect), 259073143b9aSmrg TRANS(SocketINETClose), 259173143b9aSmrg TRANS(SocketINETClose), 259273143b9aSmrg }; 259373143b9aSmrg 259473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 259573143b9aSmrgXtransport TRANS(SocketINET6Funcs) = { 259673143b9aSmrg /* Socket Interface */ 259773143b9aSmrg "inet6", 259873143b9aSmrg 0, 259973143b9aSmrg#ifdef TRANS_CLIENT 260073143b9aSmrg TRANS(SocketOpenCOTSClient), 260173143b9aSmrg#endif /* TRANS_CLIENT */ 260273143b9aSmrg#ifdef TRANS_SERVER 260373143b9aSmrg NULL, 260473143b9aSmrg TRANS(SocketOpenCOTSServer), 260573143b9aSmrg#endif /* TRANS_SERVER */ 260673143b9aSmrg#ifdef TRANS_CLIENT 260773143b9aSmrg TRANS(SocketOpenCLTSClient), 260873143b9aSmrg#endif /* TRANS_CLIENT */ 260973143b9aSmrg#ifdef TRANS_SERVER 261073143b9aSmrg TRANS(SocketOpenCLTSServer), 261173143b9aSmrg#endif /* TRANS_SERVER */ 261273143b9aSmrg#ifdef TRANS_REOPEN 261373143b9aSmrg TRANS(SocketReopenCOTSServer), 261473143b9aSmrg TRANS(SocketReopenCLTSServer), 261573143b9aSmrg#endif 261673143b9aSmrg TRANS(SocketSetOption), 261773143b9aSmrg#ifdef TRANS_SERVER 261873143b9aSmrg TRANS(SocketINETCreateListener), 261973143b9aSmrg NULL, /* ResetListener */ 262073143b9aSmrg TRANS(SocketINETAccept), 262173143b9aSmrg#endif /* TRANS_SERVER */ 262273143b9aSmrg#ifdef TRANS_CLIENT 262373143b9aSmrg TRANS(SocketINETConnect), 262473143b9aSmrg#endif /* TRANS_CLIENT */ 262573143b9aSmrg TRANS(SocketBytesReadable), 262673143b9aSmrg TRANS(SocketRead), 262773143b9aSmrg TRANS(SocketWrite), 262873143b9aSmrg TRANS(SocketReadv), 262973143b9aSmrg TRANS(SocketWritev), 263075ebec6dSmrg#if XTRANS_SEND_FDS 263175ebec6dSmrg TRANS(SocketSendFdInvalid), 263275ebec6dSmrg TRANS(SocketRecvFdInvalid), 263375ebec6dSmrg#endif 263473143b9aSmrg TRANS(SocketDisconnect), 263573143b9aSmrg TRANS(SocketINETClose), 263673143b9aSmrg TRANS(SocketINETClose), 263773143b9aSmrg }; 263873143b9aSmrg#endif /* IPv6 */ 263973143b9aSmrg#endif /* TCPCONN */ 264073143b9aSmrg 264173143b9aSmrg#ifdef UNIXCONN 264273143b9aSmrg#if !defined(LOCALCONN) 264373143b9aSmrgXtransport TRANS(SocketLocalFuncs) = { 264473143b9aSmrg /* Socket Interface */ 264573143b9aSmrg "local", 264673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 264773143b9aSmrg TRANS_ABSTRACT, 264873143b9aSmrg#else 264973143b9aSmrg 0, 265073143b9aSmrg#endif 265173143b9aSmrg#ifdef TRANS_CLIENT 265273143b9aSmrg TRANS(SocketOpenCOTSClient), 265373143b9aSmrg#endif /* TRANS_CLIENT */ 265473143b9aSmrg#ifdef TRANS_SERVER 265573143b9aSmrg NULL, 265673143b9aSmrg TRANS(SocketOpenCOTSServer), 265773143b9aSmrg#endif /* TRANS_SERVER */ 265873143b9aSmrg#ifdef TRANS_CLIENT 265973143b9aSmrg TRANS(SocketOpenCLTSClient), 266073143b9aSmrg#endif /* TRANS_CLIENT */ 266173143b9aSmrg#ifdef TRANS_SERVER 266273143b9aSmrg TRANS(SocketOpenCLTSServer), 266373143b9aSmrg#endif /* TRANS_SERVER */ 266473143b9aSmrg#ifdef TRANS_REOPEN 266573143b9aSmrg TRANS(SocketReopenCOTSServer), 266673143b9aSmrg TRANS(SocketReopenCLTSServer), 266773143b9aSmrg#endif 266873143b9aSmrg TRANS(SocketSetOption), 266973143b9aSmrg#ifdef TRANS_SERVER 267073143b9aSmrg TRANS(SocketUNIXCreateListener), 267173143b9aSmrg TRANS(SocketUNIXResetListener), 267273143b9aSmrg TRANS(SocketUNIXAccept), 267373143b9aSmrg#endif /* TRANS_SERVER */ 267473143b9aSmrg#ifdef TRANS_CLIENT 267573143b9aSmrg TRANS(SocketUNIXConnect), 267673143b9aSmrg#endif /* TRANS_CLIENT */ 267773143b9aSmrg TRANS(SocketBytesReadable), 267873143b9aSmrg TRANS(SocketRead), 267973143b9aSmrg TRANS(SocketWrite), 268073143b9aSmrg TRANS(SocketReadv), 268173143b9aSmrg TRANS(SocketWritev), 268275ebec6dSmrg#if XTRANS_SEND_FDS 268375ebec6dSmrg TRANS(SocketSendFd), 268475ebec6dSmrg TRANS(SocketRecvFd), 268575ebec6dSmrg#endif 268673143b9aSmrg TRANS(SocketDisconnect), 268773143b9aSmrg TRANS(SocketUNIXClose), 268873143b9aSmrg TRANS(SocketUNIXCloseForCloning), 268973143b9aSmrg }; 269073143b9aSmrg#endif /* !LOCALCONN */ 269173143b9aSmrg# ifdef TRANS_SERVER 269273143b9aSmrg# if !defined(LOCALCONN) 269375ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL }; 269473143b9aSmrg# endif 269573143b9aSmrg# endif 2696fe567363Smrg 269773143b9aSmrgXtransport TRANS(SocketUNIXFuncs) = { 269873143b9aSmrg /* Socket Interface */ 269973143b9aSmrg "unix", 270073143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS) 270173143b9aSmrg TRANS_ALIAS, 270273143b9aSmrg#else 270373143b9aSmrg 0, 270473143b9aSmrg#endif 270573143b9aSmrg#ifdef TRANS_CLIENT 270673143b9aSmrg TRANS(SocketOpenCOTSClient), 270773143b9aSmrg#endif /* TRANS_CLIENT */ 270873143b9aSmrg#ifdef TRANS_SERVER 270973143b9aSmrg#if !defined(LOCALCONN) 271073143b9aSmrg unix_nolisten, 271173143b9aSmrg#else 271273143b9aSmrg NULL, 271373143b9aSmrg#endif 271473143b9aSmrg TRANS(SocketOpenCOTSServer), 271573143b9aSmrg#endif /* TRANS_SERVER */ 271673143b9aSmrg#ifdef TRANS_CLIENT 271773143b9aSmrg TRANS(SocketOpenCLTSClient), 271873143b9aSmrg#endif /* TRANS_CLIENT */ 271973143b9aSmrg#ifdef TRANS_SERVER 272073143b9aSmrg TRANS(SocketOpenCLTSServer), 272173143b9aSmrg#endif /* TRANS_SERVER */ 272273143b9aSmrg#ifdef TRANS_REOPEN 272373143b9aSmrg TRANS(SocketReopenCOTSServer), 272473143b9aSmrg TRANS(SocketReopenCLTSServer), 272573143b9aSmrg#endif 272673143b9aSmrg TRANS(SocketSetOption), 272773143b9aSmrg#ifdef TRANS_SERVER 272873143b9aSmrg TRANS(SocketUNIXCreateListener), 272973143b9aSmrg TRANS(SocketUNIXResetListener), 273073143b9aSmrg TRANS(SocketUNIXAccept), 273173143b9aSmrg#endif /* TRANS_SERVER */ 273273143b9aSmrg#ifdef TRANS_CLIENT 273373143b9aSmrg TRANS(SocketUNIXConnect), 273473143b9aSmrg#endif /* TRANS_CLIENT */ 273573143b9aSmrg TRANS(SocketBytesReadable), 273673143b9aSmrg TRANS(SocketRead), 273773143b9aSmrg TRANS(SocketWrite), 273873143b9aSmrg TRANS(SocketReadv), 273973143b9aSmrg TRANS(SocketWritev), 274075ebec6dSmrg#if XTRANS_SEND_FDS 274175ebec6dSmrg TRANS(SocketSendFd), 274275ebec6dSmrg TRANS(SocketRecvFd), 274375ebec6dSmrg#endif 274473143b9aSmrg TRANS(SocketDisconnect), 274573143b9aSmrg TRANS(SocketUNIXClose), 274673143b9aSmrg TRANS(SocketUNIXCloseForCloning), 274773143b9aSmrg }; 274873143b9aSmrg 274973143b9aSmrg#endif /* UNIXCONN */ 2750