Xtranssock.c revision 94f982db
1af928962Smrg/* 2a773ec55Smrg * Copyright (c) 2002, Oracle and/or its affiliates. 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 1158d4c0f7bSmrg#include <unistd.h> 1168d4c0f7bSmrg 11773143b9aSmrg#else /* !WIN32 */ 11873143b9aSmrg 11973143b9aSmrg#include <X11/Xwinsock.h> 12073143b9aSmrg#include <X11/Xwindows.h> 12173143b9aSmrg#include <X11/Xw32defs.h> 12273143b9aSmrg#undef close 12373143b9aSmrg#define close closesocket 12473143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED 12573143b9aSmrg#define EADDRINUSE WSAEADDRINUSE 12673143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE 12773143b9aSmrg#undef EWOULDBLOCK 12873143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK 12973143b9aSmrg#define EINPROGRESS WSAEINPROGRESS 13073143b9aSmrg#undef EINTR 13173143b9aSmrg#define EINTR WSAEINTR 13273143b9aSmrg#define X_INCLUDE_NETDB_H 13373143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI 13473143b9aSmrg#include <X11/Xos_r.h> 13573143b9aSmrg#endif /* WIN32 */ 13673143b9aSmrg 13773143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER) 13873143b9aSmrg#undef SO_DONTLINGER 13973143b9aSmrg#endif 14073143b9aSmrg 14173143b9aSmrg/* others don't need this */ 14273143b9aSmrg#define SocketInitOnce() /**/ 14373143b9aSmrg 144a773ec55Smrg#ifdef __linux__ 14573143b9aSmrg#define HAVE_ABSTRACT_SOCKETS 14673143b9aSmrg#endif 14773143b9aSmrg 14873143b9aSmrg#define MIN_BACKLOG 128 14973143b9aSmrg#ifdef SOMAXCONN 15073143b9aSmrg#if SOMAXCONN > MIN_BACKLOG 15173143b9aSmrg#define BACKLOG SOMAXCONN 15273143b9aSmrg#endif 15373143b9aSmrg#endif 15473143b9aSmrg#ifndef BACKLOG 15573143b9aSmrg#define BACKLOG MIN_BACKLOG 15673143b9aSmrg#endif 15773143b9aSmrg 15873143b9aSmrg/* 15973143b9aSmrg * This is the Socket implementation of the X Transport service layer 16073143b9aSmrg * 16173143b9aSmrg * This file contains the implementation for both the UNIX and INET domains, 16273143b9aSmrg * and can be built for either one, or both. 16373143b9aSmrg * 16473143b9aSmrg */ 16573143b9aSmrg 166fe567363Smrgtypedef struct _Sockettrans2dev { 167fe567363Smrg const char *transname; 16873143b9aSmrg int family; 16973143b9aSmrg int devcotsname; 17073143b9aSmrg int devcltsname; 17173143b9aSmrg int protocol; 17273143b9aSmrg} Sockettrans2dev; 17373143b9aSmrg 17473143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = { 17573143b9aSmrg#ifdef TCPCONN 17673143b9aSmrg {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 17773143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6) 17873143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 17973143b9aSmrg#else /* IPv6 */ 18073143b9aSmrg {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 18173143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ 18273143b9aSmrg {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 18373143b9aSmrg#endif 18473143b9aSmrg#endif /* TCPCONN */ 18573143b9aSmrg#ifdef UNIXCONN 18673143b9aSmrg {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 18773143b9aSmrg#if !defined(LOCALCONN) 18873143b9aSmrg {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 18973143b9aSmrg#endif /* !LOCALCONN */ 19073143b9aSmrg#endif /* UNIXCONN */ 19173143b9aSmrg}; 19273143b9aSmrg 19373143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev)) 19473143b9aSmrg 19573143b9aSmrg#ifdef TCPCONN 19673143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr); 19773143b9aSmrg#endif 19873143b9aSmrg 19994f982dbSmrg#if (defined(TCPCONN) && defined(TRANS_SERVER)) || defined(TRANS_REOPEN) || \ 20094f982dbSmrg !defined(IPv6) 201a773ec55Smrgstatic int 202a773ec55Smrgis_numeric (const char *str) 203a773ec55Smrg{ 204a773ec55Smrg int i; 205a773ec55Smrg 206a773ec55Smrg for (i = 0; i < (int) strlen (str); i++) 207a773ec55Smrg if (!isdigit (str[i])) 208a773ec55Smrg return (0); 209a773ec55Smrg 210a773ec55Smrg return (1); 211a773ec55Smrg} 212a773ec55Smrg#endif 213a773ec55Smrg 21473143b9aSmrg#ifdef UNIXCONN 21573143b9aSmrg 21673143b9aSmrg 21773143b9aSmrg#if defined(X11_t) 21873143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 21973143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 22073143b9aSmrg#endif /* X11_t */ 22173143b9aSmrg#if defined(XIM_t) 22273143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM" 22373143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix" 22473143b9aSmrg#endif /* XIM_t */ 22573143b9aSmrg#if defined(FS_t) || defined(FONT_t) 22673143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs" 22773143b9aSmrg#define UNIX_DIR "/tmp/.font-unix" 22873143b9aSmrg#endif /* FS_t || FONT_t */ 22973143b9aSmrg#if defined(ICE_t) 23073143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/" 23173143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix" 23273143b9aSmrg#endif /* ICE_t */ 23373143b9aSmrg 23473143b9aSmrg 23573143b9aSmrg#endif /* UNIXCONN */ 23673143b9aSmrg 23773143b9aSmrg#define PORTBUFSIZE 32 23873143b9aSmrg 23973143b9aSmrg#ifndef MAXHOSTNAMELEN 24073143b9aSmrg#define MAXHOSTNAMELEN 255 24173143b9aSmrg#endif 24273143b9aSmrg 24373143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6)) 24473143b9aSmrg# define SOCKLEN_T socklen_t 245a773ec55Smrg#elif defined(SVR4) || defined(__SVR4) 246fe567363Smrg# define SOCKLEN_T size_t 24773143b9aSmrg#else 24873143b9aSmrg# define SOCKLEN_T int 24973143b9aSmrg#endif 25073143b9aSmrg 25173143b9aSmrg/* 25273143b9aSmrg * These are some utility function used by the real interface function below. 25373143b9aSmrg */ 25473143b9aSmrg 25573143b9aSmrgstatic int 256fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family) 25773143b9aSmrg 25873143b9aSmrg{ 25973143b9aSmrg int i; 26073143b9aSmrg 261fe567363Smrg prmsg (3,"SocketSelectFamily(%s)\n", family); 26273143b9aSmrg 26394f982dbSmrg for (i = first + 1; i < (int)NUMSOCKETFAMILIES; i++) 26473143b9aSmrg { 26573143b9aSmrg if (!strcmp (family, Sockettrans2devtab[i].transname)) 26673143b9aSmrg return i; 26773143b9aSmrg } 26873143b9aSmrg 26973143b9aSmrg return (first == -1 ? -2 : -1); 27073143b9aSmrg} 27173143b9aSmrg 27273143b9aSmrg 27373143b9aSmrg/* 27473143b9aSmrg * This function gets the local address of the socket and stores it in the 27573143b9aSmrg * XtransConnInfo structure for the connection. 27673143b9aSmrg */ 27773143b9aSmrg 27873143b9aSmrgstatic int 27973143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr) 28073143b9aSmrg 28173143b9aSmrg{ 28273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 28373143b9aSmrg struct sockaddr_storage socknamev6; 284b53e5eeaSmrg#else 28573143b9aSmrg struct sockaddr_in socknamev4; 286b53e5eeaSmrg#endif 28773143b9aSmrg void *socknamePtr; 28873143b9aSmrg SOCKLEN_T namelen; 28973143b9aSmrg 290fe567363Smrg prmsg (3,"SocketINETGetAddr(%p)\n", ciptr); 29173143b9aSmrg 29273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 293b53e5eeaSmrg namelen = sizeof(socknamev6); 294b53e5eeaSmrg socknamePtr = &socknamev6; 295b53e5eeaSmrg#else 296b53e5eeaSmrg namelen = sizeof(socknamev4); 297b53e5eeaSmrg socknamePtr = &socknamev4; 29873143b9aSmrg#endif 29973143b9aSmrg 30073143b9aSmrg bzero(socknamePtr, namelen); 301fe567363Smrg 30273143b9aSmrg if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, 30373143b9aSmrg (void *)&namelen) < 0) 30473143b9aSmrg { 30573143b9aSmrg#ifdef WIN32 30673143b9aSmrg errno = WSAGetLastError(); 30773143b9aSmrg#endif 308fe567363Smrg prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n", 309fe567363Smrg EGET()); 31073143b9aSmrg return -1; 31173143b9aSmrg } 31273143b9aSmrg 31373143b9aSmrg /* 31473143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 31573143b9aSmrg */ 31673143b9aSmrg 317fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 31873143b9aSmrg { 319fe567363Smrg prmsg (1, 320fe567363Smrg "SocketINETGetAddr: Can't allocate space for the addr\n"); 32173143b9aSmrg return -1; 32273143b9aSmrg } 32373143b9aSmrg 32473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 325b53e5eeaSmrg ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; 326b53e5eeaSmrg#else 327b53e5eeaSmrg ciptr->family = socknamev4.sin_family; 32873143b9aSmrg#endif 32973143b9aSmrg ciptr->addrlen = namelen; 33073143b9aSmrg memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); 33173143b9aSmrg 33273143b9aSmrg return 0; 33373143b9aSmrg} 33473143b9aSmrg 33573143b9aSmrg 33673143b9aSmrg/* 33773143b9aSmrg * This function gets the remote address of the socket and stores it in the 33873143b9aSmrg * XtransConnInfo structure for the connection. 33973143b9aSmrg */ 34073143b9aSmrg 34173143b9aSmrgstatic int 34273143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) 34373143b9aSmrg 34473143b9aSmrg{ 34573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 34673143b9aSmrg struct sockaddr_storage socknamev6; 34773143b9aSmrg#endif 34873143b9aSmrg struct sockaddr_in socknamev4; 34973143b9aSmrg void *socknamePtr; 35073143b9aSmrg SOCKLEN_T namelen; 35173143b9aSmrg 35273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 353b53e5eeaSmrg if (ciptr->family == AF_INET6) 35473143b9aSmrg { 35573143b9aSmrg namelen = sizeof(socknamev6); 35673143b9aSmrg socknamePtr = &socknamev6; 35773143b9aSmrg } 35873143b9aSmrg else 35973143b9aSmrg#endif 36073143b9aSmrg { 36173143b9aSmrg namelen = sizeof(socknamev4); 36273143b9aSmrg socknamePtr = &socknamev4; 36373143b9aSmrg } 36473143b9aSmrg 36573143b9aSmrg bzero(socknamePtr, namelen); 366fe567363Smrg 367fe567363Smrg prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr); 36873143b9aSmrg 36973143b9aSmrg if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, 37073143b9aSmrg (void *)&namelen) < 0) 37173143b9aSmrg { 37273143b9aSmrg#ifdef WIN32 37373143b9aSmrg errno = WSAGetLastError(); 37473143b9aSmrg#endif 375fe567363Smrg prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", 376fe567363Smrg EGET()); 37773143b9aSmrg return -1; 37873143b9aSmrg } 37973143b9aSmrg 38073143b9aSmrg /* 38173143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 38273143b9aSmrg */ 38373143b9aSmrg 384fe567363Smrg if ((ciptr->peeraddr = malloc (namelen)) == NULL) 38573143b9aSmrg { 386fe567363Smrg prmsg (1, 387fe567363Smrg "SocketINETGetPeerAddr: Can't allocate space for the addr\n"); 38873143b9aSmrg return -1; 38973143b9aSmrg } 39073143b9aSmrg 39173143b9aSmrg ciptr->peeraddrlen = namelen; 39273143b9aSmrg memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); 39373143b9aSmrg 39473143b9aSmrg return 0; 39573143b9aSmrg} 39673143b9aSmrg 39773143b9aSmrg 39873143b9aSmrgstatic XtransConnInfo 39973143b9aSmrgTRANS(SocketOpen) (int i, int type) 40073143b9aSmrg 40173143b9aSmrg{ 40273143b9aSmrg XtransConnInfo ciptr; 40373143b9aSmrg 404fe567363Smrg prmsg (3,"SocketOpen(%d,%d)\n", i, type); 40573143b9aSmrg 406fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 40773143b9aSmrg { 408fe567363Smrg prmsg (1, "SocketOpen: malloc failed\n"); 40973143b9aSmrg return NULL; 41073143b9aSmrg } 41173143b9aSmrg 41294f982dbSmrg ciptr->fd = socket(Sockettrans2devtab[i].family, type, 41394f982dbSmrg Sockettrans2devtab[i].protocol); 41494f982dbSmrg 41573143b9aSmrg#ifndef WIN32 41673143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) 41794f982dbSmrg if (ciptr->fd >= sysconf(_SC_OPEN_MAX)) 41894f982dbSmrg { 41994f982dbSmrg prmsg (2, "SocketOpen: socket() returned out of range fd %d\n", 42094f982dbSmrg ciptr->fd); 42194f982dbSmrg close (ciptr->fd); 42294f982dbSmrg ciptr->fd = -1; 42394f982dbSmrg } 42473143b9aSmrg#endif 42573143b9aSmrg#endif 42694f982dbSmrg 42794f982dbSmrg if (ciptr->fd < 0) { 42873143b9aSmrg#ifdef WIN32 42973143b9aSmrg errno = WSAGetLastError(); 43073143b9aSmrg#endif 431fe567363Smrg prmsg (2, "SocketOpen: socket() failed for %s\n", 432fe567363Smrg Sockettrans2devtab[i].transname); 43373143b9aSmrg 434fe567363Smrg free (ciptr); 43573143b9aSmrg return NULL; 43673143b9aSmrg } 43773143b9aSmrg 43873143b9aSmrg#ifdef TCP_NODELAY 43973143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 44073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 44173143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 44273143b9aSmrg#endif 44373143b9aSmrg ) 44473143b9aSmrg { 44573143b9aSmrg /* 44673143b9aSmrg * turn off TCP coalescence for INET sockets 44773143b9aSmrg */ 44873143b9aSmrg 44973143b9aSmrg int tmp = 1; 45073143b9aSmrg setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, 45173143b9aSmrg (char *) &tmp, sizeof (int)); 45273143b9aSmrg } 45373143b9aSmrg#endif 45473143b9aSmrg 4558a0d9095Smrg /* 4568a0d9095Smrg * Some systems provide a really small default buffer size for 4578a0d9095Smrg * UNIX sockets. Bump it up a bit such that large transfers don't 4588a0d9095Smrg * proceed at glacial speed. 4598a0d9095Smrg */ 4608a0d9095Smrg#ifdef SO_SNDBUF 4618a0d9095Smrg if (Sockettrans2devtab[i].family == AF_UNIX) 4628a0d9095Smrg { 4638a0d9095Smrg SOCKLEN_T len = sizeof (int); 4648a0d9095Smrg int val; 4658a0d9095Smrg 4668a0d9095Smrg if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4678a0d9095Smrg (char *) &val, &len) == 0 && val < 64 * 1024) 4688a0d9095Smrg { 4698a0d9095Smrg val = 64 * 1024; 4708a0d9095Smrg setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4718a0d9095Smrg (char *) &val, sizeof (int)); 4728a0d9095Smrg } 4738a0d9095Smrg } 4748a0d9095Smrg#endif 4758a0d9095Smrg 47673143b9aSmrg return ciptr; 47773143b9aSmrg} 47873143b9aSmrg 47973143b9aSmrg 48073143b9aSmrg#ifdef TRANS_REOPEN 48173143b9aSmrg 48273143b9aSmrgstatic XtransConnInfo 4836a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port) 48473143b9aSmrg 48573143b9aSmrg{ 48673143b9aSmrg XtransConnInfo ciptr; 48773143b9aSmrg int portlen; 48873143b9aSmrg struct sockaddr *addr; 489fe567363Smrg size_t addrlen; 49073143b9aSmrg 491fe567363Smrg prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); 49273143b9aSmrg 49373143b9aSmrg if (port == NULL) { 494fe567363Smrg prmsg (1, "SocketReopen: port was null!\n"); 49573143b9aSmrg return NULL; 49673143b9aSmrg } 49773143b9aSmrg 49873143b9aSmrg portlen = strlen(port) + 1; // include space for trailing null 49973143b9aSmrg#ifdef SOCK_MAXADDRLEN 50073143b9aSmrg if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { 501fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 50273143b9aSmrg return NULL; 50373143b9aSmrg } 50473143b9aSmrg if (portlen < 14) portlen = 14; 50573143b9aSmrg#else 50673143b9aSmrg if (portlen < 0 || portlen > 14) { 507fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 50873143b9aSmrg return NULL; 50973143b9aSmrg } 51073143b9aSmrg#endif /*SOCK_MAXADDRLEN*/ 51173143b9aSmrg 512fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 51373143b9aSmrg { 514fe567363Smrg prmsg (1, "SocketReopen: malloc(ciptr) failed\n"); 51573143b9aSmrg return NULL; 51673143b9aSmrg } 51773143b9aSmrg 51873143b9aSmrg ciptr->fd = fd; 51973143b9aSmrg 520fe567363Smrg addrlen = portlen + offsetof(struct sockaddr, sa_data); 521fe567363Smrg if ((addr = calloc (1, addrlen)) == NULL) { 522fe567363Smrg prmsg (1, "SocketReopen: malloc(addr) failed\n"); 523fe567363Smrg free (ciptr); 52473143b9aSmrg return NULL; 52573143b9aSmrg } 5268d4c0f7bSmrg ciptr->addr = (char *) addr; 527fe567363Smrg ciptr->addrlen = addrlen; 52873143b9aSmrg 529fe567363Smrg if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { 530fe567363Smrg prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); 531fe567363Smrg free (addr); 532fe567363Smrg free (ciptr); 53373143b9aSmrg return NULL; 53473143b9aSmrg } 535fe567363Smrg ciptr->peeraddrlen = addrlen; 53673143b9aSmrg 53773143b9aSmrg /* Initialize ciptr structure as if it were a normally-opened unix socket */ 53873143b9aSmrg ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; 53973143b9aSmrg#ifdef BSD44SOCKETS 540fe567363Smrg addr->sa_len = addrlen; 54173143b9aSmrg#endif 54273143b9aSmrg addr->sa_family = AF_UNIX; 5437448d6e9Smrg#if defined(HAVE_STRLCPY) || defined(HAS_STRLCPY) 54473143b9aSmrg strlcpy(addr->sa_data, port, portlen); 54573143b9aSmrg#else 54673143b9aSmrg strncpy(addr->sa_data, port, portlen); 54773143b9aSmrg#endif 54873143b9aSmrg ciptr->family = AF_UNIX; 549fe567363Smrg memcpy(ciptr->peeraddr, ciptr->addr, addrlen); 55073143b9aSmrg ciptr->port = rindex(addr->sa_data, ':'); 551e8a71cdfSmrg if (ciptr->port == NULL) { 552e8a71cdfSmrg if (is_numeric(addr->sa_data)) { 553e8a71cdfSmrg ciptr->port = addr->sa_data; 554e8a71cdfSmrg } 555e8a71cdfSmrg } else if (ciptr->port[0] == ':') { 556e8a71cdfSmrg ciptr->port++; 557e8a71cdfSmrg } 558e8a71cdfSmrg /* port should now point to portnum or NULL */ 55973143b9aSmrg return ciptr; 56073143b9aSmrg} 56173143b9aSmrg 56273143b9aSmrg#endif /* TRANS_REOPEN */ 56373143b9aSmrg 56473143b9aSmrg 56573143b9aSmrg/* 56673143b9aSmrg * These functions are the interface supplied in the Xtransport structure 56773143b9aSmrg */ 56873143b9aSmrg 56973143b9aSmrg#ifdef TRANS_CLIENT 57073143b9aSmrg 57173143b9aSmrgstatic XtransConnInfo 572fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol, 573fe567363Smrg const char *host, const char *port, int previndex) 57473143b9aSmrg{ 57573143b9aSmrg XtransConnInfo ciptr; 57673143b9aSmrg int i = previndex; 57773143b9aSmrg 578fe567363Smrg prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n", 57973143b9aSmrg protocol, host, port); 58073143b9aSmrg 58173143b9aSmrg SocketInitOnce(); 58273143b9aSmrg 58373143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { 58473143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 585e8a71cdfSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) { 586e8a71cdfSmrg /* Save the index for later use */ 587e8a71cdfSmrg 588e8a71cdfSmrg ciptr->index = i; 58973143b9aSmrg break; 590e8a71cdfSmrg } 59173143b9aSmrg } 59273143b9aSmrg if (i < 0) { 59373143b9aSmrg if (i == -1) 594fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", 595fe567363Smrg transname); 59673143b9aSmrg else 597fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", 598fe567363Smrg transname); 59973143b9aSmrg return NULL; 60073143b9aSmrg } 60173143b9aSmrg 60273143b9aSmrg return ciptr; 60373143b9aSmrg} 60473143b9aSmrg 60573143b9aSmrgstatic XtransConnInfo 6066a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol, 6076a3641a6Ssnj const char *host, const char *port) 60873143b9aSmrg{ 60973143b9aSmrg return TRANS(SocketOpenCOTSClientBase)( 61073143b9aSmrg thistrans->TransName, protocol, host, port, -1); 61173143b9aSmrg} 61273143b9aSmrg 61373143b9aSmrg 61473143b9aSmrg#endif /* TRANS_CLIENT */ 61573143b9aSmrg 61673143b9aSmrg 61773143b9aSmrg#ifdef TRANS_SERVER 61873143b9aSmrg 61973143b9aSmrgstatic XtransConnInfo 6206a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol, 6216a3641a6Ssnj const char *host, const char *port) 62273143b9aSmrg 62373143b9aSmrg{ 62473143b9aSmrg XtransConnInfo ciptr; 62573143b9aSmrg int i = -1; 62673143b9aSmrg 627fe567363Smrg prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); 62873143b9aSmrg 62973143b9aSmrg SocketInitOnce(); 63073143b9aSmrg 63173143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 63273143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 63373143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 63473143b9aSmrg break; 63573143b9aSmrg } 63673143b9aSmrg if (i < 0) { 637a773ec55Smrg if (i == -1) { 638a773ec55Smrg if (errno == EAFNOSUPPORT) { 639a773ec55Smrg thistrans->flags |= TRANS_NOLISTEN; 640a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Socket for %s unsupported on this system.\n", 641a773ec55Smrg thistrans->TransName); 642a773ec55Smrg } else { 643a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", 644a773ec55Smrg thistrans->TransName); 645a773ec55Smrg } 646a773ec55Smrg } else { 647fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", 648fe567363Smrg thistrans->TransName); 649a773ec55Smrg } 65073143b9aSmrg return NULL; 65173143b9aSmrg } 65273143b9aSmrg 65373143b9aSmrg /* 65473143b9aSmrg * Using this prevents the bind() check for an existing server listening 65573143b9aSmrg * on the same port, but it is required for other reasons. 65673143b9aSmrg */ 65773143b9aSmrg#ifdef SO_REUSEADDR 65873143b9aSmrg 65973143b9aSmrg /* 66073143b9aSmrg * SO_REUSEADDR only applied to AF_INET && AF_INET6 66173143b9aSmrg */ 66273143b9aSmrg 66373143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 66473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 66573143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 66673143b9aSmrg#endif 66773143b9aSmrg ) 66873143b9aSmrg { 66973143b9aSmrg int one = 1; 67073143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, 67173143b9aSmrg (char *) &one, sizeof (int)); 67273143b9aSmrg } 67373143b9aSmrg#endif 67473143b9aSmrg#ifdef IPV6_V6ONLY 67573143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 67673143b9aSmrg { 67773143b9aSmrg int one = 1; 67873143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 67973143b9aSmrg } 68073143b9aSmrg#endif 68173143b9aSmrg /* Save the index for later use */ 68273143b9aSmrg 68373143b9aSmrg ciptr->index = i; 68473143b9aSmrg 68573143b9aSmrg return ciptr; 68673143b9aSmrg} 68773143b9aSmrg 68873143b9aSmrg#endif /* TRANS_SERVER */ 68973143b9aSmrg 69073143b9aSmrg 69173143b9aSmrg#ifdef TRANS_REOPEN 69273143b9aSmrg 69373143b9aSmrgstatic XtransConnInfo 6946a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port) 69573143b9aSmrg 69673143b9aSmrg{ 69773143b9aSmrg XtransConnInfo ciptr; 69873143b9aSmrg int i = -1; 69973143b9aSmrg 700fe567363Smrg prmsg (2, 701fe567363Smrg "SocketReopenCOTSServer(%d, %s)\n", fd, port); 70273143b9aSmrg 70373143b9aSmrg SocketInitOnce(); 70473143b9aSmrg 70573143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 70673143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 70773143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 70873143b9aSmrg break; 70973143b9aSmrg } 71073143b9aSmrg if (i < 0) { 71173143b9aSmrg if (i == -1) 712fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", 713fe567363Smrg thistrans->TransName); 71473143b9aSmrg else 715fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", 716fe567363Smrg thistrans->TransName); 71773143b9aSmrg return NULL; 71873143b9aSmrg } 71973143b9aSmrg 72073143b9aSmrg /* Save the index for later use */ 72173143b9aSmrg 72273143b9aSmrg ciptr->index = i; 72373143b9aSmrg 72473143b9aSmrg return ciptr; 72573143b9aSmrg} 72673143b9aSmrg 72773143b9aSmrg#endif /* TRANS_REOPEN */ 72873143b9aSmrg 72973143b9aSmrg 73073143b9aSmrgstatic int 73173143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) 73273143b9aSmrg 73373143b9aSmrg{ 734fe567363Smrg prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); 73573143b9aSmrg 73673143b9aSmrg return -1; 73773143b9aSmrg} 73873143b9aSmrg 73973143b9aSmrg#ifdef UNIXCONN 74073143b9aSmrgstatic int 74173143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract) 74273143b9aSmrg{ 74373143b9aSmrg struct sockaddr_un s; 74494f982dbSmrg ssize_t maxlen = sizeof(s.sun_path) - 1; 74573143b9aSmrg const char *at = ""; 74673143b9aSmrg 74773143b9aSmrg if (!port || !*port || !path) 74873143b9aSmrg return -1; 74973143b9aSmrg 75073143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 75173143b9aSmrg if (port[0] == '@') 75273143b9aSmrg upath = ""; 75373143b9aSmrg else if (abstract) 75473143b9aSmrg at = "@"; 75573143b9aSmrg#endif 75673143b9aSmrg 75773143b9aSmrg if (*port == '/') /* a full pathname */ 75873143b9aSmrg upath = ""; 75973143b9aSmrg 76094f982dbSmrg if ((ssize_t)(strlen(at) + strlen(upath) + strlen(port)) > maxlen) 76173143b9aSmrg return -1; 762fe567363Smrg snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port); 76373143b9aSmrg return 0; 76473143b9aSmrg} 76573143b9aSmrg#endif 76673143b9aSmrg 76773143b9aSmrg#ifdef TRANS_SERVER 76873143b9aSmrg 76973143b9aSmrgstatic int 770fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr, 77173143b9aSmrg struct sockaddr *sockname, 77273143b9aSmrg int socknamelen, unsigned int flags) 77373143b9aSmrg 77473143b9aSmrg{ 77573143b9aSmrg SOCKLEN_T namelen = socknamelen; 77673143b9aSmrg int fd = ciptr->fd; 77773143b9aSmrg int retry; 77873143b9aSmrg 779fe567363Smrg prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd); 78073143b9aSmrg 78173143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 78273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 78373143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 78473143b9aSmrg#endif 78573143b9aSmrg ) 78673143b9aSmrg retry = 20; 78773143b9aSmrg else 78873143b9aSmrg retry = 0; 78973143b9aSmrg 79094f982dbSmrg while (bind (fd, sockname, namelen) < 0) 79173143b9aSmrg { 79273143b9aSmrg if (errno == EADDRINUSE) { 79373143b9aSmrg if (flags & ADDR_IN_USE_ALLOWED) 79473143b9aSmrg break; 79573143b9aSmrg else 79673143b9aSmrg return TRANS_ADDR_IN_USE; 79773143b9aSmrg } 798fe567363Smrg 79973143b9aSmrg if (retry-- == 0) { 800fe567363Smrg prmsg (1, "SocketCreateListener: failed to bind listener\n"); 80173143b9aSmrg close (fd); 80273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 80373143b9aSmrg } 80473143b9aSmrg#ifdef SO_REUSEADDR 80573143b9aSmrg sleep (1); 80673143b9aSmrg#else 80773143b9aSmrg sleep (10); 80873143b9aSmrg#endif /* SO_REUSEDADDR */ 80973143b9aSmrg } 81073143b9aSmrg 81173143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 81273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 81373143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 81473143b9aSmrg#endif 81573143b9aSmrg ) { 81673143b9aSmrg#ifdef SO_DONTLINGER 81773143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); 81873143b9aSmrg#else 81973143b9aSmrg#ifdef SO_LINGER 82073143b9aSmrg { 82173143b9aSmrg static int linger[2] = { 0, 0 }; 82273143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_LINGER, 82373143b9aSmrg (char *) linger, sizeof (linger)); 82473143b9aSmrg } 82573143b9aSmrg#endif 82673143b9aSmrg#endif 82773143b9aSmrg} 82873143b9aSmrg 82973143b9aSmrg if (listen (fd, BACKLOG) < 0) 83073143b9aSmrg { 831fe567363Smrg prmsg (1, "SocketCreateListener: listen() failed\n"); 83273143b9aSmrg close (fd); 83373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 83473143b9aSmrg } 835fe567363Smrg 83673143b9aSmrg /* Set a flag to indicate that this connection is a listener */ 83773143b9aSmrg 83873143b9aSmrg ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 83973143b9aSmrg 84073143b9aSmrg return 0; 84173143b9aSmrg} 84273143b9aSmrg 84373143b9aSmrg#ifdef TCPCONN 84473143b9aSmrgstatic int 8456a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port, 8466a3641a6Ssnj unsigned int flags) 84773143b9aSmrg 84873143b9aSmrg{ 84973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 85073143b9aSmrg struct sockaddr_storage sockname; 85173143b9aSmrg#else 85273143b9aSmrg struct sockaddr_in sockname; 85373143b9aSmrg#endif 85473143b9aSmrg unsigned short sport; 85573143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 85673143b9aSmrg int status; 85773143b9aSmrg long tmpport; 85873143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 85973143b9aSmrg _Xgetservbynameparams sparams; 86073143b9aSmrg#endif 86173143b9aSmrg struct servent *servp; 86273143b9aSmrg 86373143b9aSmrg#ifdef X11_t 86473143b9aSmrg char portbuf[PORTBUFSIZE]; 86573143b9aSmrg#endif 866fe567363Smrg 867fe567363Smrg prmsg (2, "SocketINETCreateListener(%s)\n", port); 86873143b9aSmrg 86973143b9aSmrg#ifdef X11_t 87073143b9aSmrg /* 87173143b9aSmrg * X has a well known port, that is transport dependent. It is easier 87273143b9aSmrg * to handle it here, than try and come up with a transport independent 87373143b9aSmrg * representation that can be passed in and resolved the usual way. 87473143b9aSmrg * 87573143b9aSmrg * The port that is passed here is really a string containing the idisplay 87673143b9aSmrg * from ConnectDisplay(). 87773143b9aSmrg */ 87873143b9aSmrg 87973143b9aSmrg if (is_numeric (port)) 88073143b9aSmrg { 88173143b9aSmrg /* fixup the server port address */ 88273143b9aSmrg tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 883fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 88473143b9aSmrg port = portbuf; 88573143b9aSmrg } 88673143b9aSmrg#endif 88773143b9aSmrg 88873143b9aSmrg if (port && *port) 88973143b9aSmrg { 89073143b9aSmrg /* Check to see if the port string is just a number (handles X11) */ 89173143b9aSmrg 89273143b9aSmrg if (!is_numeric (port)) 89373143b9aSmrg { 89473143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) 89573143b9aSmrg { 896fe567363Smrg prmsg (1, 89773143b9aSmrg "SocketINETCreateListener: Unable to get service for %s\n", 898fe567363Smrg port); 89973143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 90073143b9aSmrg } 90173143b9aSmrg /* we trust getservbyname to return a valid number */ 90273143b9aSmrg sport = servp->s_port; 90373143b9aSmrg } 90473143b9aSmrg else 90573143b9aSmrg { 90673143b9aSmrg tmpport = strtol (port, (char**)NULL, 10); 907fe567363Smrg /* 90873143b9aSmrg * check that somehow the port address isn't negative or in 90973143b9aSmrg * the range of reserved port addresses. This can happen and 910fe567363Smrg * be very bad if the server is suid-root and the user does 911fe567363Smrg * something (dumb) like `X :60049`. 91273143b9aSmrg */ 91373143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 91473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 91573143b9aSmrg 91673143b9aSmrg sport = (unsigned short) tmpport; 91773143b9aSmrg } 91873143b9aSmrg } 91973143b9aSmrg else 92073143b9aSmrg sport = 0; 92173143b9aSmrg 92273143b9aSmrg bzero(&sockname, sizeof(sockname)); 92373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 92473143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 92573143b9aSmrg namelen = sizeof (struct sockaddr_in); 92673143b9aSmrg#ifdef BSD44SOCKETS 92773143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_len = namelen; 92873143b9aSmrg#endif 92973143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; 93073143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); 93173143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); 93273143b9aSmrg } else { 93373143b9aSmrg namelen = sizeof (struct sockaddr_in6); 93473143b9aSmrg#ifdef SIN6_LEN 93573143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); 93673143b9aSmrg#endif 93773143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; 93873143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); 93973143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; 94073143b9aSmrg } 94173143b9aSmrg#else 94273143b9aSmrg#ifdef BSD44SOCKETS 94373143b9aSmrg sockname.sin_len = sizeof (sockname); 94473143b9aSmrg#endif 94573143b9aSmrg sockname.sin_family = AF_INET; 94673143b9aSmrg sockname.sin_port = htons (sport); 94773143b9aSmrg sockname.sin_addr.s_addr = htonl (INADDR_ANY); 94873143b9aSmrg#endif 94973143b9aSmrg 95073143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 95173143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 95273143b9aSmrg { 953fe567363Smrg prmsg (1, 954fe567363Smrg "SocketINETCreateListener: ...SocketCreateListener() failed\n"); 95573143b9aSmrg return status; 95673143b9aSmrg } 95773143b9aSmrg 95873143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 95973143b9aSmrg { 960fe567363Smrg prmsg (1, 961fe567363Smrg "SocketINETCreateListener: ...SocketINETGetAddr() failed\n"); 96273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 96373143b9aSmrg } 96473143b9aSmrg 96573143b9aSmrg return 0; 96673143b9aSmrg} 96773143b9aSmrg 96873143b9aSmrg#endif /* TCPCONN */ 96973143b9aSmrg 97073143b9aSmrg 97173143b9aSmrg#ifdef UNIXCONN 97273143b9aSmrg 97373143b9aSmrgstatic int 9746a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port, 97573143b9aSmrg unsigned int flags) 97673143b9aSmrg 97773143b9aSmrg{ 97873143b9aSmrg struct sockaddr_un sockname; 97973143b9aSmrg int namelen; 98073143b9aSmrg int oldUmask; 98173143b9aSmrg int status; 98273143b9aSmrg unsigned int mode; 98373143b9aSmrg char tmpport[108]; 98473143b9aSmrg 98573143b9aSmrg int abstract = 0; 98673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 98773143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 98873143b9aSmrg#endif 98973143b9aSmrg 990fe567363Smrg prmsg (2, "SocketUNIXCreateListener(%s)\n", 991fe567363Smrg port ? port : "NULL"); 99273143b9aSmrg 99373143b9aSmrg /* Make sure the directory is created */ 99473143b9aSmrg 99573143b9aSmrg oldUmask = umask (0); 99673143b9aSmrg 99773143b9aSmrg#ifdef UNIX_DIR 99873143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 99973143b9aSmrg mode = 01777; 100073143b9aSmrg#else 100173143b9aSmrg mode = 0777; 100273143b9aSmrg#endif 10038d4c0f7bSmrg if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) { 1004fe567363Smrg prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", 1005fe567363Smrg UNIX_DIR, errno); 100673143b9aSmrg (void) umask (oldUmask); 100773143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 100873143b9aSmrg } 100973143b9aSmrg#endif 101073143b9aSmrg 101173143b9aSmrg memset(&sockname, 0, sizeof(sockname)); 101273143b9aSmrg sockname.sun_family = AF_UNIX; 101373143b9aSmrg 101473143b9aSmrg if (!(port && *port)) { 101573143b9aSmrg snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid()); 101673143b9aSmrg port = tmpport; 101773143b9aSmrg } 101873143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1019fe567363Smrg prmsg (1, "SocketUNIXCreateListener: path too long\n"); 102073143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 102173143b9aSmrg } 102273143b9aSmrg 1023a773ec55Smrg#if defined(BSD44SOCKETS) 102473143b9aSmrg sockname.sun_len = strlen(sockname.sun_path); 102573143b9aSmrg#endif 102673143b9aSmrg 102773143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 102873143b9aSmrg namelen = SUN_LEN(&sockname); 102973143b9aSmrg#else 103073143b9aSmrg namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 103173143b9aSmrg#endif 103273143b9aSmrg 103373143b9aSmrg if (abstract) { 103473143b9aSmrg sockname.sun_path[0] = '\0'; 103573143b9aSmrg namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]); 103673143b9aSmrg } 103773143b9aSmrg else 103873143b9aSmrg unlink (sockname.sun_path); 103973143b9aSmrg 104073143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 104173143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 104273143b9aSmrg { 1043fe567363Smrg prmsg (1, 1044fe567363Smrg "SocketUNIXCreateListener: ...SocketCreateListener() failed\n"); 104573143b9aSmrg (void) umask (oldUmask); 104673143b9aSmrg return status; 104773143b9aSmrg } 104873143b9aSmrg 104973143b9aSmrg /* 105073143b9aSmrg * Now that the listener is esablished, create the addr info for 105173143b9aSmrg * this connection. getpeername() doesn't work for UNIX Domain Sockets 105273143b9aSmrg * on some systems (hpux at least), so we will just do it manually, instead 105373143b9aSmrg * of calling something like TRANS(SocketUNIXGetAddr). 105473143b9aSmrg */ 105573143b9aSmrg 105673143b9aSmrg namelen = sizeof (sockname); /* this will always make it the same size */ 105773143b9aSmrg 1058fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 105973143b9aSmrg { 1060fe567363Smrg prmsg (1, 1061fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 106273143b9aSmrg (void) umask (oldUmask); 106373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 106473143b9aSmrg } 106573143b9aSmrg 106673143b9aSmrg if (abstract) 106773143b9aSmrg sockname.sun_path[0] = '@'; 106873143b9aSmrg 106973143b9aSmrg ciptr->family = sockname.sun_family; 107073143b9aSmrg ciptr->addrlen = namelen; 107173143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 107273143b9aSmrg 107373143b9aSmrg (void) umask (oldUmask); 107473143b9aSmrg 107573143b9aSmrg return 0; 107673143b9aSmrg} 107773143b9aSmrg 107873143b9aSmrg 107973143b9aSmrgstatic int 108073143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) 108173143b9aSmrg 108273143b9aSmrg{ 108373143b9aSmrg /* 108473143b9aSmrg * See if the unix domain socket has disappeared. If it has, recreate it. 108573143b9aSmrg */ 108673143b9aSmrg 108773143b9aSmrg struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; 108873143b9aSmrg struct stat statb; 108973143b9aSmrg int status = TRANS_RESET_NOOP; 109073143b9aSmrg unsigned int mode; 109173143b9aSmrg int abstract = 0; 109273143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 109373143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 109473143b9aSmrg#endif 109573143b9aSmrg 1096fe567363Smrg prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd); 109773143b9aSmrg 109873143b9aSmrg if (!abstract && ( 109973143b9aSmrg stat (unsock->sun_path, &statb) == -1 || 110073143b9aSmrg ((statb.st_mode & S_IFMT) != 1101a773ec55Smrg#if !defined(S_IFSOCK) 110273143b9aSmrg S_IFIFO 110373143b9aSmrg#else 110473143b9aSmrg S_IFSOCK 110573143b9aSmrg#endif 110673143b9aSmrg ))) 110773143b9aSmrg { 110873143b9aSmrg int oldUmask = umask (0); 110973143b9aSmrg 111073143b9aSmrg#ifdef UNIX_DIR 111173143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 111273143b9aSmrg mode = 01777; 111373143b9aSmrg#else 111473143b9aSmrg mode = 0777; 111573143b9aSmrg#endif 111673143b9aSmrg if (trans_mkdir(UNIX_DIR, mode) == -1) { 1117fe567363Smrg prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", 1118fe567363Smrg UNIX_DIR, errno); 111973143b9aSmrg (void) umask (oldUmask); 112073143b9aSmrg return TRANS_RESET_FAILURE; 112173143b9aSmrg } 112273143b9aSmrg#endif 112373143b9aSmrg 112473143b9aSmrg close (ciptr->fd); 112573143b9aSmrg unlink (unsock->sun_path); 112673143b9aSmrg 112773143b9aSmrg if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 112873143b9aSmrg { 112973143b9aSmrg TRANS(FreeConnInfo) (ciptr); 113073143b9aSmrg (void) umask (oldUmask); 113173143b9aSmrg return TRANS_RESET_FAILURE; 113273143b9aSmrg } 113373143b9aSmrg 113473143b9aSmrg if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) 113573143b9aSmrg { 113673143b9aSmrg close (ciptr->fd); 113773143b9aSmrg TRANS(FreeConnInfo) (ciptr); 113873143b9aSmrg return TRANS_RESET_FAILURE; 113973143b9aSmrg } 114073143b9aSmrg 114173143b9aSmrg if (listen (ciptr->fd, BACKLOG) < 0) 114273143b9aSmrg { 114373143b9aSmrg close (ciptr->fd); 114473143b9aSmrg TRANS(FreeConnInfo) (ciptr); 114573143b9aSmrg (void) umask (oldUmask); 114673143b9aSmrg return TRANS_RESET_FAILURE; 114773143b9aSmrg } 114873143b9aSmrg 114973143b9aSmrg umask (oldUmask); 115073143b9aSmrg 115173143b9aSmrg status = TRANS_RESET_NEW_FD; 115273143b9aSmrg } 115373143b9aSmrg 115473143b9aSmrg return status; 115573143b9aSmrg} 115673143b9aSmrg 115773143b9aSmrg#endif /* UNIXCONN */ 115873143b9aSmrg 115973143b9aSmrg 116073143b9aSmrg#ifdef TCPCONN 116173143b9aSmrg 116273143b9aSmrgstatic XtransConnInfo 116373143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) 116473143b9aSmrg 116573143b9aSmrg{ 116673143b9aSmrg XtransConnInfo newciptr; 116773143b9aSmrg struct sockaddr_in sockname; 116873143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 116973143b9aSmrg 1170fe567363Smrg prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd); 117173143b9aSmrg 1172fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 117373143b9aSmrg { 1174fe567363Smrg prmsg (1, "SocketINETAccept: malloc failed\n"); 117573143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 117673143b9aSmrg return NULL; 117773143b9aSmrg } 117873143b9aSmrg 117973143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 118073143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 118173143b9aSmrg { 118273143b9aSmrg#ifdef WIN32 118373143b9aSmrg errno = WSAGetLastError(); 118473143b9aSmrg#endif 1185fe567363Smrg prmsg (1, "SocketINETAccept: accept() failed\n"); 1186fe567363Smrg free (newciptr); 118773143b9aSmrg *status = TRANS_ACCEPT_FAILED; 118873143b9aSmrg return NULL; 118973143b9aSmrg } 119073143b9aSmrg 119173143b9aSmrg#ifdef TCP_NODELAY 119273143b9aSmrg { 119373143b9aSmrg /* 119473143b9aSmrg * turn off TCP coalescence for INET sockets 119573143b9aSmrg */ 119673143b9aSmrg 119773143b9aSmrg int tmp = 1; 119873143b9aSmrg setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, 119973143b9aSmrg (char *) &tmp, sizeof (int)); 120073143b9aSmrg } 120173143b9aSmrg#endif 120273143b9aSmrg 120373143b9aSmrg /* 1204fe567363Smrg * Get this address again because the transport may give a more 120573143b9aSmrg * specific address now that a connection is established. 120673143b9aSmrg */ 120773143b9aSmrg 120873143b9aSmrg if (TRANS(SocketINETGetAddr) (newciptr) < 0) 120973143b9aSmrg { 1210fe567363Smrg prmsg (1, 1211fe567363Smrg "SocketINETAccept: ...SocketINETGetAddr() failed:\n"); 121273143b9aSmrg close (newciptr->fd); 1213fe567363Smrg free (newciptr); 121473143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 121573143b9aSmrg return NULL; 121673143b9aSmrg } 121773143b9aSmrg 121873143b9aSmrg if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) 121973143b9aSmrg { 1220fe567363Smrg prmsg (1, 1221fe567363Smrg "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n"); 122273143b9aSmrg close (newciptr->fd); 1223fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1224fe567363Smrg free (newciptr); 122573143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 122673143b9aSmrg return NULL; 122773143b9aSmrg } 122873143b9aSmrg 122973143b9aSmrg *status = 0; 123073143b9aSmrg 123173143b9aSmrg return newciptr; 123273143b9aSmrg} 123373143b9aSmrg 123473143b9aSmrg#endif /* TCPCONN */ 123573143b9aSmrg 123673143b9aSmrg 123773143b9aSmrg#ifdef UNIXCONN 123873143b9aSmrgstatic XtransConnInfo 123973143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) 124073143b9aSmrg 124173143b9aSmrg{ 124273143b9aSmrg XtransConnInfo newciptr; 124373143b9aSmrg struct sockaddr_un sockname; 124473143b9aSmrg SOCKLEN_T namelen = sizeof sockname; 124573143b9aSmrg 1246fe567363Smrg prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd); 124773143b9aSmrg 1248fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 124973143b9aSmrg { 1250fe567363Smrg prmsg (1, "SocketUNIXAccept: malloc() failed\n"); 125173143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 125273143b9aSmrg return NULL; 125373143b9aSmrg } 125473143b9aSmrg 125573143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 125673143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 125773143b9aSmrg { 1258fe567363Smrg prmsg (1, "SocketUNIXAccept: accept() failed\n"); 1259fe567363Smrg free (newciptr); 126073143b9aSmrg *status = TRANS_ACCEPT_FAILED; 126173143b9aSmrg return NULL; 126273143b9aSmrg } 126373143b9aSmrg 126473143b9aSmrg ciptr->addrlen = namelen; 126573143b9aSmrg /* 126673143b9aSmrg * Get the socket name and the peer name from the listener socket, 126773143b9aSmrg * since this is unix domain. 126873143b9aSmrg */ 126973143b9aSmrg 1270fe567363Smrg if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL) 127173143b9aSmrg { 1272fe567363Smrg prmsg (1, 1273fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 127473143b9aSmrg close (newciptr->fd); 1275fe567363Smrg free (newciptr); 127673143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 127773143b9aSmrg return NULL; 127873143b9aSmrg } 127973143b9aSmrg 128073143b9aSmrg /* 128173143b9aSmrg * if the socket is abstract, we already modified the address to have a 128273143b9aSmrg * @ instead of the initial NUL, so no need to do that again here. 128373143b9aSmrg */ 128473143b9aSmrg 128573143b9aSmrg newciptr->addrlen = ciptr->addrlen; 128673143b9aSmrg memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); 128773143b9aSmrg 1288fe567363Smrg if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL) 128973143b9aSmrg { 1290fe567363Smrg prmsg (1, 1291fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 129273143b9aSmrg close (newciptr->fd); 1293fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1294fe567363Smrg free (newciptr); 129573143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 129673143b9aSmrg return NULL; 129773143b9aSmrg } 1298fe567363Smrg 129973143b9aSmrg newciptr->peeraddrlen = ciptr->addrlen; 130073143b9aSmrg memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); 130173143b9aSmrg 130273143b9aSmrg newciptr->family = AF_UNIX; 130373143b9aSmrg 130473143b9aSmrg *status = 0; 130573143b9aSmrg 130673143b9aSmrg return newciptr; 130773143b9aSmrg} 130873143b9aSmrg 130973143b9aSmrg#endif /* UNIXCONN */ 131073143b9aSmrg 131173143b9aSmrg#endif /* TRANS_SERVER */ 131273143b9aSmrg 131373143b9aSmrg 131473143b9aSmrg#ifdef TRANS_CLIENT 131573143b9aSmrg 131673143b9aSmrg#ifdef TCPCONN 131773143b9aSmrg 131873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 131973143b9aSmrgstruct addrlist { 132073143b9aSmrg struct addrinfo * addr; 1321fe567363Smrg struct addrinfo * firstaddr; 132273143b9aSmrg char port[PORTBUFSIZE]; 132373143b9aSmrg char host[MAXHOSTNAMELEN]; 132473143b9aSmrg}; 132573143b9aSmrgstatic struct addrlist *addrlist = NULL; 132673143b9aSmrg#endif 132773143b9aSmrg 132873143b9aSmrg 132973143b9aSmrgstatic int 13306a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr, 13316a3641a6Ssnj const char *host, const char *port) 133273143b9aSmrg 133373143b9aSmrg{ 133473143b9aSmrg struct sockaddr * socketaddr = NULL; 133573143b9aSmrg int socketaddrlen = 0; 133673143b9aSmrg int res; 133773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 133873143b9aSmrg struct addrinfo hints; 133973143b9aSmrg char ntopbuf[INET6_ADDRSTRLEN]; 134073143b9aSmrg int resetonce = 0; 1341fe567363Smrg#else 134273143b9aSmrg struct sockaddr_in sockname; 1343fe567363Smrg struct hostent *hostp; 1344fe567363Smrg struct servent *servp; 1345fe567363Smrg unsigned long tmpaddr; 1346fe567363Smrg#endif 134773143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 134873143b9aSmrg _Xgethostbynameparams hparams; 134973143b9aSmrg _Xgetservbynameparams sparams; 135073143b9aSmrg#endif 135173143b9aSmrg#ifdef X11_t 135273143b9aSmrg char portbuf[PORTBUFSIZE]; 135373143b9aSmrg#endif 135473143b9aSmrg 135573143b9aSmrg char hostnamebuf[256]; /* tmp space */ 135673143b9aSmrg 1357fe567363Smrg prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); 135873143b9aSmrg 135973143b9aSmrg if (!host) 136073143b9aSmrg { 136173143b9aSmrg hostnamebuf[0] = '\0'; 136273143b9aSmrg (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); 136373143b9aSmrg host = hostnamebuf; 136473143b9aSmrg } 136573143b9aSmrg 136673143b9aSmrg#ifdef X11_t 136773143b9aSmrg /* 136873143b9aSmrg * X has a well known port, that is transport dependent. It is easier 136973143b9aSmrg * to handle it here, than try and come up with a transport independent 137073143b9aSmrg * representation that can be passed in and resolved the usual way. 137173143b9aSmrg * 137273143b9aSmrg * The port that is passed here is really a string containing the idisplay 137373143b9aSmrg * from ConnectDisplay(). 137473143b9aSmrg */ 137573143b9aSmrg 137673143b9aSmrg if (is_numeric (port)) 137773143b9aSmrg { 1378fe567363Smrg long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 1379fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 138073143b9aSmrg port = portbuf; 138173143b9aSmrg } 138273143b9aSmrg#endif 138373143b9aSmrg 138473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1385b53e5eeaSmrg { 138673143b9aSmrg if (addrlist != NULL) { 138773143b9aSmrg if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { 138873143b9aSmrg if (addrlist->firstaddr) 138973143b9aSmrg freeaddrinfo(addrlist->firstaddr); 139073143b9aSmrg addrlist->firstaddr = NULL; 139173143b9aSmrg } 139273143b9aSmrg } else { 139373143b9aSmrg addrlist = malloc(sizeof(struct addrlist)); 139494f982dbSmrg if (addrlist == NULL) { 139594f982dbSmrg prmsg (1, "SocketINETConnect() can't allocate memory " 139694f982dbSmrg "for addrlist: %s\n", strerror(errno)); 139794f982dbSmrg return TRANS_CONNECT_FAILED; 139894f982dbSmrg } 139973143b9aSmrg addrlist->firstaddr = NULL; 140073143b9aSmrg } 140173143b9aSmrg 140273143b9aSmrg if (addrlist->firstaddr == NULL) { 140373143b9aSmrg strncpy(addrlist->port, port, sizeof(addrlist->port)); 140473143b9aSmrg addrlist->port[sizeof(addrlist->port) - 1] = '\0'; 140573143b9aSmrg strncpy(addrlist->host, host, sizeof(addrlist->host)); 140673143b9aSmrg addrlist->host[sizeof(addrlist->host) - 1] = '\0'; 140773143b9aSmrg 140873143b9aSmrg bzero(&hints,sizeof(hints)); 140973143b9aSmrg hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; 141073143b9aSmrg 141173143b9aSmrg res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); 141273143b9aSmrg if (res != 0) { 1413fe567363Smrg prmsg (1, "SocketINETConnect() can't get address " 141473143b9aSmrg "for %s:%s: %s\n", host, port, gai_strerror(res)); 141573143b9aSmrg ESET(EINVAL); 141673143b9aSmrg return TRANS_CONNECT_FAILED; 141773143b9aSmrg } 141873143b9aSmrg for (res = 0, addrlist->addr = addrlist->firstaddr; 141973143b9aSmrg addrlist->addr ; res++) { 142073143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 142173143b9aSmrg } 1422fe567363Smrg prmsg(4,"Got New Address list with %d addresses\n", res); 142373143b9aSmrg res = 0; 142473143b9aSmrg addrlist->addr = NULL; 142573143b9aSmrg } 142673143b9aSmrg 142773143b9aSmrg while (socketaddr == NULL) { 142873143b9aSmrg if (addrlist->addr == NULL) { 1429fe567363Smrg if (resetonce) { 143073143b9aSmrg /* Already checked entire list - no usable addresses */ 1431fe567363Smrg prmsg (1, "SocketINETConnect() no usable address " 1432fe567363Smrg "for %s:%s\n", host, port); 143373143b9aSmrg return TRANS_CONNECT_FAILED; 143473143b9aSmrg } else { 143573143b9aSmrg /* Go back to beginning of list */ 143673143b9aSmrg resetonce = 1; 143773143b9aSmrg addrlist->addr = addrlist->firstaddr; 143873143b9aSmrg } 1439fe567363Smrg } 144073143b9aSmrg 144173143b9aSmrg socketaddr = addrlist->addr->ai_addr; 144273143b9aSmrg socketaddrlen = addrlist->addr->ai_addrlen; 144373143b9aSmrg 144473143b9aSmrg if (addrlist->addr->ai_family == AF_INET) { 144573143b9aSmrg struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; 144673143b9aSmrg 1447fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n", 144873143b9aSmrg inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, 1449fe567363Smrg ntopbuf,sizeof(ntopbuf))); 145073143b9aSmrg 1451fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n", 1452fe567363Smrg ntohs(sin->sin_port)); 145373143b9aSmrg 145473143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { 145573143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 145673143b9aSmrg "tcp") == 0) { 145773143b9aSmrg XtransConnInfo newciptr; 145873143b9aSmrg 145973143b9aSmrg /* 146073143b9aSmrg * Our socket is an IPv6 socket, but the address is 146173143b9aSmrg * IPv4. Close it and get an IPv4 socket. This is 146273143b9aSmrg * needed for IPv4 connections to work on platforms 146373143b9aSmrg * that don't allow IPv4 over IPv6 sockets. 146473143b9aSmrg */ 146573143b9aSmrg TRANS(SocketINETClose)(ciptr); 146673143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 146773143b9aSmrg "tcp", "tcp", host, port, ciptr->index); 146873143b9aSmrg if (newciptr) 146973143b9aSmrg ciptr->fd = newciptr->fd; 147073143b9aSmrg if (!newciptr || 147173143b9aSmrg Sockettrans2devtab[newciptr->index].family != 147273143b9aSmrg AF_INET) { 147373143b9aSmrg socketaddr = NULL; 1474fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv4 " 1475fe567363Smrg " socketfor IPv4 address\n"); 147673143b9aSmrg } 147773143b9aSmrg if (newciptr) 1478fe567363Smrg free(newciptr); 147973143b9aSmrg } else { 148073143b9aSmrg socketaddr = NULL; 1481fe567363Smrg prmsg (4,"SocketINETConnect Skipping IPv4 address\n"); 148273143b9aSmrg } 148373143b9aSmrg } 148473143b9aSmrg } else if (addrlist->addr->ai_family == AF_INET6) { 148573143b9aSmrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; 1486fe567363Smrg 1487fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n", 148873143b9aSmrg inet_ntop(addrlist->addr->ai_family, 1489fe567363Smrg &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf))); 1490fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n", 1491fe567363Smrg ntohs(sin6->sin6_port)); 149273143b9aSmrg 149373143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 149473143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 149573143b9aSmrg "tcp") == 0) { 149673143b9aSmrg XtransConnInfo newciptr; 149773143b9aSmrg 149873143b9aSmrg /* 149973143b9aSmrg * Close the IPv4 socket and try to open an IPv6 socket. 150073143b9aSmrg */ 150173143b9aSmrg TRANS(SocketINETClose)(ciptr); 150273143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 150373143b9aSmrg "tcp", "tcp", host, port, -1); 150473143b9aSmrg if (newciptr) 150573143b9aSmrg ciptr->fd = newciptr->fd; 150673143b9aSmrg if (!newciptr || 150773143b9aSmrg Sockettrans2devtab[newciptr->index].family != 150873143b9aSmrg AF_INET6) { 150973143b9aSmrg socketaddr = NULL; 1510fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv6 " 1511fe567363Smrg "socket for IPv6 address\n"); 151273143b9aSmrg } 151373143b9aSmrg if (newciptr) 1514fe567363Smrg free(newciptr); 151573143b9aSmrg } 151673143b9aSmrg else 151773143b9aSmrg { 151873143b9aSmrg socketaddr = NULL; 1519fe567363Smrg prmsg (4,"SocketINETConnect() Skipping IPv6 address\n"); 152073143b9aSmrg } 152173143b9aSmrg } 152273143b9aSmrg } else { 152373143b9aSmrg socketaddr = NULL; /* Unsupported address type */ 152473143b9aSmrg } 152573143b9aSmrg if (socketaddr == NULL) { 152673143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 152773143b9aSmrg } 1528fe567363Smrg } 1529b53e5eeaSmrg } 1530b53e5eeaSmrg#else 153173143b9aSmrg { 153273143b9aSmrg /* 153373143b9aSmrg * Build the socket name. 153473143b9aSmrg */ 153573143b9aSmrg 153673143b9aSmrg#ifdef BSD44SOCKETS 153773143b9aSmrg sockname.sin_len = sizeof (struct sockaddr_in); 153873143b9aSmrg#endif 153973143b9aSmrg sockname.sin_family = AF_INET; 154073143b9aSmrg 154173143b9aSmrg /* 154273143b9aSmrg * fill in sin_addr 154373143b9aSmrg */ 154473143b9aSmrg 154573143b9aSmrg#ifndef INADDR_NONE 154673143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff) 154773143b9aSmrg#endif 154873143b9aSmrg 154973143b9aSmrg /* check for ww.xx.yy.zz host string */ 155073143b9aSmrg 155173143b9aSmrg if (isascii (host[0]) && isdigit (host[0])) { 155273143b9aSmrg tmpaddr = inet_addr (host); /* returns network byte order */ 155373143b9aSmrg } else { 155473143b9aSmrg tmpaddr = INADDR_NONE; 155573143b9aSmrg } 155673143b9aSmrg 155781d6fa61Srin prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr); 155873143b9aSmrg 155973143b9aSmrg if (tmpaddr == INADDR_NONE) { 156073143b9aSmrg if ((hostp = _XGethostbyname(host,hparams)) == NULL) { 1561fe567363Smrg prmsg (1,"SocketINETConnect: Can't get address for %s\n", 1562fe567363Smrg host); 156373143b9aSmrg ESET(EINVAL); 156473143b9aSmrg return TRANS_CONNECT_FAILED; 156573143b9aSmrg } 156673143b9aSmrg if (hostp->h_addrtype != AF_INET) { /* is IP host? */ 1567fe567363Smrg prmsg (1,"SocketINETConnect: not INET host%s\n", host); 156873143b9aSmrg ESET(EPROTOTYPE); 156973143b9aSmrg return TRANS_CONNECT_FAILED; 157073143b9aSmrg } 1571fe567363Smrg 157273143b9aSmrg memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, 157373143b9aSmrg sizeof (sockname.sin_addr)); 157473143b9aSmrg 157573143b9aSmrg } else { 157673143b9aSmrg sockname.sin_addr.s_addr = tmpaddr; 157773143b9aSmrg } 157873143b9aSmrg 157973143b9aSmrg /* 158073143b9aSmrg * fill in sin_port 158173143b9aSmrg */ 158273143b9aSmrg 158373143b9aSmrg /* Check for number in the port string */ 158473143b9aSmrg 158573143b9aSmrg if (!is_numeric (port)) { 158673143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) { 1587fe567363Smrg prmsg (1,"SocketINETConnect: can't get service for %s\n", 1588fe567363Smrg port); 158973143b9aSmrg return TRANS_CONNECT_FAILED; 159073143b9aSmrg } 159173143b9aSmrg sockname.sin_port = htons (servp->s_port); 159273143b9aSmrg } else { 1593fe567363Smrg long tmpport = strtol (port, (char**)NULL, 10); 159473143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 159573143b9aSmrg return TRANS_CONNECT_FAILED; 159673143b9aSmrg sockname.sin_port = htons (((unsigned short) tmpport)); 159773143b9aSmrg } 159873143b9aSmrg 1599fe567363Smrg prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n", 1600fe567363Smrg ntohs(sockname.sin_port)); 160173143b9aSmrg socketaddr = (struct sockaddr *) &sockname; 160273143b9aSmrg socketaddrlen = sizeof(sockname); 160373143b9aSmrg } 1604b53e5eeaSmrg#endif 160573143b9aSmrg 160673143b9aSmrg /* 160773143b9aSmrg * Turn on socket keepalive so the client process will eventually 160873143b9aSmrg * be notified with a SIGPIPE signal if the display server fails 160973143b9aSmrg * to respond to a periodic transmission of messages 161073143b9aSmrg * on the connected socket. 161173143b9aSmrg * This is useful to avoid hung application processes when the 161273143b9aSmrg * processes are not spawned from the xdm session and 161373143b9aSmrg * the display server terminates abnormally. 161473143b9aSmrg * (Someone turned off the power switch.) 161573143b9aSmrg */ 161673143b9aSmrg 161773143b9aSmrg { 161873143b9aSmrg int tmp = 1; 161973143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE, 162073143b9aSmrg (char *) &tmp, sizeof (int)); 162173143b9aSmrg } 162273143b9aSmrg 162373143b9aSmrg /* 162473143b9aSmrg * Do the connect() 162573143b9aSmrg */ 162673143b9aSmrg 162773143b9aSmrg if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) 162873143b9aSmrg { 162973143b9aSmrg#ifdef WIN32 163073143b9aSmrg int olderrno = WSAGetLastError(); 163173143b9aSmrg#else 163273143b9aSmrg int olderrno = errno; 163373143b9aSmrg#endif 163473143b9aSmrg 163573143b9aSmrg /* 163673143b9aSmrg * If the error was ECONNREFUSED, the server may be overloaded 163773143b9aSmrg * and we should try again. 163873143b9aSmrg * 163973143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 164073143b9aSmrg * was non-blocking and we should poll using select 164173143b9aSmrg * 164273143b9aSmrg * If the error was EINTR, the connect was interrupted and we 164373143b9aSmrg * should try again. 164473143b9aSmrg * 164573143b9aSmrg * If multiple addresses are found for a host then we should 164673143b9aSmrg * try to connect again with a different address for a larger 164773143b9aSmrg * number of errors that made us quit before, since those 164873143b9aSmrg * could be caused by trying to use an IPv6 address to contact 164973143b9aSmrg * a machine with an IPv4-only server or other reasons that 1650fe567363Smrg * only affect one of a set of addresses. 165173143b9aSmrg */ 165273143b9aSmrg 165373143b9aSmrg if (olderrno == ECONNREFUSED || olderrno == EINTR 165473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1655b53e5eeaSmrg || (((addrlist->addr->ai_next != NULL) || 165673143b9aSmrg (addrlist->addr != addrlist->firstaddr)) && 165773143b9aSmrg (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT || 165873143b9aSmrg olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT 165973143b9aSmrg#if defined(EHOSTDOWN) 166073143b9aSmrg || olderrno == EHOSTDOWN 166173143b9aSmrg#endif 166273143b9aSmrg )) 166373143b9aSmrg#endif 166473143b9aSmrg ) 166573143b9aSmrg res = TRANS_TRY_CONNECT_AGAIN; 166673143b9aSmrg else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 166773143b9aSmrg res = TRANS_IN_PROGRESS; 166873143b9aSmrg else 166973143b9aSmrg { 1670fe567363Smrg prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n", 1671fe567363Smrg olderrno); 167273143b9aSmrg 1673fe567363Smrg res = TRANS_CONNECT_FAILED; 167473143b9aSmrg } 167573143b9aSmrg } else { 167673143b9aSmrg res = 0; 1677fe567363Smrg 167873143b9aSmrg 167973143b9aSmrg /* 168073143b9aSmrg * Sync up the address fields of ciptr. 168173143b9aSmrg */ 1682fe567363Smrg 168373143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 168473143b9aSmrg { 1685fe567363Smrg prmsg (1, 1686fe567363Smrg "SocketINETConnect: ...SocketINETGetAddr() failed:\n"); 168773143b9aSmrg res = TRANS_CONNECT_FAILED; 168873143b9aSmrg } 168973143b9aSmrg 169073143b9aSmrg else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) 169173143b9aSmrg { 1692fe567363Smrg prmsg (1, 1693fe567363Smrg "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n"); 169473143b9aSmrg res = TRANS_CONNECT_FAILED; 169573143b9aSmrg } 169673143b9aSmrg } 169773143b9aSmrg 169873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1699b53e5eeaSmrg if (res != 0) { 170073143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 170173143b9aSmrg } 170273143b9aSmrg#endif 170373143b9aSmrg 170473143b9aSmrg return res; 170573143b9aSmrg} 170673143b9aSmrg 170773143b9aSmrg#endif /* TCPCONN */ 170873143b9aSmrg 170973143b9aSmrg 171073143b9aSmrg 171173143b9aSmrg#ifdef UNIXCONN 171273143b9aSmrg 171373143b9aSmrg/* 171473143b9aSmrg * Make sure 'host' is really local. 171573143b9aSmrg */ 171673143b9aSmrg 171773143b9aSmrgstatic int 17186a3641a6SsnjUnixHostReallyLocal (const char *host) 171973143b9aSmrg 172073143b9aSmrg{ 172173143b9aSmrg char hostnamebuf[256]; 172273143b9aSmrg 172373143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 172473143b9aSmrg 172573143b9aSmrg if (strcmp (hostnamebuf, host) == 0) 172673143b9aSmrg { 172773143b9aSmrg return (1); 1728b53e5eeaSmrg } else { 172973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 173073143b9aSmrg struct addrinfo *localhostaddr; 173173143b9aSmrg struct addrinfo *otherhostaddr; 173273143b9aSmrg struct addrinfo *i, *j; 173373143b9aSmrg int equiv = 0; 173473143b9aSmrg 173573143b9aSmrg if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0) 173673143b9aSmrg return 0; 173773143b9aSmrg if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) { 173873143b9aSmrg freeaddrinfo(localhostaddr); 173973143b9aSmrg return 0; 174073143b9aSmrg } 174173143b9aSmrg 174273143b9aSmrg for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) { 174373143b9aSmrg for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) { 174473143b9aSmrg if (i->ai_family == j->ai_family) { 174573143b9aSmrg if (i->ai_family == AF_INET) { 1746fe567363Smrg struct sockaddr_in *sinA 174773143b9aSmrg = (struct sockaddr_in *) i->ai_addr; 174873143b9aSmrg struct sockaddr_in *sinB 174973143b9aSmrg = (struct sockaddr_in *) j->ai_addr; 175073143b9aSmrg struct in_addr *A = &sinA->sin_addr; 175173143b9aSmrg struct in_addr *B = &sinB->sin_addr; 175273143b9aSmrg 175373143b9aSmrg if (memcmp(A,B,sizeof(struct in_addr)) == 0) { 175473143b9aSmrg equiv = 1; 175573143b9aSmrg } 175673143b9aSmrg } else if (i->ai_family == AF_INET6) { 1757fe567363Smrg struct sockaddr_in6 *sinA 175873143b9aSmrg = (struct sockaddr_in6 *) i->ai_addr; 1759fe567363Smrg struct sockaddr_in6 *sinB 176073143b9aSmrg = (struct sockaddr_in6 *) j->ai_addr; 176173143b9aSmrg struct in6_addr *A = &sinA->sin6_addr; 176273143b9aSmrg struct in6_addr *B = &sinB->sin6_addr; 176373143b9aSmrg 176473143b9aSmrg if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { 176573143b9aSmrg equiv = 1; 176673143b9aSmrg } 176773143b9aSmrg } 176873143b9aSmrg } 176973143b9aSmrg } 177073143b9aSmrg } 1771fe567363Smrg 177273143b9aSmrg freeaddrinfo(localhostaddr); 177373143b9aSmrg freeaddrinfo(otherhostaddr); 177473143b9aSmrg return equiv; 1775b53e5eeaSmrg#else 177673143b9aSmrg /* 177773143b9aSmrg * A host may have more than one network address. If any of the 177873143b9aSmrg * network addresses of 'host' (specified to the connect call) 177973143b9aSmrg * match any of the network addresses of 'hostname' (determined 178073143b9aSmrg * by TRANS(GetHostname)), then the two hostnames are equivalent, 178173143b9aSmrg * and we know that 'host' is really a local host. 178273143b9aSmrg */ 178373143b9aSmrg char specified_local_addr_list[10][4]; 178473143b9aSmrg int scount, equiv, i, j; 178573143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 178673143b9aSmrg _Xgethostbynameparams hparams; 178773143b9aSmrg#endif 178873143b9aSmrg struct hostent *hostp; 178973143b9aSmrg 179073143b9aSmrg if ((hostp = _XGethostbyname (host,hparams)) == NULL) 179173143b9aSmrg return (0); 179273143b9aSmrg 179373143b9aSmrg scount = 0; 179473143b9aSmrg while (hostp->h_addr_list[scount] && scount <= 8) 179573143b9aSmrg { 179673143b9aSmrg /* 179773143b9aSmrg * The 2nd call to gethostname() overrides the data 179873143b9aSmrg * from the 1st call, so we must save the address list. 179973143b9aSmrg */ 180073143b9aSmrg 1801fe567363Smrg specified_local_addr_list[scount][0] = 180273143b9aSmrg hostp->h_addr_list[scount][0]; 1803fe567363Smrg specified_local_addr_list[scount][1] = 180473143b9aSmrg hostp->h_addr_list[scount][1]; 1805fe567363Smrg specified_local_addr_list[scount][2] = 180673143b9aSmrg hostp->h_addr_list[scount][2]; 1807fe567363Smrg specified_local_addr_list[scount][3] = 180873143b9aSmrg hostp->h_addr_list[scount][3]; 180973143b9aSmrg scount++; 181073143b9aSmrg } 181173143b9aSmrg if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) 181273143b9aSmrg return (0); 181373143b9aSmrg 181473143b9aSmrg equiv = 0; 181573143b9aSmrg i = 0; 181673143b9aSmrg 181773143b9aSmrg while (i < scount && !equiv) 181873143b9aSmrg { 181973143b9aSmrg j = 0; 182073143b9aSmrg 182173143b9aSmrg while (hostp->h_addr_list[j]) 182273143b9aSmrg { 1823fe567363Smrg if ((specified_local_addr_list[i][0] == 182473143b9aSmrg hostp->h_addr_list[j][0]) && 1825fe567363Smrg (specified_local_addr_list[i][1] == 182673143b9aSmrg hostp->h_addr_list[j][1]) && 1827fe567363Smrg (specified_local_addr_list[i][2] == 182873143b9aSmrg hostp->h_addr_list[j][2]) && 1829fe567363Smrg (specified_local_addr_list[i][3] == 183073143b9aSmrg hostp->h_addr_list[j][3])) 183173143b9aSmrg { 183273143b9aSmrg /* They're equal, so we're done */ 1833fe567363Smrg 183473143b9aSmrg equiv = 1; 183573143b9aSmrg break; 183673143b9aSmrg } 183773143b9aSmrg 183873143b9aSmrg j++; 183973143b9aSmrg } 184073143b9aSmrg 184173143b9aSmrg i++; 184273143b9aSmrg } 184373143b9aSmrg return (equiv); 1844b53e5eeaSmrg#endif 184573143b9aSmrg } 184673143b9aSmrg} 184773143b9aSmrg 184873143b9aSmrgstatic int 18496a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, 18506a3641a6Ssnj const char *host, const char *port) 185173143b9aSmrg 185273143b9aSmrg{ 185373143b9aSmrg struct sockaddr_un sockname; 185473143b9aSmrg SOCKLEN_T namelen; 185573143b9aSmrg 1856fe567363Smrg prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); 1857fe567363Smrg 185873143b9aSmrg /* 185973143b9aSmrg * Make sure 'host' is really local. If not, we return failure. 186073143b9aSmrg * The reason we make this check is because a process may advertise 186173143b9aSmrg * a "local" network ID for which it can accept connections, but if 186273143b9aSmrg * a process on a remote machine tries to connect to this network ID, 186373143b9aSmrg * we know for sure it will fail. 186473143b9aSmrg */ 186573143b9aSmrg 186673143b9aSmrg if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) 186773143b9aSmrg { 1868fe567363Smrg prmsg (1, 186973143b9aSmrg "SocketUNIXConnect: Cannot connect to non-local host %s\n", 1870fe567363Smrg host); 187173143b9aSmrg return TRANS_CONNECT_FAILED; 187273143b9aSmrg } 187373143b9aSmrg 187473143b9aSmrg 187573143b9aSmrg /* 187673143b9aSmrg * Check the port. 187773143b9aSmrg */ 187873143b9aSmrg 187973143b9aSmrg if (!port || !*port) 188073143b9aSmrg { 1881fe567363Smrg prmsg (1,"SocketUNIXConnect: Missing port specification\n"); 188273143b9aSmrg return TRANS_CONNECT_FAILED; 188373143b9aSmrg } 188473143b9aSmrg 188573143b9aSmrg /* 188673143b9aSmrg * Build the socket name. 188773143b9aSmrg */ 1888fe567363Smrg 188973143b9aSmrg sockname.sun_family = AF_UNIX; 189073143b9aSmrg 1891a773ec55Smrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, 0) != 0) { 1892fe567363Smrg prmsg (1, "SocketUNIXConnect: path too long\n"); 189373143b9aSmrg return TRANS_CONNECT_FAILED; 189473143b9aSmrg } 189573143b9aSmrg 1896a773ec55Smrg#if defined(BSD44SOCKETS) 189773143b9aSmrg sockname.sun_len = strlen (sockname.sun_path); 189873143b9aSmrg#endif 189973143b9aSmrg 190073143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 190173143b9aSmrg namelen = SUN_LEN (&sockname); 190273143b9aSmrg#else 190373143b9aSmrg namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 190473143b9aSmrg#endif 190573143b9aSmrg 190673143b9aSmrg 190773143b9aSmrg /* 190873143b9aSmrg * Do the connect() 190973143b9aSmrg */ 191073143b9aSmrg 191173143b9aSmrg if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) 191273143b9aSmrg { 191373143b9aSmrg int olderrno = errno; 191473143b9aSmrg int connected = 0; 1915fe567363Smrg 191673143b9aSmrg if (!connected) 191773143b9aSmrg { 191873143b9aSmrg errno = olderrno; 1919fe567363Smrg 192073143b9aSmrg /* 192173143b9aSmrg * If the error was ENOENT, the server may be starting up; we used 192273143b9aSmrg * to suggest to try again in this case with 192373143b9aSmrg * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for 192473143b9aSmrg * processes still referencing stale sockets in their environment. 192573143b9aSmrg * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it 192673143b9aSmrg * is suggested that higher level stacks handle retries on their 192773143b9aSmrg * level when they face a slow starting server. 192873143b9aSmrg * 192973143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 193073143b9aSmrg * was non-blocking and we should poll using select 193173143b9aSmrg * 193273143b9aSmrg * If the error was EINTR, the connect was interrupted and we 193373143b9aSmrg * should try again. 193473143b9aSmrg */ 193573143b9aSmrg 193673143b9aSmrg if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 193773143b9aSmrg return TRANS_IN_PROGRESS; 193873143b9aSmrg else if (olderrno == EINTR) 193973143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 1940a773ec55Smrg else { 1941fe567363Smrg prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n", 1942fe567363Smrg EGET()); 194373143b9aSmrg 194473143b9aSmrg return TRANS_CONNECT_FAILED; 194573143b9aSmrg } 194673143b9aSmrg } 194773143b9aSmrg } 194873143b9aSmrg 194973143b9aSmrg /* 195073143b9aSmrg * Get the socket name and the peer name from the connect socket, 195173143b9aSmrg * since this is unix domain. 195273143b9aSmrg */ 195373143b9aSmrg 1954fe567363Smrg if ((ciptr->addr = malloc(namelen)) == NULL || 1955fe567363Smrg (ciptr->peeraddr = malloc(namelen)) == NULL) 195673143b9aSmrg { 1957fe567363Smrg prmsg (1, 1958fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 195973143b9aSmrg return TRANS_CONNECT_FAILED; 196073143b9aSmrg } 196173143b9aSmrg 196273143b9aSmrg ciptr->family = AF_UNIX; 196373143b9aSmrg ciptr->addrlen = namelen; 196473143b9aSmrg ciptr->peeraddrlen = namelen; 196573143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 196673143b9aSmrg memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); 196773143b9aSmrg 196873143b9aSmrg return 0; 196973143b9aSmrg} 197073143b9aSmrg 197173143b9aSmrg#endif /* UNIXCONN */ 197273143b9aSmrg 197373143b9aSmrg#endif /* TRANS_CLIENT */ 197473143b9aSmrg 197573143b9aSmrg 197673143b9aSmrgstatic int 197773143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 197873143b9aSmrg 197973143b9aSmrg{ 1980fe567363Smrg prmsg (2,"SocketBytesReadable(%p,%d,%p)\n", 198173143b9aSmrg ciptr, ciptr->fd, pend); 198273143b9aSmrg#ifdef WIN32 198373143b9aSmrg { 198473143b9aSmrg int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); 198573143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 198673143b9aSmrg return ret; 198773143b9aSmrg } 198873143b9aSmrg#else 198973143b9aSmrg return ioctl (ciptr->fd, FIONREAD, (char *) pend); 199073143b9aSmrg#endif /* WIN32 */ 199173143b9aSmrg} 199273143b9aSmrg 199375ebec6dSmrg#if XTRANS_SEND_FDS 199475ebec6dSmrg 199575ebec6dSmrgstatic void 199675ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close) 199775ebec6dSmrg{ 199875ebec6dSmrg struct _XtransConnFd *cf, *new; 199975ebec6dSmrg 200075ebec6dSmrg new = malloc (sizeof (struct _XtransConnFd)); 200175ebec6dSmrg if (!new) { 200275ebec6dSmrg /* XXX mark connection as broken */ 200375ebec6dSmrg close(fd); 200475ebec6dSmrg return; 200575ebec6dSmrg } 200675ebec6dSmrg new->next = 0; 200775ebec6dSmrg new->fd = fd; 200875ebec6dSmrg new->do_close = do_close; 200975ebec6dSmrg /* search to end of list */ 201075ebec6dSmrg for (; (cf = *prev); prev = &(cf->next)); 201175ebec6dSmrg *prev = new; 201275ebec6dSmrg} 201373143b9aSmrg 201473143b9aSmrgstatic int 201575ebec6dSmrgremoveFd(struct _XtransConnFd **prev) 201675ebec6dSmrg{ 201775ebec6dSmrg struct _XtransConnFd *cf; 201875ebec6dSmrg int fd; 201975ebec6dSmrg 202075ebec6dSmrg if ((cf = *prev)) { 202175ebec6dSmrg *prev = cf->next; 202275ebec6dSmrg fd = cf->fd; 202375ebec6dSmrg free(cf); 202475ebec6dSmrg } else 202575ebec6dSmrg fd = -1; 202675ebec6dSmrg return fd; 202775ebec6dSmrg} 202873143b9aSmrg 202975ebec6dSmrgstatic void 203075ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) 203173143b9aSmrg{ 203275ebec6dSmrg struct _XtransConnFd *cf, *next; 203373143b9aSmrg 203475ebec6dSmrg for (cf = *prev; cf != upto; cf = next) { 203575ebec6dSmrg next = cf->next; 203675ebec6dSmrg if (do_close || cf->do_close) 203775ebec6dSmrg close(cf->fd); 203875ebec6dSmrg free(cf); 203973143b9aSmrg } 204075ebec6dSmrg *prev = upto; 204173143b9aSmrg} 204273143b9aSmrg 204375ebec6dSmrgstatic void 204475ebec6dSmrgcleanupFds(XtransConnInfo ciptr) 204575ebec6dSmrg{ 204675ebec6dSmrg /* Clean up the send list but don't close the fds */ 204775ebec6dSmrg discardFd(&ciptr->send_fds, NULL, 0); 204875ebec6dSmrg /* Clean up the recv list and *do* close the fds */ 204975ebec6dSmrg discardFd(&ciptr->recv_fds, NULL, 1); 205075ebec6dSmrg} 205173143b9aSmrg 205273143b9aSmrgstatic int 205375ebec6dSmrgnFd(struct _XtransConnFd **prev) 205475ebec6dSmrg{ 205575ebec6dSmrg struct _XtransConnFd *cf; 205675ebec6dSmrg int n = 0; 205775ebec6dSmrg 205875ebec6dSmrg for (cf = *prev; cf; cf = cf->next) 205975ebec6dSmrg n++; 206075ebec6dSmrg return n; 206175ebec6dSmrg} 206273143b9aSmrg 206375ebec6dSmrgstatic int 206475ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr) 206573143b9aSmrg{ 206675ebec6dSmrg prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); 206775ebec6dSmrg return removeFd(&ciptr->recv_fds); 206875ebec6dSmrg} 206975ebec6dSmrg 207075ebec6dSmrgstatic int 207175ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) 207275ebec6dSmrg{ 207375ebec6dSmrg appendFd(&ciptr->send_fds, fd, do_close); 207475ebec6dSmrg return 0; 207575ebec6dSmrg} 207675ebec6dSmrg 207775ebec6dSmrgstatic int 207875ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) 207975ebec6dSmrg{ 208075ebec6dSmrg errno = EINVAL; 208175ebec6dSmrg return -1; 208275ebec6dSmrg} 208375ebec6dSmrg 208475ebec6dSmrgstatic int 208575ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) 208675ebec6dSmrg{ 208775ebec6dSmrg errno = EINVAL; 208875ebec6dSmrg return -1; 208975ebec6dSmrg} 209075ebec6dSmrg 209175ebec6dSmrg#define MAX_FDS 128 209275ebec6dSmrg 209375ebec6dSmrgunion fd_pass { 209475ebec6dSmrg struct cmsghdr cmsghdr; 209575ebec6dSmrg char buf[CMSG_SPACE(MAX_FDS * sizeof(int))]; 209675ebec6dSmrg}; 209775ebec6dSmrg 209875ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 209975ebec6dSmrg 210075ebec6dSmrgstatic int 210175ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) 210275ebec6dSmrg 210375ebec6dSmrg{ 210475ebec6dSmrg prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); 210573143b9aSmrg 2106fe567363Smrg#if defined(WIN32) 210773143b9aSmrg { 210875ebec6dSmrg int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); 210973143b9aSmrg#ifdef WIN32 211073143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 211173143b9aSmrg#endif 211273143b9aSmrg return ret; 211373143b9aSmrg } 211473143b9aSmrg#else 211575ebec6dSmrg#if XTRANS_SEND_FDS 211675ebec6dSmrg { 211775ebec6dSmrg struct iovec iov = { 211875ebec6dSmrg .iov_base = buf, 211975ebec6dSmrg .iov_len = size 212075ebec6dSmrg }; 212175ebec6dSmrg union fd_pass cmsgbuf; 212275ebec6dSmrg struct msghdr msg = { 212375ebec6dSmrg .msg_name = NULL, 212475ebec6dSmrg .msg_namelen = 0, 212575ebec6dSmrg .msg_iov = &iov, 212675ebec6dSmrg .msg_iovlen = 1, 212775ebec6dSmrg .msg_control = cmsgbuf.buf, 212875ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 212975ebec6dSmrg }; 213075ebec6dSmrg 213175ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 213275ebec6dSmrg if (size >= 0) { 213375ebec6dSmrg struct cmsghdr *hdr; 213475ebec6dSmrg 213575ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 213675ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 213775ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 213875ebec6dSmrg int i; 213975ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 214075ebec6dSmrg 214175ebec6dSmrg for (i = 0; i < nfd; i++) 214275ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 214375ebec6dSmrg } 214475ebec6dSmrg } 214575ebec6dSmrg } 214675ebec6dSmrg return size; 214775ebec6dSmrg } 214875ebec6dSmrg#else 214975ebec6dSmrg return read(ciptr->fd, buf, size); 215075ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 215173143b9aSmrg#endif /* WIN32 */ 215273143b9aSmrg} 215373143b9aSmrg 215473143b9aSmrgstatic int 215573143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) 215673143b9aSmrg 215773143b9aSmrg{ 2158fe567363Smrg prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); 215973143b9aSmrg 216075ebec6dSmrg#if XTRANS_SEND_FDS 216175ebec6dSmrg { 216275ebec6dSmrg union fd_pass cmsgbuf; 216375ebec6dSmrg struct msghdr msg = { 216475ebec6dSmrg .msg_name = NULL, 216575ebec6dSmrg .msg_namelen = 0, 216675ebec6dSmrg .msg_iov = buf, 216775ebec6dSmrg .msg_iovlen = size, 216875ebec6dSmrg .msg_control = cmsgbuf.buf, 216975ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 217075ebec6dSmrg }; 217175ebec6dSmrg 217275ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 217375ebec6dSmrg if (size >= 0) { 217475ebec6dSmrg struct cmsghdr *hdr; 217575ebec6dSmrg 217675ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 217775ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 217875ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 217975ebec6dSmrg int i; 218075ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 218175ebec6dSmrg 218275ebec6dSmrg for (i = 0; i < nfd; i++) 218375ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 218475ebec6dSmrg } 218575ebec6dSmrg } 218675ebec6dSmrg } 218775ebec6dSmrg return size; 218875ebec6dSmrg } 218975ebec6dSmrg#else 219073143b9aSmrg return READV (ciptr, buf, size); 219175ebec6dSmrg#endif 219273143b9aSmrg} 219373143b9aSmrg 219473143b9aSmrg 219573143b9aSmrgstatic int 219673143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) 219773143b9aSmrg 219873143b9aSmrg{ 2199fe567363Smrg prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); 220073143b9aSmrg 220175ebec6dSmrg#if XTRANS_SEND_FDS 220275ebec6dSmrg if (ciptr->send_fds) 220375ebec6dSmrg { 220475ebec6dSmrg union fd_pass cmsgbuf; 220575ebec6dSmrg int nfd = nFd(&ciptr->send_fds); 220675ebec6dSmrg struct _XtransConnFd *cf = ciptr->send_fds; 220775ebec6dSmrg struct msghdr msg = { 220875ebec6dSmrg .msg_name = NULL, 220975ebec6dSmrg .msg_namelen = 0, 221075ebec6dSmrg .msg_iov = buf, 221175ebec6dSmrg .msg_iovlen = size, 221275ebec6dSmrg .msg_control = cmsgbuf.buf, 221375ebec6dSmrg .msg_controllen = CMSG_LEN(nfd * sizeof(int)) 221475ebec6dSmrg }; 221575ebec6dSmrg struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 221675ebec6dSmrg int i; 221775ebec6dSmrg int *fds; 221875ebec6dSmrg 221975ebec6dSmrg hdr->cmsg_len = msg.msg_controllen; 222075ebec6dSmrg hdr->cmsg_level = SOL_SOCKET; 222175ebec6dSmrg hdr->cmsg_type = SCM_RIGHTS; 222275ebec6dSmrg 222375ebec6dSmrg fds = (int *) CMSG_DATA(hdr); 222475ebec6dSmrg /* Set up fds */ 222575ebec6dSmrg for (i = 0; i < nfd; i++) { 222675ebec6dSmrg fds[i] = cf->fd; 222775ebec6dSmrg cf = cf->next; 222875ebec6dSmrg } 222975ebec6dSmrg 223075ebec6dSmrg i = sendmsg(ciptr->fd, &msg, 0); 223175ebec6dSmrg if (i > 0) 223275ebec6dSmrg discardFd(&ciptr->send_fds, cf, 0); 223375ebec6dSmrg return i; 223475ebec6dSmrg } 223575ebec6dSmrg#endif 223673143b9aSmrg return WRITEV (ciptr, buf, size); 223773143b9aSmrg} 223873143b9aSmrg 223973143b9aSmrg 224075ebec6dSmrgstatic int 224175ebec6dSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) 224275ebec6dSmrg 224375ebec6dSmrg{ 224475ebec6dSmrg prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); 224575ebec6dSmrg 224675ebec6dSmrg#if defined(WIN32) 224775ebec6dSmrg { 224875ebec6dSmrg int ret = send ((SOCKET)ciptr->fd, buf, size, 0); 224975ebec6dSmrg#ifdef WIN32 225075ebec6dSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 225175ebec6dSmrg#endif 225275ebec6dSmrg return ret; 225375ebec6dSmrg } 225475ebec6dSmrg#else 225575ebec6dSmrg#if XTRANS_SEND_FDS 225675ebec6dSmrg if (ciptr->send_fds) 225775ebec6dSmrg { 225875ebec6dSmrg struct iovec iov; 225975ebec6dSmrg 226075ebec6dSmrg iov.iov_base = buf; 226175ebec6dSmrg iov.iov_len = size; 226275ebec6dSmrg return TRANS(SocketWritev)(ciptr, &iov, 1); 226375ebec6dSmrg } 226475ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 226575ebec6dSmrg return write (ciptr->fd, buf, size); 226675ebec6dSmrg#endif /* WIN32 */ 226775ebec6dSmrg} 226875ebec6dSmrg 226973143b9aSmrgstatic int 227073143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr) 227173143b9aSmrg 227273143b9aSmrg{ 2273fe567363Smrg prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd); 227473143b9aSmrg 227573143b9aSmrg#ifdef WIN32 2276fe567363Smrg { 227773143b9aSmrg int ret = shutdown (ciptr->fd, 2); 227873143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 227973143b9aSmrg return ret; 228073143b9aSmrg } 228173143b9aSmrg#else 228273143b9aSmrg return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ 228373143b9aSmrg#endif 228473143b9aSmrg} 228573143b9aSmrg 228673143b9aSmrg 228773143b9aSmrg#ifdef TCPCONN 228873143b9aSmrgstatic int 228973143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr) 229073143b9aSmrg 229173143b9aSmrg{ 2292fe567363Smrg prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd); 229373143b9aSmrg 229473143b9aSmrg#ifdef WIN32 229573143b9aSmrg { 229673143b9aSmrg int ret = close (ciptr->fd); 229773143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 229873143b9aSmrg return ret; 229973143b9aSmrg } 230073143b9aSmrg#else 230173143b9aSmrg return close (ciptr->fd); 230273143b9aSmrg#endif 230373143b9aSmrg} 230473143b9aSmrg 230573143b9aSmrg#endif /* TCPCONN */ 230673143b9aSmrg 230773143b9aSmrg 230873143b9aSmrg#ifdef UNIXCONN 230973143b9aSmrgstatic int 231073143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr) 231173143b9aSmrg{ 231273143b9aSmrg /* 231373143b9aSmrg * If this is the server side, then once the socket is closed, 231473143b9aSmrg * it must be unlinked to completely close it 231573143b9aSmrg */ 231673143b9aSmrg 231773143b9aSmrg struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; 231873143b9aSmrg int ret; 231973143b9aSmrg 2320fe567363Smrg prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd); 232173143b9aSmrg 232275ebec6dSmrg#if XTRANS_SEND_FDS 232375ebec6dSmrg cleanupFds(ciptr); 232475ebec6dSmrg#endif 232573143b9aSmrg ret = close(ciptr->fd); 232673143b9aSmrg 232773143b9aSmrg if (ciptr->flags 232873143b9aSmrg && sockname 232973143b9aSmrg && sockname->sun_family == AF_UNIX 233073143b9aSmrg && sockname->sun_path[0]) 233173143b9aSmrg { 233273143b9aSmrg if (!(ciptr->flags & TRANS_NOUNLINK 233373143b9aSmrg || ciptr->transptr->flags & TRANS_ABSTRACT)) 233473143b9aSmrg unlink (sockname->sun_path); 233573143b9aSmrg } 233673143b9aSmrg 233773143b9aSmrg return ret; 233873143b9aSmrg} 233973143b9aSmrg 234073143b9aSmrgstatic int 234173143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) 234273143b9aSmrg 234373143b9aSmrg{ 234473143b9aSmrg /* 234573143b9aSmrg * Don't unlink path. 234673143b9aSmrg */ 234773143b9aSmrg 234873143b9aSmrg int ret; 234973143b9aSmrg 2350fe567363Smrg prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", 2351fe567363Smrg ciptr, ciptr->fd); 235273143b9aSmrg 235375ebec6dSmrg#if XTRANS_SEND_FDS 235475ebec6dSmrg cleanupFds(ciptr); 235575ebec6dSmrg#endif 235673143b9aSmrg ret = close(ciptr->fd); 235773143b9aSmrg 235873143b9aSmrg return ret; 235973143b9aSmrg} 236073143b9aSmrg 236173143b9aSmrg#endif /* UNIXCONN */ 236273143b9aSmrg 236373143b9aSmrg 236473143b9aSmrg#ifdef TCPCONN 236573143b9aSmrg# ifdef TRANS_SERVER 2366fe567363Smrgstatic const char* tcp_nolisten[] = { 236773143b9aSmrg "inet", 236873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 236973143b9aSmrg "inet6", 237073143b9aSmrg#endif 237173143b9aSmrg NULL 237273143b9aSmrg}; 237373143b9aSmrg# endif 237473143b9aSmrg 237573143b9aSmrgXtransport TRANS(SocketTCPFuncs) = { 237673143b9aSmrg /* Socket Interface */ 237773143b9aSmrg "tcp", 237873143b9aSmrg TRANS_ALIAS, 237973143b9aSmrg#ifdef TRANS_CLIENT 238073143b9aSmrg TRANS(SocketOpenCOTSClient), 238173143b9aSmrg#endif /* TRANS_CLIENT */ 238273143b9aSmrg#ifdef TRANS_SERVER 238373143b9aSmrg tcp_nolisten, 238473143b9aSmrg TRANS(SocketOpenCOTSServer), 238573143b9aSmrg#endif /* TRANS_SERVER */ 238673143b9aSmrg#ifdef TRANS_REOPEN 238773143b9aSmrg TRANS(SocketReopenCOTSServer), 238873143b9aSmrg#endif 238973143b9aSmrg TRANS(SocketSetOption), 239073143b9aSmrg#ifdef TRANS_SERVER 239173143b9aSmrg TRANS(SocketINETCreateListener), 239273143b9aSmrg NULL, /* ResetListener */ 239373143b9aSmrg TRANS(SocketINETAccept), 239473143b9aSmrg#endif /* TRANS_SERVER */ 239573143b9aSmrg#ifdef TRANS_CLIENT 239673143b9aSmrg TRANS(SocketINETConnect), 239773143b9aSmrg#endif /* TRANS_CLIENT */ 239873143b9aSmrg TRANS(SocketBytesReadable), 239973143b9aSmrg TRANS(SocketRead), 240073143b9aSmrg TRANS(SocketWrite), 240173143b9aSmrg TRANS(SocketReadv), 240273143b9aSmrg TRANS(SocketWritev), 240375ebec6dSmrg#if XTRANS_SEND_FDS 240475ebec6dSmrg TRANS(SocketSendFdInvalid), 240575ebec6dSmrg TRANS(SocketRecvFdInvalid), 240675ebec6dSmrg#endif 240773143b9aSmrg TRANS(SocketDisconnect), 240873143b9aSmrg TRANS(SocketINETClose), 240973143b9aSmrg TRANS(SocketINETClose), 241073143b9aSmrg }; 241173143b9aSmrg 241273143b9aSmrgXtransport TRANS(SocketINETFuncs) = { 241373143b9aSmrg /* Socket Interface */ 241473143b9aSmrg "inet", 241573143b9aSmrg 0, 241673143b9aSmrg#ifdef TRANS_CLIENT 241773143b9aSmrg TRANS(SocketOpenCOTSClient), 241873143b9aSmrg#endif /* TRANS_CLIENT */ 241973143b9aSmrg#ifdef TRANS_SERVER 242073143b9aSmrg NULL, 242173143b9aSmrg TRANS(SocketOpenCOTSServer), 242273143b9aSmrg#endif /* TRANS_SERVER */ 242373143b9aSmrg#ifdef TRANS_REOPEN 242473143b9aSmrg TRANS(SocketReopenCOTSServer), 242573143b9aSmrg#endif 242673143b9aSmrg TRANS(SocketSetOption), 242773143b9aSmrg#ifdef TRANS_SERVER 242873143b9aSmrg TRANS(SocketINETCreateListener), 242973143b9aSmrg NULL, /* ResetListener */ 243073143b9aSmrg TRANS(SocketINETAccept), 243173143b9aSmrg#endif /* TRANS_SERVER */ 243273143b9aSmrg#ifdef TRANS_CLIENT 243373143b9aSmrg TRANS(SocketINETConnect), 243473143b9aSmrg#endif /* TRANS_CLIENT */ 243573143b9aSmrg TRANS(SocketBytesReadable), 243673143b9aSmrg TRANS(SocketRead), 243773143b9aSmrg TRANS(SocketWrite), 243873143b9aSmrg TRANS(SocketReadv), 243973143b9aSmrg TRANS(SocketWritev), 244075ebec6dSmrg#if XTRANS_SEND_FDS 244175ebec6dSmrg TRANS(SocketSendFdInvalid), 244275ebec6dSmrg TRANS(SocketRecvFdInvalid), 244375ebec6dSmrg#endif 244473143b9aSmrg TRANS(SocketDisconnect), 244573143b9aSmrg TRANS(SocketINETClose), 244673143b9aSmrg TRANS(SocketINETClose), 244773143b9aSmrg }; 244873143b9aSmrg 244973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 245073143b9aSmrgXtransport TRANS(SocketINET6Funcs) = { 245173143b9aSmrg /* Socket Interface */ 245273143b9aSmrg "inet6", 245373143b9aSmrg 0, 245473143b9aSmrg#ifdef TRANS_CLIENT 245573143b9aSmrg TRANS(SocketOpenCOTSClient), 245673143b9aSmrg#endif /* TRANS_CLIENT */ 245773143b9aSmrg#ifdef TRANS_SERVER 245873143b9aSmrg NULL, 245973143b9aSmrg TRANS(SocketOpenCOTSServer), 246073143b9aSmrg#endif /* TRANS_SERVER */ 246173143b9aSmrg#ifdef TRANS_REOPEN 246273143b9aSmrg TRANS(SocketReopenCOTSServer), 246373143b9aSmrg#endif 246473143b9aSmrg TRANS(SocketSetOption), 246573143b9aSmrg#ifdef TRANS_SERVER 246673143b9aSmrg TRANS(SocketINETCreateListener), 246773143b9aSmrg NULL, /* ResetListener */ 246873143b9aSmrg TRANS(SocketINETAccept), 246973143b9aSmrg#endif /* TRANS_SERVER */ 247073143b9aSmrg#ifdef TRANS_CLIENT 247173143b9aSmrg TRANS(SocketINETConnect), 247273143b9aSmrg#endif /* TRANS_CLIENT */ 247373143b9aSmrg TRANS(SocketBytesReadable), 247473143b9aSmrg TRANS(SocketRead), 247573143b9aSmrg TRANS(SocketWrite), 247673143b9aSmrg TRANS(SocketReadv), 247773143b9aSmrg TRANS(SocketWritev), 247875ebec6dSmrg#if XTRANS_SEND_FDS 247975ebec6dSmrg TRANS(SocketSendFdInvalid), 248075ebec6dSmrg TRANS(SocketRecvFdInvalid), 248175ebec6dSmrg#endif 248273143b9aSmrg TRANS(SocketDisconnect), 248373143b9aSmrg TRANS(SocketINETClose), 248473143b9aSmrg TRANS(SocketINETClose), 248573143b9aSmrg }; 248673143b9aSmrg#endif /* IPv6 */ 248773143b9aSmrg#endif /* TCPCONN */ 248873143b9aSmrg 248973143b9aSmrg#ifdef UNIXCONN 249073143b9aSmrg#if !defined(LOCALCONN) 249173143b9aSmrgXtransport TRANS(SocketLocalFuncs) = { 249273143b9aSmrg /* Socket Interface */ 249373143b9aSmrg "local", 249473143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 249573143b9aSmrg TRANS_ABSTRACT, 249673143b9aSmrg#else 249773143b9aSmrg 0, 249873143b9aSmrg#endif 249973143b9aSmrg#ifdef TRANS_CLIENT 250073143b9aSmrg TRANS(SocketOpenCOTSClient), 250173143b9aSmrg#endif /* TRANS_CLIENT */ 250273143b9aSmrg#ifdef TRANS_SERVER 250373143b9aSmrg NULL, 250473143b9aSmrg TRANS(SocketOpenCOTSServer), 250573143b9aSmrg#endif /* TRANS_SERVER */ 250673143b9aSmrg#ifdef TRANS_REOPEN 250773143b9aSmrg TRANS(SocketReopenCOTSServer), 250873143b9aSmrg#endif 250973143b9aSmrg TRANS(SocketSetOption), 251073143b9aSmrg#ifdef TRANS_SERVER 251173143b9aSmrg TRANS(SocketUNIXCreateListener), 251273143b9aSmrg TRANS(SocketUNIXResetListener), 251373143b9aSmrg TRANS(SocketUNIXAccept), 251473143b9aSmrg#endif /* TRANS_SERVER */ 251573143b9aSmrg#ifdef TRANS_CLIENT 251673143b9aSmrg TRANS(SocketUNIXConnect), 251773143b9aSmrg#endif /* TRANS_CLIENT */ 251873143b9aSmrg TRANS(SocketBytesReadable), 251973143b9aSmrg TRANS(SocketRead), 252073143b9aSmrg TRANS(SocketWrite), 252173143b9aSmrg TRANS(SocketReadv), 252273143b9aSmrg TRANS(SocketWritev), 252375ebec6dSmrg#if XTRANS_SEND_FDS 252475ebec6dSmrg TRANS(SocketSendFd), 252575ebec6dSmrg TRANS(SocketRecvFd), 252675ebec6dSmrg#endif 252773143b9aSmrg TRANS(SocketDisconnect), 252873143b9aSmrg TRANS(SocketUNIXClose), 252973143b9aSmrg TRANS(SocketUNIXCloseForCloning), 253073143b9aSmrg }; 253173143b9aSmrg#endif /* !LOCALCONN */ 253273143b9aSmrg# ifdef TRANS_SERVER 253373143b9aSmrg# if !defined(LOCALCONN) 253475ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL }; 253573143b9aSmrg# endif 253673143b9aSmrg# endif 2537fe567363Smrg 253873143b9aSmrgXtransport TRANS(SocketUNIXFuncs) = { 253973143b9aSmrg /* Socket Interface */ 254073143b9aSmrg "unix", 254173143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS) 254273143b9aSmrg TRANS_ALIAS, 254373143b9aSmrg#else 254473143b9aSmrg 0, 254573143b9aSmrg#endif 254673143b9aSmrg#ifdef TRANS_CLIENT 254773143b9aSmrg TRANS(SocketOpenCOTSClient), 254873143b9aSmrg#endif /* TRANS_CLIENT */ 254973143b9aSmrg#ifdef TRANS_SERVER 255073143b9aSmrg#if !defined(LOCALCONN) 255173143b9aSmrg unix_nolisten, 255273143b9aSmrg#else 255373143b9aSmrg NULL, 255473143b9aSmrg#endif 255573143b9aSmrg TRANS(SocketOpenCOTSServer), 255673143b9aSmrg#endif /* TRANS_SERVER */ 255773143b9aSmrg#ifdef TRANS_REOPEN 255873143b9aSmrg TRANS(SocketReopenCOTSServer), 255973143b9aSmrg#endif 256073143b9aSmrg TRANS(SocketSetOption), 256173143b9aSmrg#ifdef TRANS_SERVER 256273143b9aSmrg TRANS(SocketUNIXCreateListener), 256373143b9aSmrg TRANS(SocketUNIXResetListener), 256473143b9aSmrg TRANS(SocketUNIXAccept), 256573143b9aSmrg#endif /* TRANS_SERVER */ 256673143b9aSmrg#ifdef TRANS_CLIENT 256773143b9aSmrg TRANS(SocketUNIXConnect), 256873143b9aSmrg#endif /* TRANS_CLIENT */ 256973143b9aSmrg TRANS(SocketBytesReadable), 257073143b9aSmrg TRANS(SocketRead), 257173143b9aSmrg TRANS(SocketWrite), 257273143b9aSmrg TRANS(SocketReadv), 257373143b9aSmrg TRANS(SocketWritev), 257475ebec6dSmrg#if XTRANS_SEND_FDS 257575ebec6dSmrg TRANS(SocketSendFd), 257675ebec6dSmrg TRANS(SocketRecvFd), 257775ebec6dSmrg#endif 257873143b9aSmrg TRANS(SocketDisconnect), 257973143b9aSmrg TRANS(SocketUNIXClose), 258073143b9aSmrg TRANS(SocketUNIXCloseForCloning), 258173143b9aSmrg }; 258273143b9aSmrg 258373143b9aSmrg#endif /* UNIXCONN */ 2584