1af928962Smrg/* 2ac57ed83Smrg * Copyright (c) 2002, 2025, 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 158ac57ed83Smrg#if defined(IPv6) && !defined(AF_INET6) 159ac57ed83Smrg#error "Cannot build IPv6 support without AF_INET6" 160ac57ed83Smrg#endif 161ac57ed83Smrg 162ac57ed83Smrg/* Temporary workaround for consumers whose configure scripts were 163ac57ed83Smrg generated with pre-1.6 versions of xtrans.m4 */ 164ac57ed83Smrg#if defined(IPv6) && !defined(HAVE_GETADDRINFO) 165ac57ed83Smrg#define HAVE_GETADDRINFO 166ac57ed83Smrg#endif 167ac57ed83Smrg 16873143b9aSmrg/* 16973143b9aSmrg * This is the Socket implementation of the X Transport service layer 17073143b9aSmrg * 17173143b9aSmrg * This file contains the implementation for both the UNIX and INET domains, 17273143b9aSmrg * and can be built for either one, or both. 17373143b9aSmrg * 17473143b9aSmrg */ 17573143b9aSmrg 176fe567363Smrgtypedef struct _Sockettrans2dev { 177fe567363Smrg const char *transname; 17873143b9aSmrg int family; 17973143b9aSmrg int devcotsname; 18073143b9aSmrg int devcltsname; 18173143b9aSmrg int protocol; 18273143b9aSmrg} Sockettrans2dev; 18373143b9aSmrg 184ac57ed83Smrg/* As documented in the X(7) man page: 185ac57ed83Smrg * tcp TCP over IPv4 or IPv6 186ac57ed83Smrg * inet TCP over IPv4 only 187ac57ed83Smrg * inet6 TCP over IPv6 only 188ac57ed83Smrg * unix UNIX Domain Sockets (same host only) 189ac57ed83Smrg * local Platform preferred local connection method 190ac57ed83Smrg */ 19173143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = { 19273143b9aSmrg#ifdef TCPCONN 19373143b9aSmrg {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 194ac57ed83Smrg#ifndef IPv6 19573143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 19673143b9aSmrg#else /* IPv6 */ 19773143b9aSmrg {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 19873143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ 19973143b9aSmrg {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 20073143b9aSmrg#endif 20173143b9aSmrg#endif /* TCPCONN */ 20273143b9aSmrg#ifdef UNIXCONN 20373143b9aSmrg {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 20473143b9aSmrg#if !defined(LOCALCONN) 20573143b9aSmrg {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 20673143b9aSmrg#endif /* !LOCALCONN */ 20773143b9aSmrg#endif /* UNIXCONN */ 20873143b9aSmrg}; 20973143b9aSmrg 21073143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev)) 21173143b9aSmrg 21273143b9aSmrg#ifdef TCPCONN 21373143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr); 21473143b9aSmrg#endif 21573143b9aSmrg 216ac57ed83Smrg#if (defined(TCPCONN) && \ 217ac57ed83Smrg (defined(TRANS_SERVER) || defined(X11_t) || !defined(HAVE_GETADDRINFO))) \ 218ac57ed83Smrg || defined(TRANS_REOPEN) 219a773ec55Smrgstatic int 220a773ec55Smrgis_numeric (const char *str) 221a773ec55Smrg{ 222a773ec55Smrg int i; 223a773ec55Smrg 224a773ec55Smrg for (i = 0; i < (int) strlen (str); i++) 225a773ec55Smrg if (!isdigit (str[i])) 226a773ec55Smrg return (0); 227a773ec55Smrg 228a773ec55Smrg return (1); 229a773ec55Smrg} 230a773ec55Smrg#endif 231a773ec55Smrg 23273143b9aSmrg#ifdef UNIXCONN 23373143b9aSmrg 23473143b9aSmrg 23573143b9aSmrg#if defined(X11_t) 23673143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 23773143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 23873143b9aSmrg#endif /* X11_t */ 23973143b9aSmrg#if defined(XIM_t) 24073143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM" 24173143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix" 24273143b9aSmrg#endif /* XIM_t */ 24373143b9aSmrg#if defined(FS_t) || defined(FONT_t) 24473143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs" 24573143b9aSmrg#define UNIX_DIR "/tmp/.font-unix" 24673143b9aSmrg#endif /* FS_t || FONT_t */ 24773143b9aSmrg#if defined(ICE_t) 24873143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/" 24973143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix" 25073143b9aSmrg#endif /* ICE_t */ 25173143b9aSmrg 25273143b9aSmrg 25373143b9aSmrg#endif /* UNIXCONN */ 25473143b9aSmrg 25573143b9aSmrg#define PORTBUFSIZE 32 25673143b9aSmrg 25773143b9aSmrg#ifndef MAXHOSTNAMELEN 25873143b9aSmrg#define MAXHOSTNAMELEN 255 25973143b9aSmrg#endif 26073143b9aSmrg 261ac57ed83Smrg#if defined(HAVE_SOCKLEN_T) || defined(IPv6) 26273143b9aSmrg# define SOCKLEN_T socklen_t 263a773ec55Smrg#elif defined(SVR4) || defined(__SVR4) 264fe567363Smrg# define SOCKLEN_T size_t 26573143b9aSmrg#else 26673143b9aSmrg# define SOCKLEN_T int 26773143b9aSmrg#endif 26873143b9aSmrg 26973143b9aSmrg/* 27073143b9aSmrg * These are some utility function used by the real interface function below. 27173143b9aSmrg */ 27273143b9aSmrg 27373143b9aSmrgstatic int 274fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family) 27573143b9aSmrg 27673143b9aSmrg{ 27773143b9aSmrg int i; 27873143b9aSmrg 279fe567363Smrg prmsg (3,"SocketSelectFamily(%s)\n", family); 28073143b9aSmrg 28194f982dbSmrg for (i = first + 1; i < (int)NUMSOCKETFAMILIES; i++) 28273143b9aSmrg { 28373143b9aSmrg if (!strcmp (family, Sockettrans2devtab[i].transname)) 28473143b9aSmrg return i; 28573143b9aSmrg } 28673143b9aSmrg 28773143b9aSmrg return (first == -1 ? -2 : -1); 28873143b9aSmrg} 28973143b9aSmrg 29073143b9aSmrg 29173143b9aSmrg/* 29273143b9aSmrg * This function gets the local address of the socket and stores it in the 29373143b9aSmrg * XtransConnInfo structure for the connection. 29473143b9aSmrg */ 29573143b9aSmrg 29673143b9aSmrgstatic int 29773143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr) 29873143b9aSmrg 29973143b9aSmrg{ 300ac57ed83Smrg#ifdef HAVE_STRUCT_SOCKADDR_STORAGE 301ac57ed83Smrg struct sockaddr_storage sockname; 302b53e5eeaSmrg#else 303ac57ed83Smrg struct sockaddr_in sockname; 304b53e5eeaSmrg#endif 305ac57ed83Smrg void *socknamePtr = &sockname; 306ac57ed83Smrg SOCKLEN_T namelen = sizeof(sockname); 30773143b9aSmrg 308ac57ed83Smrg prmsg (3,"SocketINETGetAddr(%p)\n", (void *) ciptr); 30973143b9aSmrg 31073143b9aSmrg bzero(socknamePtr, namelen); 311fe567363Smrg 31273143b9aSmrg if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, 31373143b9aSmrg (void *)&namelen) < 0) 31473143b9aSmrg { 31573143b9aSmrg#ifdef WIN32 31673143b9aSmrg errno = WSAGetLastError(); 31773143b9aSmrg#endif 318fe567363Smrg prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n", 319fe567363Smrg EGET()); 32073143b9aSmrg return -1; 32173143b9aSmrg } 32273143b9aSmrg 32373143b9aSmrg /* 32473143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 32573143b9aSmrg */ 32673143b9aSmrg 327fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 32873143b9aSmrg { 329fe567363Smrg prmsg (1, 330fe567363Smrg "SocketINETGetAddr: Can't allocate space for the addr\n"); 33173143b9aSmrg return -1; 33273143b9aSmrg } 33373143b9aSmrg 334b53e5eeaSmrg ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; 33573143b9aSmrg ciptr->addrlen = namelen; 33673143b9aSmrg memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); 33773143b9aSmrg 33873143b9aSmrg return 0; 33973143b9aSmrg} 34073143b9aSmrg 34173143b9aSmrg 34273143b9aSmrg/* 34373143b9aSmrg * This function gets the remote address of the socket and stores it in the 34473143b9aSmrg * XtransConnInfo structure for the connection. 34573143b9aSmrg */ 34673143b9aSmrg 34773143b9aSmrgstatic int 34873143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) 34973143b9aSmrg 35073143b9aSmrg{ 351ac57ed83Smrg#ifdef HAVE_STRUCT_SOCKADDR_STORAGE 352ac57ed83Smrg struct sockaddr_storage sockname; 353ac57ed83Smrg#else 354ac57ed83Smrg struct sockaddr_in sockname; 35573143b9aSmrg#endif 356ac57ed83Smrg void *socknamePtr = &sockname; 357ac57ed83Smrg SOCKLEN_T namelen = sizeof(sockname); 35873143b9aSmrg 35973143b9aSmrg bzero(socknamePtr, namelen); 360fe567363Smrg 361ac57ed83Smrg prmsg (3,"SocketINETGetPeerAddr(%p)\n", (void *) ciptr); 36273143b9aSmrg 36373143b9aSmrg if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, 36473143b9aSmrg (void *)&namelen) < 0) 36573143b9aSmrg { 36673143b9aSmrg#ifdef WIN32 36773143b9aSmrg errno = WSAGetLastError(); 36873143b9aSmrg#endif 369fe567363Smrg prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", 370fe567363Smrg EGET()); 37173143b9aSmrg return -1; 37273143b9aSmrg } 37373143b9aSmrg 37473143b9aSmrg /* 37573143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 37673143b9aSmrg */ 37773143b9aSmrg 378fe567363Smrg if ((ciptr->peeraddr = malloc (namelen)) == NULL) 37973143b9aSmrg { 380fe567363Smrg prmsg (1, 381fe567363Smrg "SocketINETGetPeerAddr: Can't allocate space for the addr\n"); 38273143b9aSmrg return -1; 38373143b9aSmrg } 38473143b9aSmrg 38573143b9aSmrg ciptr->peeraddrlen = namelen; 38673143b9aSmrg memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); 38773143b9aSmrg 38873143b9aSmrg return 0; 38973143b9aSmrg} 39073143b9aSmrg 39173143b9aSmrg 39273143b9aSmrgstatic XtransConnInfo 39373143b9aSmrgTRANS(SocketOpen) (int i, int type) 39473143b9aSmrg 39573143b9aSmrg{ 39673143b9aSmrg XtransConnInfo ciptr; 39773143b9aSmrg 398fe567363Smrg prmsg (3,"SocketOpen(%d,%d)\n", i, type); 39973143b9aSmrg 400fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 40173143b9aSmrg { 402fe567363Smrg prmsg (1, "SocketOpen: malloc failed\n"); 40373143b9aSmrg return NULL; 40473143b9aSmrg } 40573143b9aSmrg 40694f982dbSmrg ciptr->fd = socket(Sockettrans2devtab[i].family, type, 40794f982dbSmrg Sockettrans2devtab[i].protocol); 40894f982dbSmrg 40973143b9aSmrg#ifndef WIN32 41073143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) 41194f982dbSmrg if (ciptr->fd >= sysconf(_SC_OPEN_MAX)) 41294f982dbSmrg { 41394f982dbSmrg prmsg (2, "SocketOpen: socket() returned out of range fd %d\n", 41494f982dbSmrg ciptr->fd); 41594f982dbSmrg close (ciptr->fd); 41694f982dbSmrg ciptr->fd = -1; 41794f982dbSmrg } 41873143b9aSmrg#endif 41973143b9aSmrg#endif 42094f982dbSmrg 42194f982dbSmrg if (ciptr->fd < 0) { 42273143b9aSmrg#ifdef WIN32 42373143b9aSmrg errno = WSAGetLastError(); 42473143b9aSmrg#endif 425fe567363Smrg prmsg (2, "SocketOpen: socket() failed for %s\n", 426fe567363Smrg Sockettrans2devtab[i].transname); 42773143b9aSmrg 428fe567363Smrg free (ciptr); 42973143b9aSmrg return NULL; 43073143b9aSmrg } 43173143b9aSmrg 43273143b9aSmrg#ifdef TCP_NODELAY 43373143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 434ac57ed83Smrg#ifdef IPv6 43573143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 43673143b9aSmrg#endif 43773143b9aSmrg ) 43873143b9aSmrg { 43973143b9aSmrg /* 44073143b9aSmrg * turn off TCP coalescence for INET sockets 44173143b9aSmrg */ 44273143b9aSmrg 44373143b9aSmrg int tmp = 1; 44473143b9aSmrg setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, 44573143b9aSmrg (char *) &tmp, sizeof (int)); 44673143b9aSmrg } 44773143b9aSmrg#endif 44873143b9aSmrg 4498a0d9095Smrg /* 4508a0d9095Smrg * Some systems provide a really small default buffer size for 4518a0d9095Smrg * UNIX sockets. Bump it up a bit such that large transfers don't 4528a0d9095Smrg * proceed at glacial speed. 4538a0d9095Smrg */ 4548a0d9095Smrg#ifdef SO_SNDBUF 4558a0d9095Smrg if (Sockettrans2devtab[i].family == AF_UNIX) 4568a0d9095Smrg { 4578a0d9095Smrg SOCKLEN_T len = sizeof (int); 4588a0d9095Smrg int val; 4598a0d9095Smrg 4608a0d9095Smrg if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4618a0d9095Smrg (char *) &val, &len) == 0 && val < 64 * 1024) 4628a0d9095Smrg { 4638a0d9095Smrg val = 64 * 1024; 4648a0d9095Smrg setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4658a0d9095Smrg (char *) &val, sizeof (int)); 4668a0d9095Smrg } 4678a0d9095Smrg } 4688a0d9095Smrg#endif 4698a0d9095Smrg 47073143b9aSmrg return ciptr; 47173143b9aSmrg} 47273143b9aSmrg 47373143b9aSmrg 47473143b9aSmrg#ifdef TRANS_REOPEN 47573143b9aSmrg 47673143b9aSmrgstatic XtransConnInfo 4776a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port) 47873143b9aSmrg 47973143b9aSmrg{ 48073143b9aSmrg XtransConnInfo ciptr; 48173143b9aSmrg int portlen; 48273143b9aSmrg struct sockaddr *addr; 483fe567363Smrg size_t addrlen; 48473143b9aSmrg 485fe567363Smrg prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); 48673143b9aSmrg 48773143b9aSmrg if (port == NULL) { 488fe567363Smrg prmsg (1, "SocketReopen: port was null!\n"); 48973143b9aSmrg return NULL; 49073143b9aSmrg } 49173143b9aSmrg 49273143b9aSmrg portlen = strlen(port) + 1; // include space for trailing null 49373143b9aSmrg#ifdef SOCK_MAXADDRLEN 49473143b9aSmrg if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { 495fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 49673143b9aSmrg return NULL; 49773143b9aSmrg } 49873143b9aSmrg if (portlen < 14) portlen = 14; 49973143b9aSmrg#else 50073143b9aSmrg if (portlen < 0 || portlen > 14) { 501fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 50273143b9aSmrg return NULL; 50373143b9aSmrg } 50473143b9aSmrg#endif /*SOCK_MAXADDRLEN*/ 50573143b9aSmrg 506fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 50773143b9aSmrg { 508fe567363Smrg prmsg (1, "SocketReopen: malloc(ciptr) failed\n"); 50973143b9aSmrg return NULL; 51073143b9aSmrg } 51173143b9aSmrg 51273143b9aSmrg ciptr->fd = fd; 51373143b9aSmrg 514fe567363Smrg addrlen = portlen + offsetof(struct sockaddr, sa_data); 515fe567363Smrg if ((addr = calloc (1, addrlen)) == NULL) { 516fe567363Smrg prmsg (1, "SocketReopen: malloc(addr) failed\n"); 517fe567363Smrg free (ciptr); 51873143b9aSmrg return NULL; 51973143b9aSmrg } 5208d4c0f7bSmrg ciptr->addr = (char *) addr; 521fe567363Smrg ciptr->addrlen = addrlen; 52273143b9aSmrg 523fe567363Smrg if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { 524fe567363Smrg prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); 525fe567363Smrg free (addr); 526fe567363Smrg free (ciptr); 52773143b9aSmrg return NULL; 52873143b9aSmrg } 529fe567363Smrg ciptr->peeraddrlen = addrlen; 53073143b9aSmrg 53173143b9aSmrg /* Initialize ciptr structure as if it were a normally-opened unix socket */ 53273143b9aSmrg ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; 53373143b9aSmrg#ifdef BSD44SOCKETS 534fe567363Smrg addr->sa_len = addrlen; 53573143b9aSmrg#endif 53673143b9aSmrg addr->sa_family = AF_UNIX; 5377448d6e9Smrg#if defined(HAVE_STRLCPY) || defined(HAS_STRLCPY) 53873143b9aSmrg strlcpy(addr->sa_data, port, portlen); 53973143b9aSmrg#else 54073143b9aSmrg strncpy(addr->sa_data, port, portlen); 54173143b9aSmrg#endif 54273143b9aSmrg ciptr->family = AF_UNIX; 543fe567363Smrg memcpy(ciptr->peeraddr, ciptr->addr, addrlen); 54473143b9aSmrg ciptr->port = rindex(addr->sa_data, ':'); 545e8a71cdfSmrg if (ciptr->port == NULL) { 546e8a71cdfSmrg if (is_numeric(addr->sa_data)) { 547e8a71cdfSmrg ciptr->port = addr->sa_data; 548e8a71cdfSmrg } 549e8a71cdfSmrg } else if (ciptr->port[0] == ':') { 550e8a71cdfSmrg ciptr->port++; 551e8a71cdfSmrg } 552e8a71cdfSmrg /* port should now point to portnum or NULL */ 55373143b9aSmrg return ciptr; 55473143b9aSmrg} 55573143b9aSmrg 55673143b9aSmrg#endif /* TRANS_REOPEN */ 55773143b9aSmrg 55873143b9aSmrg 55973143b9aSmrg/* 56073143b9aSmrg * These functions are the interface supplied in the Xtransport structure 56173143b9aSmrg */ 56273143b9aSmrg 56373143b9aSmrg#ifdef TRANS_CLIENT 56473143b9aSmrg 56573143b9aSmrgstatic XtransConnInfo 566fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol, 567fe567363Smrg const char *host, const char *port, int previndex) 56873143b9aSmrg{ 569ac57ed83Smrg XtransConnInfo ciptr = NULL; 57073143b9aSmrg int i = previndex; 57173143b9aSmrg 572fe567363Smrg prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n", 57373143b9aSmrg protocol, host, port); 57473143b9aSmrg 57573143b9aSmrg SocketInitOnce(); 57673143b9aSmrg 57773143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { 57873143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 579e8a71cdfSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) { 580e8a71cdfSmrg /* Save the index for later use */ 581e8a71cdfSmrg 582e8a71cdfSmrg ciptr->index = i; 58373143b9aSmrg break; 584e8a71cdfSmrg } 58573143b9aSmrg } 58673143b9aSmrg if (i < 0) { 58773143b9aSmrg if (i == -1) 588fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", 589fe567363Smrg transname); 59073143b9aSmrg else 591fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", 592fe567363Smrg transname); 59373143b9aSmrg return NULL; 59473143b9aSmrg } 59573143b9aSmrg 59673143b9aSmrg return ciptr; 59773143b9aSmrg} 59873143b9aSmrg 59973143b9aSmrgstatic XtransConnInfo 6006a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol, 6016a3641a6Ssnj const char *host, const char *port) 60273143b9aSmrg{ 60373143b9aSmrg return TRANS(SocketOpenCOTSClientBase)( 60473143b9aSmrg thistrans->TransName, protocol, host, port, -1); 60573143b9aSmrg} 60673143b9aSmrg 60773143b9aSmrg 60873143b9aSmrg#endif /* TRANS_CLIENT */ 60973143b9aSmrg 61073143b9aSmrg 61173143b9aSmrg#ifdef TRANS_SERVER 61273143b9aSmrg 61373143b9aSmrgstatic XtransConnInfo 6146a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol, 6156a3641a6Ssnj const char *host, const char *port) 61673143b9aSmrg 61773143b9aSmrg{ 618ac57ed83Smrg XtransConnInfo ciptr = NULL; 61973143b9aSmrg int i = -1; 62073143b9aSmrg 621fe567363Smrg prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); 62273143b9aSmrg 62373143b9aSmrg SocketInitOnce(); 62473143b9aSmrg 62573143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 62673143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 62773143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 62873143b9aSmrg break; 62973143b9aSmrg } 63073143b9aSmrg if (i < 0) { 631a773ec55Smrg if (i == -1) { 632a773ec55Smrg if (errno == EAFNOSUPPORT) { 633a773ec55Smrg thistrans->flags |= TRANS_NOLISTEN; 634a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Socket for %s unsupported on this system.\n", 635a773ec55Smrg thistrans->TransName); 636a773ec55Smrg } else { 637a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", 638a773ec55Smrg thistrans->TransName); 639a773ec55Smrg } 640a773ec55Smrg } else { 641fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", 642fe567363Smrg thistrans->TransName); 643a773ec55Smrg } 64473143b9aSmrg return NULL; 64573143b9aSmrg } 64673143b9aSmrg 64773143b9aSmrg /* 64873143b9aSmrg * Using this prevents the bind() check for an existing server listening 64973143b9aSmrg * on the same port, but it is required for other reasons. 65073143b9aSmrg */ 65173143b9aSmrg#ifdef SO_REUSEADDR 65273143b9aSmrg 65373143b9aSmrg /* 65473143b9aSmrg * SO_REUSEADDR only applied to AF_INET && AF_INET6 65573143b9aSmrg */ 65673143b9aSmrg 65773143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 658ac57ed83Smrg#ifdef IPv6 65973143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 66073143b9aSmrg#endif 66173143b9aSmrg ) 66273143b9aSmrg { 66373143b9aSmrg int one = 1; 66473143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, 66573143b9aSmrg (char *) &one, sizeof (int)); 66673143b9aSmrg } 66773143b9aSmrg#endif 66873143b9aSmrg#ifdef IPV6_V6ONLY 66973143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 67073143b9aSmrg { 67173143b9aSmrg int one = 1; 67273143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 67373143b9aSmrg } 67473143b9aSmrg#endif 67573143b9aSmrg /* Save the index for later use */ 67673143b9aSmrg 67773143b9aSmrg ciptr->index = i; 67873143b9aSmrg 67973143b9aSmrg return ciptr; 68073143b9aSmrg} 68173143b9aSmrg 68273143b9aSmrg#endif /* TRANS_SERVER */ 68373143b9aSmrg 68473143b9aSmrg 68573143b9aSmrg#ifdef TRANS_REOPEN 68673143b9aSmrg 68773143b9aSmrgstatic XtransConnInfo 6886a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port) 68973143b9aSmrg 69073143b9aSmrg{ 69173143b9aSmrg XtransConnInfo ciptr; 69273143b9aSmrg int i = -1; 69373143b9aSmrg 694fe567363Smrg prmsg (2, 695fe567363Smrg "SocketReopenCOTSServer(%d, %s)\n", fd, port); 69673143b9aSmrg 69773143b9aSmrg SocketInitOnce(); 69873143b9aSmrg 69973143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 70073143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 70173143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 70273143b9aSmrg break; 70373143b9aSmrg } 70473143b9aSmrg if (i < 0) { 70573143b9aSmrg if (i == -1) 706fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", 707fe567363Smrg thistrans->TransName); 70873143b9aSmrg else 709fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", 710fe567363Smrg thistrans->TransName); 71173143b9aSmrg return NULL; 71273143b9aSmrg } 71373143b9aSmrg 71473143b9aSmrg /* Save the index for later use */ 71573143b9aSmrg 71673143b9aSmrg ciptr->index = i; 71773143b9aSmrg 71873143b9aSmrg return ciptr; 71973143b9aSmrg} 72073143b9aSmrg 72173143b9aSmrg#endif /* TRANS_REOPEN */ 72273143b9aSmrg 72373143b9aSmrg 72473143b9aSmrgstatic int 72573143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) 72673143b9aSmrg 72773143b9aSmrg{ 728fe567363Smrg prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); 72973143b9aSmrg 73073143b9aSmrg return -1; 73173143b9aSmrg} 73273143b9aSmrg 73373143b9aSmrg#ifdef UNIXCONN 73473143b9aSmrgstatic int 73573143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract) 73673143b9aSmrg{ 73773143b9aSmrg struct sockaddr_un s; 73894f982dbSmrg ssize_t maxlen = sizeof(s.sun_path) - 1; 73973143b9aSmrg const char *at = ""; 74073143b9aSmrg 74173143b9aSmrg if (!port || !*port || !path) 74273143b9aSmrg return -1; 74373143b9aSmrg 74473143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 74573143b9aSmrg if (port[0] == '@') 74673143b9aSmrg upath = ""; 74773143b9aSmrg else if (abstract) 74873143b9aSmrg at = "@"; 74973143b9aSmrg#endif 75073143b9aSmrg 75173143b9aSmrg if (*port == '/') /* a full pathname */ 75273143b9aSmrg upath = ""; 75373143b9aSmrg 75494f982dbSmrg if ((ssize_t)(strlen(at) + strlen(upath) + strlen(port)) > maxlen) 75573143b9aSmrg return -1; 756fe567363Smrg snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port); 75773143b9aSmrg return 0; 75873143b9aSmrg} 75973143b9aSmrg#endif 76073143b9aSmrg 76173143b9aSmrg#ifdef TRANS_SERVER 76273143b9aSmrg 76373143b9aSmrgstatic int 764fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr, 76573143b9aSmrg struct sockaddr *sockname, 76673143b9aSmrg int socknamelen, unsigned int flags) 76773143b9aSmrg 76873143b9aSmrg{ 76973143b9aSmrg SOCKLEN_T namelen = socknamelen; 77073143b9aSmrg int fd = ciptr->fd; 77173143b9aSmrg int retry; 77273143b9aSmrg 773ac57ed83Smrg prmsg (3, "SocketCreateListener(%p,%d)\n", (void *) ciptr, fd); 77473143b9aSmrg 77573143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 776ac57ed83Smrg#ifdef IPv6 77773143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 77873143b9aSmrg#endif 77973143b9aSmrg ) 78073143b9aSmrg retry = 20; 78173143b9aSmrg else 78273143b9aSmrg retry = 0; 78373143b9aSmrg 78494f982dbSmrg while (bind (fd, sockname, namelen) < 0) 78573143b9aSmrg { 78673143b9aSmrg if (errno == EADDRINUSE) { 78773143b9aSmrg if (flags & ADDR_IN_USE_ALLOWED) 78873143b9aSmrg break; 78973143b9aSmrg else 79073143b9aSmrg return TRANS_ADDR_IN_USE; 79173143b9aSmrg } 792fe567363Smrg 79373143b9aSmrg if (retry-- == 0) { 794fe567363Smrg prmsg (1, "SocketCreateListener: failed to bind listener\n"); 79573143b9aSmrg close (fd); 79673143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 79773143b9aSmrg } 79873143b9aSmrg#ifdef SO_REUSEADDR 79973143b9aSmrg sleep (1); 80073143b9aSmrg#else 80173143b9aSmrg sleep (10); 80273143b9aSmrg#endif /* SO_REUSEDADDR */ 80373143b9aSmrg } 80473143b9aSmrg 80573143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 806ac57ed83Smrg#ifdef IPv6 80773143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 80873143b9aSmrg#endif 80973143b9aSmrg ) { 81073143b9aSmrg#ifdef SO_DONTLINGER 81173143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); 81273143b9aSmrg#else 81373143b9aSmrg#ifdef SO_LINGER 81473143b9aSmrg { 81573143b9aSmrg static int linger[2] = { 0, 0 }; 81673143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_LINGER, 81773143b9aSmrg (char *) linger, sizeof (linger)); 81873143b9aSmrg } 81973143b9aSmrg#endif 82073143b9aSmrg#endif 82173143b9aSmrg} 82273143b9aSmrg 82373143b9aSmrg if (listen (fd, BACKLOG) < 0) 82473143b9aSmrg { 825fe567363Smrg prmsg (1, "SocketCreateListener: listen() failed\n"); 82673143b9aSmrg close (fd); 82773143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 82873143b9aSmrg } 829fe567363Smrg 83073143b9aSmrg /* Set a flag to indicate that this connection is a listener */ 83173143b9aSmrg 83273143b9aSmrg ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 83373143b9aSmrg 83473143b9aSmrg return 0; 83573143b9aSmrg} 83673143b9aSmrg 83773143b9aSmrg#ifdef TCPCONN 83873143b9aSmrgstatic int 8396a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port, 8406a3641a6Ssnj unsigned int flags) 84173143b9aSmrg 84273143b9aSmrg{ 843ac57ed83Smrg#ifdef HAVE_STRUCT_SOCKADDR_STORAGE 84473143b9aSmrg struct sockaddr_storage sockname; 84573143b9aSmrg#else 84673143b9aSmrg struct sockaddr_in sockname; 84773143b9aSmrg#endif 84873143b9aSmrg unsigned short sport; 84973143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 85073143b9aSmrg int status; 85173143b9aSmrg long tmpport; 85273143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 85373143b9aSmrg _Xgetservbynameparams sparams; 85473143b9aSmrg#endif 85573143b9aSmrg struct servent *servp; 85673143b9aSmrg 85773143b9aSmrg#ifdef X11_t 85873143b9aSmrg char portbuf[PORTBUFSIZE]; 85973143b9aSmrg#endif 860fe567363Smrg 861fe567363Smrg prmsg (2, "SocketINETCreateListener(%s)\n", port); 86273143b9aSmrg 86373143b9aSmrg#ifdef X11_t 86473143b9aSmrg /* 86573143b9aSmrg * X has a well known port, that is transport dependent. It is easier 86673143b9aSmrg * to handle it here, than try and come up with a transport independent 86773143b9aSmrg * representation that can be passed in and resolved the usual way. 86873143b9aSmrg * 86973143b9aSmrg * The port that is passed here is really a string containing the idisplay 87073143b9aSmrg * from ConnectDisplay(). 87173143b9aSmrg */ 87273143b9aSmrg 87373143b9aSmrg if (is_numeric (port)) 87473143b9aSmrg { 87573143b9aSmrg /* fixup the server port address */ 87673143b9aSmrg tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 877fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 87873143b9aSmrg port = portbuf; 87973143b9aSmrg } 88073143b9aSmrg#endif 88173143b9aSmrg 88273143b9aSmrg if (port && *port) 88373143b9aSmrg { 88473143b9aSmrg /* Check to see if the port string is just a number (handles X11) */ 88573143b9aSmrg 88673143b9aSmrg if (!is_numeric (port)) 88773143b9aSmrg { 88873143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) 88973143b9aSmrg { 890fe567363Smrg prmsg (1, 89173143b9aSmrg "SocketINETCreateListener: Unable to get service for %s\n", 892fe567363Smrg port); 89373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 89473143b9aSmrg } 89573143b9aSmrg /* we trust getservbyname to return a valid number */ 89673143b9aSmrg sport = servp->s_port; 89773143b9aSmrg } 89873143b9aSmrg else 89973143b9aSmrg { 90073143b9aSmrg tmpport = strtol (port, (char**)NULL, 10); 901fe567363Smrg /* 90273143b9aSmrg * check that somehow the port address isn't negative or in 90373143b9aSmrg * the range of reserved port addresses. This can happen and 904fe567363Smrg * be very bad if the server is suid-root and the user does 905fe567363Smrg * something (dumb) like `X :60049`. 90673143b9aSmrg */ 90773143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 90873143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 90973143b9aSmrg 91073143b9aSmrg sport = (unsigned short) tmpport; 91173143b9aSmrg } 91273143b9aSmrg } 91373143b9aSmrg else 91473143b9aSmrg sport = 0; 91573143b9aSmrg 91673143b9aSmrg bzero(&sockname, sizeof(sockname)); 91773143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 91873143b9aSmrg namelen = sizeof (struct sockaddr_in); 91973143b9aSmrg#ifdef BSD44SOCKETS 92073143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_len = namelen; 92173143b9aSmrg#endif 92273143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; 92373143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); 92473143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); 92573143b9aSmrg } else { 926ac57ed83Smrg#ifdef IPv6 92773143b9aSmrg namelen = sizeof (struct sockaddr_in6); 92873143b9aSmrg#ifdef SIN6_LEN 92973143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); 93073143b9aSmrg#endif 93173143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; 93273143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); 93373143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; 93473143b9aSmrg#else 935ac57ed83Smrg prmsg (1, 936ac57ed83Smrg "SocketINETCreateListener: unsupported address family %d\n", 937ac57ed83Smrg Sockettrans2devtab[ciptr->index].family); 938ac57ed83Smrg return TRANS_CREATE_LISTENER_FAILED; 93973143b9aSmrg#endif 940ac57ed83Smrg } 94173143b9aSmrg 94273143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 94373143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 94473143b9aSmrg { 945fe567363Smrg prmsg (1, 946fe567363Smrg "SocketINETCreateListener: ...SocketCreateListener() failed\n"); 94773143b9aSmrg return status; 94873143b9aSmrg } 94973143b9aSmrg 95073143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 95173143b9aSmrg { 952fe567363Smrg prmsg (1, 953fe567363Smrg "SocketINETCreateListener: ...SocketINETGetAddr() failed\n"); 95473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 95573143b9aSmrg } 95673143b9aSmrg 95773143b9aSmrg return 0; 95873143b9aSmrg} 95973143b9aSmrg 96073143b9aSmrg#endif /* TCPCONN */ 96173143b9aSmrg 96273143b9aSmrg 96373143b9aSmrg#ifdef UNIXCONN 96473143b9aSmrg 96573143b9aSmrgstatic int 9666a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port, 96773143b9aSmrg unsigned int flags) 96873143b9aSmrg 96973143b9aSmrg{ 97073143b9aSmrg struct sockaddr_un sockname; 97173143b9aSmrg int namelen; 97273143b9aSmrg int oldUmask; 97373143b9aSmrg int status; 97473143b9aSmrg unsigned int mode; 97573143b9aSmrg char tmpport[108]; 97673143b9aSmrg 97773143b9aSmrg int abstract = 0; 97873143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 97973143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 98073143b9aSmrg#endif 98173143b9aSmrg 982fe567363Smrg prmsg (2, "SocketUNIXCreateListener(%s)\n", 983fe567363Smrg port ? port : "NULL"); 98473143b9aSmrg 98573143b9aSmrg /* Make sure the directory is created */ 98673143b9aSmrg 98773143b9aSmrg oldUmask = umask (0); 98873143b9aSmrg 98973143b9aSmrg#ifdef UNIX_DIR 99073143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 99173143b9aSmrg mode = 01777; 99273143b9aSmrg#else 99373143b9aSmrg mode = 0777; 99473143b9aSmrg#endif 9958d4c0f7bSmrg if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) { 996fe567363Smrg prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", 997fe567363Smrg UNIX_DIR, errno); 99873143b9aSmrg (void) umask (oldUmask); 99973143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 100073143b9aSmrg } 100173143b9aSmrg#endif 100273143b9aSmrg 100373143b9aSmrg memset(&sockname, 0, sizeof(sockname)); 100473143b9aSmrg sockname.sun_family = AF_UNIX; 100573143b9aSmrg 100673143b9aSmrg if (!(port && *port)) { 100773143b9aSmrg snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid()); 100873143b9aSmrg port = tmpport; 100973143b9aSmrg } 101073143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1011fe567363Smrg prmsg (1, "SocketUNIXCreateListener: path too long\n"); 101273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 101373143b9aSmrg } 101473143b9aSmrg 1015a773ec55Smrg#if defined(BSD44SOCKETS) 101673143b9aSmrg sockname.sun_len = strlen(sockname.sun_path); 101773143b9aSmrg#endif 101873143b9aSmrg 101973143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 102073143b9aSmrg namelen = SUN_LEN(&sockname); 102173143b9aSmrg#else 102273143b9aSmrg namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 102373143b9aSmrg#endif 102473143b9aSmrg 102573143b9aSmrg if (abstract) { 102673143b9aSmrg sockname.sun_path[0] = '\0'; 102773143b9aSmrg namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]); 102873143b9aSmrg } 102973143b9aSmrg else 103073143b9aSmrg unlink (sockname.sun_path); 103173143b9aSmrg 103273143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 103373143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 103473143b9aSmrg { 1035fe567363Smrg prmsg (1, 1036fe567363Smrg "SocketUNIXCreateListener: ...SocketCreateListener() failed\n"); 103773143b9aSmrg (void) umask (oldUmask); 103873143b9aSmrg return status; 103973143b9aSmrg } 104073143b9aSmrg 104173143b9aSmrg /* 104273143b9aSmrg * Now that the listener is esablished, create the addr info for 104373143b9aSmrg * this connection. getpeername() doesn't work for UNIX Domain Sockets 104473143b9aSmrg * on some systems (hpux at least), so we will just do it manually, instead 104573143b9aSmrg * of calling something like TRANS(SocketUNIXGetAddr). 104673143b9aSmrg */ 104773143b9aSmrg 104873143b9aSmrg namelen = sizeof (sockname); /* this will always make it the same size */ 104973143b9aSmrg 1050fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 105173143b9aSmrg { 1052fe567363Smrg prmsg (1, 1053fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 105473143b9aSmrg (void) umask (oldUmask); 105573143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 105673143b9aSmrg } 105773143b9aSmrg 105873143b9aSmrg if (abstract) 105973143b9aSmrg sockname.sun_path[0] = '@'; 106073143b9aSmrg 106173143b9aSmrg ciptr->family = sockname.sun_family; 106273143b9aSmrg ciptr->addrlen = namelen; 106373143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 106473143b9aSmrg 106573143b9aSmrg (void) umask (oldUmask); 106673143b9aSmrg 106773143b9aSmrg return 0; 106873143b9aSmrg} 106973143b9aSmrg 107073143b9aSmrg 107173143b9aSmrgstatic int 107273143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) 107373143b9aSmrg 107473143b9aSmrg{ 107573143b9aSmrg /* 107673143b9aSmrg * See if the unix domain socket has disappeared. If it has, recreate it. 107773143b9aSmrg */ 107873143b9aSmrg 107973143b9aSmrg struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; 108073143b9aSmrg struct stat statb; 108173143b9aSmrg int status = TRANS_RESET_NOOP; 108273143b9aSmrg unsigned int mode; 108373143b9aSmrg int abstract = 0; 108473143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 108573143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 108673143b9aSmrg#endif 108773143b9aSmrg 1088ac57ed83Smrg prmsg (3, "SocketUNIXResetListener(%p,%d)\n", (void *) ciptr, ciptr->fd); 108973143b9aSmrg 109073143b9aSmrg if (!abstract && ( 109173143b9aSmrg stat (unsock->sun_path, &statb) == -1 || 109273143b9aSmrg ((statb.st_mode & S_IFMT) != 1093a773ec55Smrg#if !defined(S_IFSOCK) 109473143b9aSmrg S_IFIFO 109573143b9aSmrg#else 109673143b9aSmrg S_IFSOCK 109773143b9aSmrg#endif 109873143b9aSmrg ))) 109973143b9aSmrg { 110073143b9aSmrg int oldUmask = umask (0); 110173143b9aSmrg 110273143b9aSmrg#ifdef UNIX_DIR 110373143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 110473143b9aSmrg mode = 01777; 110573143b9aSmrg#else 110673143b9aSmrg mode = 0777; 110773143b9aSmrg#endif 110873143b9aSmrg if (trans_mkdir(UNIX_DIR, mode) == -1) { 1109fe567363Smrg prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", 1110fe567363Smrg UNIX_DIR, errno); 111173143b9aSmrg (void) umask (oldUmask); 111273143b9aSmrg return TRANS_RESET_FAILURE; 111373143b9aSmrg } 111473143b9aSmrg#endif 111573143b9aSmrg 111673143b9aSmrg close (ciptr->fd); 111773143b9aSmrg unlink (unsock->sun_path); 111873143b9aSmrg 111973143b9aSmrg if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 112073143b9aSmrg { 112173143b9aSmrg TRANS(FreeConnInfo) (ciptr); 112273143b9aSmrg (void) umask (oldUmask); 112373143b9aSmrg return TRANS_RESET_FAILURE; 112473143b9aSmrg } 112573143b9aSmrg 112673143b9aSmrg if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) 112773143b9aSmrg { 112873143b9aSmrg close (ciptr->fd); 112973143b9aSmrg TRANS(FreeConnInfo) (ciptr); 113073143b9aSmrg return TRANS_RESET_FAILURE; 113173143b9aSmrg } 113273143b9aSmrg 113373143b9aSmrg if (listen (ciptr->fd, BACKLOG) < 0) 113473143b9aSmrg { 113573143b9aSmrg close (ciptr->fd); 113673143b9aSmrg TRANS(FreeConnInfo) (ciptr); 113773143b9aSmrg (void) umask (oldUmask); 113873143b9aSmrg return TRANS_RESET_FAILURE; 113973143b9aSmrg } 114073143b9aSmrg 114173143b9aSmrg umask (oldUmask); 114273143b9aSmrg 114373143b9aSmrg status = TRANS_RESET_NEW_FD; 114473143b9aSmrg } 114573143b9aSmrg 114673143b9aSmrg return status; 114773143b9aSmrg} 114873143b9aSmrg 114973143b9aSmrg#endif /* UNIXCONN */ 115073143b9aSmrg 115173143b9aSmrg 115273143b9aSmrg#ifdef TCPCONN 115373143b9aSmrg 115473143b9aSmrgstatic XtransConnInfo 115573143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) 115673143b9aSmrg 115773143b9aSmrg{ 115873143b9aSmrg XtransConnInfo newciptr; 115973143b9aSmrg struct sockaddr_in sockname; 116073143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 116173143b9aSmrg 1162ac57ed83Smrg prmsg (2, "SocketINETAccept(%p,%d)\n", (void *) ciptr, ciptr->fd); 116373143b9aSmrg 1164fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 116573143b9aSmrg { 1166fe567363Smrg prmsg (1, "SocketINETAccept: malloc failed\n"); 116773143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 116873143b9aSmrg return NULL; 116973143b9aSmrg } 117073143b9aSmrg 117173143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 117273143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 117373143b9aSmrg { 117473143b9aSmrg#ifdef WIN32 117573143b9aSmrg errno = WSAGetLastError(); 117673143b9aSmrg#endif 1177fe567363Smrg prmsg (1, "SocketINETAccept: accept() failed\n"); 1178fe567363Smrg free (newciptr); 117973143b9aSmrg *status = TRANS_ACCEPT_FAILED; 118073143b9aSmrg return NULL; 118173143b9aSmrg } 118273143b9aSmrg 118373143b9aSmrg#ifdef TCP_NODELAY 118473143b9aSmrg { 118573143b9aSmrg /* 118673143b9aSmrg * turn off TCP coalescence for INET sockets 118773143b9aSmrg */ 118873143b9aSmrg 118973143b9aSmrg int tmp = 1; 119073143b9aSmrg setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, 119173143b9aSmrg (char *) &tmp, sizeof (int)); 119273143b9aSmrg } 119373143b9aSmrg#endif 119473143b9aSmrg 119573143b9aSmrg /* 1196fe567363Smrg * Get this address again because the transport may give a more 119773143b9aSmrg * specific address now that a connection is established. 119873143b9aSmrg */ 119973143b9aSmrg 120073143b9aSmrg if (TRANS(SocketINETGetAddr) (newciptr) < 0) 120173143b9aSmrg { 1202fe567363Smrg prmsg (1, 1203fe567363Smrg "SocketINETAccept: ...SocketINETGetAddr() failed:\n"); 120473143b9aSmrg close (newciptr->fd); 1205fe567363Smrg free (newciptr); 120673143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 120773143b9aSmrg return NULL; 120873143b9aSmrg } 120973143b9aSmrg 121073143b9aSmrg if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) 121173143b9aSmrg { 1212fe567363Smrg prmsg (1, 1213fe567363Smrg "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n"); 121473143b9aSmrg close (newciptr->fd); 1215fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1216fe567363Smrg free (newciptr); 121773143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 121873143b9aSmrg return NULL; 121973143b9aSmrg } 122073143b9aSmrg 122173143b9aSmrg *status = 0; 122273143b9aSmrg 122373143b9aSmrg return newciptr; 122473143b9aSmrg} 122573143b9aSmrg 122673143b9aSmrg#endif /* TCPCONN */ 122773143b9aSmrg 122873143b9aSmrg 122973143b9aSmrg#ifdef UNIXCONN 123073143b9aSmrgstatic XtransConnInfo 123173143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) 123273143b9aSmrg 123373143b9aSmrg{ 123473143b9aSmrg XtransConnInfo newciptr; 123573143b9aSmrg struct sockaddr_un sockname; 123673143b9aSmrg SOCKLEN_T namelen = sizeof sockname; 123773143b9aSmrg 1238ac57ed83Smrg prmsg (2, "SocketUNIXAccept(%p,%d)\n", (void *) ciptr, ciptr->fd); 123973143b9aSmrg 1240fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 124173143b9aSmrg { 1242fe567363Smrg prmsg (1, "SocketUNIXAccept: malloc() failed\n"); 124373143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 124473143b9aSmrg return NULL; 124573143b9aSmrg } 124673143b9aSmrg 124773143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 124873143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 124973143b9aSmrg { 1250fe567363Smrg prmsg (1, "SocketUNIXAccept: accept() failed\n"); 1251fe567363Smrg free (newciptr); 125273143b9aSmrg *status = TRANS_ACCEPT_FAILED; 125373143b9aSmrg return NULL; 125473143b9aSmrg } 125573143b9aSmrg 125673143b9aSmrg ciptr->addrlen = namelen; 125773143b9aSmrg /* 125873143b9aSmrg * Get the socket name and the peer name from the listener socket, 125973143b9aSmrg * since this is unix domain. 126073143b9aSmrg */ 126173143b9aSmrg 1262fe567363Smrg if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL) 126373143b9aSmrg { 1264fe567363Smrg prmsg (1, 1265fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 126673143b9aSmrg close (newciptr->fd); 1267fe567363Smrg free (newciptr); 126873143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 126973143b9aSmrg return NULL; 127073143b9aSmrg } 127173143b9aSmrg 127273143b9aSmrg /* 127373143b9aSmrg * if the socket is abstract, we already modified the address to have a 127473143b9aSmrg * @ instead of the initial NUL, so no need to do that again here. 127573143b9aSmrg */ 127673143b9aSmrg 127773143b9aSmrg newciptr->addrlen = ciptr->addrlen; 127873143b9aSmrg memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); 127973143b9aSmrg 1280fe567363Smrg if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL) 128173143b9aSmrg { 1282fe567363Smrg prmsg (1, 1283fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 128473143b9aSmrg close (newciptr->fd); 1285fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1286fe567363Smrg free (newciptr); 128773143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 128873143b9aSmrg return NULL; 128973143b9aSmrg } 1290fe567363Smrg 129173143b9aSmrg newciptr->peeraddrlen = ciptr->addrlen; 129273143b9aSmrg memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); 129373143b9aSmrg 129473143b9aSmrg newciptr->family = AF_UNIX; 129573143b9aSmrg 129673143b9aSmrg *status = 0; 129773143b9aSmrg 129873143b9aSmrg return newciptr; 129973143b9aSmrg} 130073143b9aSmrg 130173143b9aSmrg#endif /* UNIXCONN */ 130273143b9aSmrg 130373143b9aSmrg#endif /* TRANS_SERVER */ 130473143b9aSmrg 130573143b9aSmrg 130673143b9aSmrg#ifdef TRANS_CLIENT 130773143b9aSmrg 130873143b9aSmrg#ifdef TCPCONN 130973143b9aSmrg 1310ac57ed83Smrg#ifdef HAVE_GETADDRINFO 131173143b9aSmrgstruct addrlist { 131273143b9aSmrg struct addrinfo * addr; 1313fe567363Smrg struct addrinfo * firstaddr; 131473143b9aSmrg char port[PORTBUFSIZE]; 131573143b9aSmrg char host[MAXHOSTNAMELEN]; 131673143b9aSmrg}; 131773143b9aSmrgstatic struct addrlist *addrlist = NULL; 131873143b9aSmrg#endif 131973143b9aSmrg 132073143b9aSmrg 132173143b9aSmrgstatic int 13226a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr, 13236a3641a6Ssnj const char *host, const char *port) 132473143b9aSmrg 132573143b9aSmrg{ 132673143b9aSmrg struct sockaddr * socketaddr = NULL; 132773143b9aSmrg int socketaddrlen = 0; 132873143b9aSmrg int res; 1329ac57ed83Smrg#ifdef HAVE_GETADDRINFO 133073143b9aSmrg struct addrinfo hints; 133173143b9aSmrg char ntopbuf[INET6_ADDRSTRLEN]; 133273143b9aSmrg int resetonce = 0; 1333fe567363Smrg#else 133473143b9aSmrg struct sockaddr_in sockname; 1335fe567363Smrg struct hostent *hostp; 1336fe567363Smrg struct servent *servp; 1337fe567363Smrg unsigned long tmpaddr; 1338fe567363Smrg#endif 133973143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 134073143b9aSmrg _Xgethostbynameparams hparams; 134173143b9aSmrg _Xgetservbynameparams sparams; 134273143b9aSmrg#endif 134373143b9aSmrg#ifdef X11_t 134473143b9aSmrg char portbuf[PORTBUFSIZE]; 134573143b9aSmrg#endif 134673143b9aSmrg 134773143b9aSmrg char hostnamebuf[256]; /* tmp space */ 134873143b9aSmrg 1349fe567363Smrg prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); 135073143b9aSmrg 135173143b9aSmrg if (!host) 135273143b9aSmrg { 135373143b9aSmrg hostnamebuf[0] = '\0'; 135473143b9aSmrg (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); 135573143b9aSmrg host = hostnamebuf; 135673143b9aSmrg } 135773143b9aSmrg 135873143b9aSmrg#ifdef X11_t 135973143b9aSmrg /* 136073143b9aSmrg * X has a well known port, that is transport dependent. It is easier 136173143b9aSmrg * to handle it here, than try and come up with a transport independent 136273143b9aSmrg * representation that can be passed in and resolved the usual way. 136373143b9aSmrg * 136473143b9aSmrg * The port that is passed here is really a string containing the idisplay 136573143b9aSmrg * from ConnectDisplay(). 136673143b9aSmrg */ 136773143b9aSmrg 136873143b9aSmrg if (is_numeric (port)) 136973143b9aSmrg { 1370fe567363Smrg long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 1371fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 137273143b9aSmrg port = portbuf; 137373143b9aSmrg } 137473143b9aSmrg#endif 137573143b9aSmrg 1376ac57ed83Smrg#ifdef HAVE_GETADDRINFO 1377b53e5eeaSmrg { 137873143b9aSmrg if (addrlist != NULL) { 137973143b9aSmrg if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { 138073143b9aSmrg if (addrlist->firstaddr) 138173143b9aSmrg freeaddrinfo(addrlist->firstaddr); 138273143b9aSmrg addrlist->firstaddr = NULL; 138373143b9aSmrg } 138473143b9aSmrg } else { 138573143b9aSmrg addrlist = malloc(sizeof(struct addrlist)); 138694f982dbSmrg if (addrlist == NULL) { 138794f982dbSmrg prmsg (1, "SocketINETConnect() can't allocate memory " 138894f982dbSmrg "for addrlist: %s\n", strerror(errno)); 138994f982dbSmrg return TRANS_CONNECT_FAILED; 139094f982dbSmrg } 139173143b9aSmrg addrlist->firstaddr = NULL; 139273143b9aSmrg } 139373143b9aSmrg 139473143b9aSmrg if (addrlist->firstaddr == NULL) { 139573143b9aSmrg strncpy(addrlist->port, port, sizeof(addrlist->port)); 139673143b9aSmrg addrlist->port[sizeof(addrlist->port) - 1] = '\0'; 139773143b9aSmrg strncpy(addrlist->host, host, sizeof(addrlist->host)); 139873143b9aSmrg addrlist->host[sizeof(addrlist->host) - 1] = '\0'; 139973143b9aSmrg 140073143b9aSmrg bzero(&hints,sizeof(hints)); 1401ac57ed83Smrg#ifdef IPv6 1402ac57ed83Smrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, "tcp") == 0) 1403ac57ed83Smrg hints.ai_family = AF_UNSPEC; 1404ac57ed83Smrg else 1405ac57ed83Smrg#endif 1406ac57ed83Smrg hints.ai_family = Sockettrans2devtab[ciptr->index].family; 140773143b9aSmrg hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; 140873143b9aSmrg 140973143b9aSmrg res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); 141073143b9aSmrg if (res != 0) { 1411fe567363Smrg prmsg (1, "SocketINETConnect() can't get address " 141273143b9aSmrg "for %s:%s: %s\n", host, port, gai_strerror(res)); 141373143b9aSmrg ESET(EINVAL); 141473143b9aSmrg return TRANS_CONNECT_FAILED; 141573143b9aSmrg } 141673143b9aSmrg for (res = 0, addrlist->addr = addrlist->firstaddr; 141773143b9aSmrg addrlist->addr ; res++) { 141873143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 141973143b9aSmrg } 1420fe567363Smrg prmsg(4,"Got New Address list with %d addresses\n", res); 142173143b9aSmrg res = 0; 142273143b9aSmrg addrlist->addr = NULL; 142373143b9aSmrg } 142473143b9aSmrg 142573143b9aSmrg while (socketaddr == NULL) { 142673143b9aSmrg if (addrlist->addr == NULL) { 1427fe567363Smrg if (resetonce) { 142873143b9aSmrg /* Already checked entire list - no usable addresses */ 1429fe567363Smrg prmsg (1, "SocketINETConnect() no usable address " 1430fe567363Smrg "for %s:%s\n", host, port); 143173143b9aSmrg return TRANS_CONNECT_FAILED; 143273143b9aSmrg } else { 143373143b9aSmrg /* Go back to beginning of list */ 143473143b9aSmrg resetonce = 1; 143573143b9aSmrg addrlist->addr = addrlist->firstaddr; 143673143b9aSmrg } 1437fe567363Smrg } 143873143b9aSmrg 143973143b9aSmrg socketaddr = addrlist->addr->ai_addr; 144073143b9aSmrg socketaddrlen = addrlist->addr->ai_addrlen; 144173143b9aSmrg 144273143b9aSmrg if (addrlist->addr->ai_family == AF_INET) { 144373143b9aSmrg struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; 144473143b9aSmrg 1445fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n", 144673143b9aSmrg inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, 1447fe567363Smrg ntopbuf,sizeof(ntopbuf))); 144873143b9aSmrg 1449fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n", 1450fe567363Smrg ntohs(sin->sin_port)); 145173143b9aSmrg 1452ac57ed83Smrg#ifdef IPv6 145373143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { 145473143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 145573143b9aSmrg "tcp") == 0) { 145673143b9aSmrg XtransConnInfo newciptr; 145773143b9aSmrg 145873143b9aSmrg /* 145973143b9aSmrg * Our socket is an IPv6 socket, but the address is 146073143b9aSmrg * IPv4. Close it and get an IPv4 socket. This is 146173143b9aSmrg * needed for IPv4 connections to work on platforms 146273143b9aSmrg * that don't allow IPv4 over IPv6 sockets. 146373143b9aSmrg */ 146473143b9aSmrg TRANS(SocketINETClose)(ciptr); 146573143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 146673143b9aSmrg "tcp", "tcp", host, port, ciptr->index); 146773143b9aSmrg if (newciptr) 146873143b9aSmrg ciptr->fd = newciptr->fd; 146973143b9aSmrg if (!newciptr || 147073143b9aSmrg Sockettrans2devtab[newciptr->index].family != 147173143b9aSmrg AF_INET) { 147273143b9aSmrg socketaddr = NULL; 1473fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv4 " 1474fe567363Smrg " socketfor IPv4 address\n"); 147573143b9aSmrg } 147673143b9aSmrg if (newciptr) 1477fe567363Smrg free(newciptr); 147873143b9aSmrg } else { 147973143b9aSmrg socketaddr = NULL; 1480fe567363Smrg prmsg (4,"SocketINETConnect Skipping IPv4 address\n"); 148173143b9aSmrg } 148273143b9aSmrg } 148373143b9aSmrg } else if (addrlist->addr->ai_family == AF_INET6) { 148473143b9aSmrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; 1485fe567363Smrg 1486fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n", 148773143b9aSmrg inet_ntop(addrlist->addr->ai_family, 1488fe567363Smrg &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf))); 1489fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n", 1490fe567363Smrg ntohs(sin6->sin6_port)); 149173143b9aSmrg 149273143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 149373143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 149473143b9aSmrg "tcp") == 0) { 149573143b9aSmrg XtransConnInfo newciptr; 149673143b9aSmrg 149773143b9aSmrg /* 149873143b9aSmrg * Close the IPv4 socket and try to open an IPv6 socket. 149973143b9aSmrg */ 150073143b9aSmrg TRANS(SocketINETClose)(ciptr); 150173143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 150273143b9aSmrg "tcp", "tcp", host, port, -1); 150373143b9aSmrg if (newciptr) 150473143b9aSmrg ciptr->fd = newciptr->fd; 150573143b9aSmrg if (!newciptr || 150673143b9aSmrg Sockettrans2devtab[newciptr->index].family != 150773143b9aSmrg AF_INET6) { 150873143b9aSmrg socketaddr = NULL; 1509fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv6 " 1510fe567363Smrg "socket for IPv6 address\n"); 151173143b9aSmrg } 151273143b9aSmrg if (newciptr) 1513fe567363Smrg free(newciptr); 151473143b9aSmrg } 151573143b9aSmrg else 151673143b9aSmrg { 151773143b9aSmrg socketaddr = NULL; 1518fe567363Smrg prmsg (4,"SocketINETConnect() Skipping IPv6 address\n"); 151973143b9aSmrg } 152073143b9aSmrg } 1521ac57ed83Smrg#endif /* IPv6 */ 152273143b9aSmrg } else { 152373143b9aSmrg socketaddr = NULL; /* Unsupported address type */ 152473143b9aSmrg } 152573143b9aSmrg if (socketaddr == NULL) { 152673143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 152773143b9aSmrg } 1528fe567363Smrg } 1529b53e5eeaSmrg } 1530ac57ed83Smrg#else /* !HAVE_GETADDRINFO */ 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 1654ac57ed83Smrg#ifdef HAVE_GETADDRINFO 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 1698ac57ed83Smrg#ifdef HAVE_GETADDRINFO 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 { 1729ac57ed83Smrg#ifdef HAVE_GETADDRINFO 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 } 1756ac57ed83Smrg#ifdef IPv6 175773143b9aSmrg } else if (i->ai_family == AF_INET6) { 1758fe567363Smrg struct sockaddr_in6 *sinA 175973143b9aSmrg = (struct sockaddr_in6 *) i->ai_addr; 1760fe567363Smrg struct sockaddr_in6 *sinB 176173143b9aSmrg = (struct sockaddr_in6 *) j->ai_addr; 176273143b9aSmrg struct in6_addr *A = &sinA->sin6_addr; 176373143b9aSmrg struct in6_addr *B = &sinB->sin6_addr; 176473143b9aSmrg 176573143b9aSmrg if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { 176673143b9aSmrg equiv = 1; 176773143b9aSmrg } 1768ac57ed83Smrg#endif /* IPv6 */ 176973143b9aSmrg } 177073143b9aSmrg } 177173143b9aSmrg } 177273143b9aSmrg } 1773fe567363Smrg 177473143b9aSmrg freeaddrinfo(localhostaddr); 177573143b9aSmrg freeaddrinfo(otherhostaddr); 177673143b9aSmrg return equiv; 1777ac57ed83Smrg#else /* !HAVE_GETADDRINFO */ 177873143b9aSmrg /* 177973143b9aSmrg * A host may have more than one network address. If any of the 178073143b9aSmrg * network addresses of 'host' (specified to the connect call) 178173143b9aSmrg * match any of the network addresses of 'hostname' (determined 178273143b9aSmrg * by TRANS(GetHostname)), then the two hostnames are equivalent, 178373143b9aSmrg * and we know that 'host' is really a local host. 178473143b9aSmrg */ 178573143b9aSmrg char specified_local_addr_list[10][4]; 178673143b9aSmrg int scount, equiv, i, j; 178773143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 178873143b9aSmrg _Xgethostbynameparams hparams; 178973143b9aSmrg#endif 179073143b9aSmrg struct hostent *hostp; 179173143b9aSmrg 179273143b9aSmrg if ((hostp = _XGethostbyname (host,hparams)) == NULL) 179373143b9aSmrg return (0); 179473143b9aSmrg 179573143b9aSmrg scount = 0; 179673143b9aSmrg while (hostp->h_addr_list[scount] && scount <= 8) 179773143b9aSmrg { 179873143b9aSmrg /* 179973143b9aSmrg * The 2nd call to gethostname() overrides the data 180073143b9aSmrg * from the 1st call, so we must save the address list. 180173143b9aSmrg */ 180273143b9aSmrg 1803fe567363Smrg specified_local_addr_list[scount][0] = 180473143b9aSmrg hostp->h_addr_list[scount][0]; 1805fe567363Smrg specified_local_addr_list[scount][1] = 180673143b9aSmrg hostp->h_addr_list[scount][1]; 1807fe567363Smrg specified_local_addr_list[scount][2] = 180873143b9aSmrg hostp->h_addr_list[scount][2]; 1809fe567363Smrg specified_local_addr_list[scount][3] = 181073143b9aSmrg hostp->h_addr_list[scount][3]; 181173143b9aSmrg scount++; 181273143b9aSmrg } 181373143b9aSmrg if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) 181473143b9aSmrg return (0); 181573143b9aSmrg 181673143b9aSmrg equiv = 0; 181773143b9aSmrg i = 0; 181873143b9aSmrg 181973143b9aSmrg while (i < scount && !equiv) 182073143b9aSmrg { 182173143b9aSmrg j = 0; 182273143b9aSmrg 182373143b9aSmrg while (hostp->h_addr_list[j]) 182473143b9aSmrg { 1825fe567363Smrg if ((specified_local_addr_list[i][0] == 182673143b9aSmrg hostp->h_addr_list[j][0]) && 1827fe567363Smrg (specified_local_addr_list[i][1] == 182873143b9aSmrg hostp->h_addr_list[j][1]) && 1829fe567363Smrg (specified_local_addr_list[i][2] == 183073143b9aSmrg hostp->h_addr_list[j][2]) && 1831fe567363Smrg (specified_local_addr_list[i][3] == 183273143b9aSmrg hostp->h_addr_list[j][3])) 183373143b9aSmrg { 183473143b9aSmrg /* They're equal, so we're done */ 1835fe567363Smrg 183673143b9aSmrg equiv = 1; 183773143b9aSmrg break; 183873143b9aSmrg } 183973143b9aSmrg 184073143b9aSmrg j++; 184173143b9aSmrg } 184273143b9aSmrg 184373143b9aSmrg i++; 184473143b9aSmrg } 184573143b9aSmrg return (equiv); 1846b53e5eeaSmrg#endif 184773143b9aSmrg } 184873143b9aSmrg} 184973143b9aSmrg 185073143b9aSmrgstatic int 18516a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, 18526a3641a6Ssnj const char *host, const char *port) 185373143b9aSmrg 185473143b9aSmrg{ 185573143b9aSmrg struct sockaddr_un sockname; 185673143b9aSmrg SOCKLEN_T namelen; 185773143b9aSmrg 1858fe567363Smrg prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); 1859fe567363Smrg 186073143b9aSmrg /* 186173143b9aSmrg * Make sure 'host' is really local. If not, we return failure. 186273143b9aSmrg * The reason we make this check is because a process may advertise 186373143b9aSmrg * a "local" network ID for which it can accept connections, but if 186473143b9aSmrg * a process on a remote machine tries to connect to this network ID, 186573143b9aSmrg * we know for sure it will fail. 186673143b9aSmrg */ 186773143b9aSmrg 186873143b9aSmrg if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) 186973143b9aSmrg { 1870fe567363Smrg prmsg (1, 187173143b9aSmrg "SocketUNIXConnect: Cannot connect to non-local host %s\n", 1872fe567363Smrg host); 187373143b9aSmrg return TRANS_CONNECT_FAILED; 187473143b9aSmrg } 187573143b9aSmrg 187673143b9aSmrg 187773143b9aSmrg /* 187873143b9aSmrg * Check the port. 187973143b9aSmrg */ 188073143b9aSmrg 188173143b9aSmrg if (!port || !*port) 188273143b9aSmrg { 1883fe567363Smrg prmsg (1,"SocketUNIXConnect: Missing port specification\n"); 188473143b9aSmrg return TRANS_CONNECT_FAILED; 188573143b9aSmrg } 188673143b9aSmrg 188773143b9aSmrg /* 188873143b9aSmrg * Build the socket name. 188973143b9aSmrg */ 1890fe567363Smrg 189173143b9aSmrg sockname.sun_family = AF_UNIX; 189273143b9aSmrg 1893a773ec55Smrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, 0) != 0) { 1894fe567363Smrg prmsg (1, "SocketUNIXConnect: path too long\n"); 189573143b9aSmrg return TRANS_CONNECT_FAILED; 189673143b9aSmrg } 189773143b9aSmrg 1898a773ec55Smrg#if defined(BSD44SOCKETS) 189973143b9aSmrg sockname.sun_len = strlen (sockname.sun_path); 190073143b9aSmrg#endif 190173143b9aSmrg 190273143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 190373143b9aSmrg namelen = SUN_LEN (&sockname); 190473143b9aSmrg#else 190573143b9aSmrg namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 190673143b9aSmrg#endif 190773143b9aSmrg 190873143b9aSmrg 190973143b9aSmrg /* 191073143b9aSmrg * Do the connect() 191173143b9aSmrg */ 191273143b9aSmrg 191373143b9aSmrg if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) 191473143b9aSmrg { 191573143b9aSmrg int olderrno = errno; 191673143b9aSmrg int connected = 0; 1917fe567363Smrg 191873143b9aSmrg if (!connected) 191973143b9aSmrg { 192073143b9aSmrg errno = olderrno; 1921fe567363Smrg 192273143b9aSmrg /* 192373143b9aSmrg * If the error was ENOENT, the server may be starting up; we used 192473143b9aSmrg * to suggest to try again in this case with 192573143b9aSmrg * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for 192673143b9aSmrg * processes still referencing stale sockets in their environment. 192773143b9aSmrg * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it 192873143b9aSmrg * is suggested that higher level stacks handle retries on their 192973143b9aSmrg * level when they face a slow starting server. 193073143b9aSmrg * 193173143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 193273143b9aSmrg * was non-blocking and we should poll using select 193373143b9aSmrg * 193473143b9aSmrg * If the error was EINTR, the connect was interrupted and we 193573143b9aSmrg * should try again. 193673143b9aSmrg */ 193773143b9aSmrg 193873143b9aSmrg if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 193973143b9aSmrg return TRANS_IN_PROGRESS; 194073143b9aSmrg else if (olderrno == EINTR) 194173143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 1942a773ec55Smrg else { 1943fe567363Smrg prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n", 1944fe567363Smrg EGET()); 194573143b9aSmrg 194673143b9aSmrg return TRANS_CONNECT_FAILED; 194773143b9aSmrg } 194873143b9aSmrg } 194973143b9aSmrg } 195073143b9aSmrg 195173143b9aSmrg /* 195273143b9aSmrg * Get the socket name and the peer name from the connect socket, 195373143b9aSmrg * since this is unix domain. 195473143b9aSmrg */ 195573143b9aSmrg 1956fe567363Smrg if ((ciptr->addr = malloc(namelen)) == NULL || 1957fe567363Smrg (ciptr->peeraddr = malloc(namelen)) == NULL) 195873143b9aSmrg { 1959fe567363Smrg prmsg (1, 1960fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 196173143b9aSmrg return TRANS_CONNECT_FAILED; 196273143b9aSmrg } 196373143b9aSmrg 196473143b9aSmrg ciptr->family = AF_UNIX; 196573143b9aSmrg ciptr->addrlen = namelen; 196673143b9aSmrg ciptr->peeraddrlen = namelen; 196773143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 196873143b9aSmrg memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); 196973143b9aSmrg 197073143b9aSmrg return 0; 197173143b9aSmrg} 197273143b9aSmrg 197373143b9aSmrg#endif /* UNIXCONN */ 197473143b9aSmrg 197573143b9aSmrg#endif /* TRANS_CLIENT */ 197673143b9aSmrg 197773143b9aSmrg 197873143b9aSmrgstatic int 197973143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 198073143b9aSmrg 198173143b9aSmrg{ 1982fe567363Smrg prmsg (2,"SocketBytesReadable(%p,%d,%p)\n", 1983ac57ed83Smrg (void *) ciptr, ciptr->fd, (void *) pend); 198473143b9aSmrg#ifdef WIN32 198573143b9aSmrg { 198673143b9aSmrg int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); 198773143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 198873143b9aSmrg return ret; 198973143b9aSmrg } 199073143b9aSmrg#else 199173143b9aSmrg return ioctl (ciptr->fd, FIONREAD, (char *) pend); 199273143b9aSmrg#endif /* WIN32 */ 199373143b9aSmrg} 199473143b9aSmrg 199575ebec6dSmrg#if XTRANS_SEND_FDS 199675ebec6dSmrg 199775ebec6dSmrgstatic void 199875ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close) 199975ebec6dSmrg{ 200075ebec6dSmrg struct _XtransConnFd *cf, *new; 200175ebec6dSmrg 200275ebec6dSmrg new = malloc (sizeof (struct _XtransConnFd)); 200375ebec6dSmrg if (!new) { 200475ebec6dSmrg /* XXX mark connection as broken */ 200575ebec6dSmrg close(fd); 200675ebec6dSmrg return; 200775ebec6dSmrg } 200875ebec6dSmrg new->next = 0; 200975ebec6dSmrg new->fd = fd; 201075ebec6dSmrg new->do_close = do_close; 201175ebec6dSmrg /* search to end of list */ 201275ebec6dSmrg for (; (cf = *prev); prev = &(cf->next)); 201375ebec6dSmrg *prev = new; 201475ebec6dSmrg} 201573143b9aSmrg 201673143b9aSmrgstatic int 201775ebec6dSmrgremoveFd(struct _XtransConnFd **prev) 201875ebec6dSmrg{ 201975ebec6dSmrg struct _XtransConnFd *cf; 202075ebec6dSmrg int fd; 202175ebec6dSmrg 202275ebec6dSmrg if ((cf = *prev)) { 202375ebec6dSmrg *prev = cf->next; 202475ebec6dSmrg fd = cf->fd; 202575ebec6dSmrg free(cf); 202675ebec6dSmrg } else 202775ebec6dSmrg fd = -1; 202875ebec6dSmrg return fd; 202975ebec6dSmrg} 203073143b9aSmrg 203175ebec6dSmrgstatic void 203275ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) 203373143b9aSmrg{ 203475ebec6dSmrg struct _XtransConnFd *cf, *next; 203573143b9aSmrg 203675ebec6dSmrg for (cf = *prev; cf != upto; cf = next) { 203775ebec6dSmrg next = cf->next; 203875ebec6dSmrg if (do_close || cf->do_close) 203975ebec6dSmrg close(cf->fd); 204075ebec6dSmrg free(cf); 204173143b9aSmrg } 204275ebec6dSmrg *prev = upto; 204373143b9aSmrg} 204473143b9aSmrg 204575ebec6dSmrgstatic void 204675ebec6dSmrgcleanupFds(XtransConnInfo ciptr) 204775ebec6dSmrg{ 204875ebec6dSmrg /* Clean up the send list but don't close the fds */ 204975ebec6dSmrg discardFd(&ciptr->send_fds, NULL, 0); 205075ebec6dSmrg /* Clean up the recv list and *do* close the fds */ 205175ebec6dSmrg discardFd(&ciptr->recv_fds, NULL, 1); 205275ebec6dSmrg} 205373143b9aSmrg 205473143b9aSmrgstatic int 205575ebec6dSmrgnFd(struct _XtransConnFd **prev) 205675ebec6dSmrg{ 205775ebec6dSmrg struct _XtransConnFd *cf; 205875ebec6dSmrg int n = 0; 205975ebec6dSmrg 206075ebec6dSmrg for (cf = *prev; cf; cf = cf->next) 206175ebec6dSmrg n++; 206275ebec6dSmrg return n; 206375ebec6dSmrg} 206473143b9aSmrg 206575ebec6dSmrgstatic int 206675ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr) 206773143b9aSmrg{ 206875ebec6dSmrg prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); 206975ebec6dSmrg return removeFd(&ciptr->recv_fds); 207075ebec6dSmrg} 207175ebec6dSmrg 207275ebec6dSmrgstatic int 207375ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) 207475ebec6dSmrg{ 207575ebec6dSmrg appendFd(&ciptr->send_fds, fd, do_close); 207675ebec6dSmrg return 0; 207775ebec6dSmrg} 207875ebec6dSmrg 207975ebec6dSmrgstatic int 208075ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) 208175ebec6dSmrg{ 208275ebec6dSmrg errno = EINVAL; 208375ebec6dSmrg return -1; 208475ebec6dSmrg} 208575ebec6dSmrg 208675ebec6dSmrgstatic int 208775ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) 208875ebec6dSmrg{ 208975ebec6dSmrg errno = EINVAL; 209075ebec6dSmrg return -1; 209175ebec6dSmrg} 209275ebec6dSmrg 209375ebec6dSmrg#define MAX_FDS 128 209475ebec6dSmrg 209575ebec6dSmrgunion fd_pass { 209675ebec6dSmrg struct cmsghdr cmsghdr; 209775ebec6dSmrg char buf[CMSG_SPACE(MAX_FDS * sizeof(int))]; 209875ebec6dSmrg}; 209975ebec6dSmrg 210075ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 210175ebec6dSmrg 210275ebec6dSmrgstatic int 210375ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) 210475ebec6dSmrg 210575ebec6dSmrg{ 2106ac57ed83Smrg prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, (void *) buf, size); 210773143b9aSmrg 2108fe567363Smrg#if defined(WIN32) 210973143b9aSmrg { 211075ebec6dSmrg int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); 211173143b9aSmrg#ifdef WIN32 211273143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 211373143b9aSmrg#endif 211473143b9aSmrg return ret; 211573143b9aSmrg } 211673143b9aSmrg#else 211775ebec6dSmrg#if XTRANS_SEND_FDS 211875ebec6dSmrg { 211975ebec6dSmrg struct iovec iov = { 212075ebec6dSmrg .iov_base = buf, 212175ebec6dSmrg .iov_len = size 212275ebec6dSmrg }; 212375ebec6dSmrg union fd_pass cmsgbuf; 212475ebec6dSmrg struct msghdr msg = { 212575ebec6dSmrg .msg_name = NULL, 212675ebec6dSmrg .msg_namelen = 0, 212775ebec6dSmrg .msg_iov = &iov, 212875ebec6dSmrg .msg_iovlen = 1, 212975ebec6dSmrg .msg_control = cmsgbuf.buf, 213075ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 213175ebec6dSmrg }; 213275ebec6dSmrg 213375ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 213475ebec6dSmrg if (size >= 0) { 213575ebec6dSmrg struct cmsghdr *hdr; 213675ebec6dSmrg 213775ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 213875ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 213975ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 214075ebec6dSmrg int i; 214175ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 214275ebec6dSmrg 214375ebec6dSmrg for (i = 0; i < nfd; i++) 214475ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 214575ebec6dSmrg } 214675ebec6dSmrg } 214775ebec6dSmrg } 214875ebec6dSmrg return size; 214975ebec6dSmrg } 215075ebec6dSmrg#else 215175ebec6dSmrg return read(ciptr->fd, buf, size); 215275ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 215373143b9aSmrg#endif /* WIN32 */ 215473143b9aSmrg} 215573143b9aSmrg 215673143b9aSmrgstatic int 215773143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) 215873143b9aSmrg 215973143b9aSmrg{ 2160ac57ed83Smrg prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, (void *) buf, size); 216173143b9aSmrg 216275ebec6dSmrg#if XTRANS_SEND_FDS 216375ebec6dSmrg { 216475ebec6dSmrg union fd_pass cmsgbuf; 216575ebec6dSmrg struct msghdr msg = { 216675ebec6dSmrg .msg_name = NULL, 216775ebec6dSmrg .msg_namelen = 0, 216875ebec6dSmrg .msg_iov = buf, 216975ebec6dSmrg .msg_iovlen = size, 217075ebec6dSmrg .msg_control = cmsgbuf.buf, 217175ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 217275ebec6dSmrg }; 217375ebec6dSmrg 217475ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 217575ebec6dSmrg if (size >= 0) { 217675ebec6dSmrg struct cmsghdr *hdr; 217775ebec6dSmrg 217875ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 217975ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 218075ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 218175ebec6dSmrg int i; 218275ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 218375ebec6dSmrg 218475ebec6dSmrg for (i = 0; i < nfd; i++) 218575ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 218675ebec6dSmrg } 218775ebec6dSmrg } 218875ebec6dSmrg } 218975ebec6dSmrg return size; 219075ebec6dSmrg } 219175ebec6dSmrg#else 219273143b9aSmrg return READV (ciptr, buf, size); 219375ebec6dSmrg#endif 219473143b9aSmrg} 219573143b9aSmrg 219673143b9aSmrg 219773143b9aSmrgstatic int 219873143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) 219973143b9aSmrg 220073143b9aSmrg{ 2201ac57ed83Smrg prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, (void *) buf, size); 220273143b9aSmrg 220375ebec6dSmrg#if XTRANS_SEND_FDS 220475ebec6dSmrg if (ciptr->send_fds) 220575ebec6dSmrg { 220675ebec6dSmrg union fd_pass cmsgbuf; 220775ebec6dSmrg int nfd = nFd(&ciptr->send_fds); 220875ebec6dSmrg struct _XtransConnFd *cf = ciptr->send_fds; 220975ebec6dSmrg struct msghdr msg = { 221075ebec6dSmrg .msg_name = NULL, 221175ebec6dSmrg .msg_namelen = 0, 221275ebec6dSmrg .msg_iov = buf, 221375ebec6dSmrg .msg_iovlen = size, 221475ebec6dSmrg .msg_control = cmsgbuf.buf, 221575ebec6dSmrg .msg_controllen = CMSG_LEN(nfd * sizeof(int)) 221675ebec6dSmrg }; 221775ebec6dSmrg struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 221875ebec6dSmrg int i; 221975ebec6dSmrg int *fds; 222075ebec6dSmrg 222175ebec6dSmrg hdr->cmsg_len = msg.msg_controllen; 222275ebec6dSmrg hdr->cmsg_level = SOL_SOCKET; 222375ebec6dSmrg hdr->cmsg_type = SCM_RIGHTS; 222475ebec6dSmrg 222575ebec6dSmrg fds = (int *) CMSG_DATA(hdr); 222675ebec6dSmrg /* Set up fds */ 222775ebec6dSmrg for (i = 0; i < nfd; i++) { 222875ebec6dSmrg fds[i] = cf->fd; 222975ebec6dSmrg cf = cf->next; 223075ebec6dSmrg } 223175ebec6dSmrg 223275ebec6dSmrg i = sendmsg(ciptr->fd, &msg, 0); 223375ebec6dSmrg if (i > 0) 223475ebec6dSmrg discardFd(&ciptr->send_fds, cf, 0); 223575ebec6dSmrg return i; 223675ebec6dSmrg } 223775ebec6dSmrg#endif 223873143b9aSmrg return WRITEV (ciptr, buf, size); 223973143b9aSmrg} 224073143b9aSmrg 224173143b9aSmrg 224275ebec6dSmrgstatic int 2243ac57ed83SmrgTRANS(SocketWrite) (XtransConnInfo ciptr, const char *buf, int size) 224475ebec6dSmrg 224575ebec6dSmrg{ 2246ac57ed83Smrg prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, (const void *) buf, size); 224775ebec6dSmrg 224875ebec6dSmrg#if defined(WIN32) 224975ebec6dSmrg { 225075ebec6dSmrg int ret = send ((SOCKET)ciptr->fd, buf, size, 0); 225175ebec6dSmrg#ifdef WIN32 225275ebec6dSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 225375ebec6dSmrg#endif 225475ebec6dSmrg return ret; 225575ebec6dSmrg } 225675ebec6dSmrg#else 225775ebec6dSmrg#if XTRANS_SEND_FDS 225875ebec6dSmrg if (ciptr->send_fds) 225975ebec6dSmrg { 226075ebec6dSmrg struct iovec iov; 226175ebec6dSmrg 2262ac57ed83Smrg iov.iov_base = (void *) buf; 226375ebec6dSmrg iov.iov_len = size; 226475ebec6dSmrg return TRANS(SocketWritev)(ciptr, &iov, 1); 226575ebec6dSmrg } 226675ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 226775ebec6dSmrg return write (ciptr->fd, buf, size); 226875ebec6dSmrg#endif /* WIN32 */ 226975ebec6dSmrg} 227075ebec6dSmrg 227173143b9aSmrgstatic int 227273143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr) 227373143b9aSmrg 227473143b9aSmrg{ 2275ac57ed83Smrg prmsg (2,"SocketDisconnect(%p,%d)\n", (void *) ciptr, ciptr->fd); 227673143b9aSmrg 227773143b9aSmrg#ifdef WIN32 2278fe567363Smrg { 227973143b9aSmrg int ret = shutdown (ciptr->fd, 2); 228073143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 228173143b9aSmrg return ret; 228273143b9aSmrg } 228373143b9aSmrg#else 228473143b9aSmrg return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ 228573143b9aSmrg#endif 228673143b9aSmrg} 228773143b9aSmrg 228873143b9aSmrg 228973143b9aSmrg#ifdef TCPCONN 229073143b9aSmrgstatic int 229173143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr) 229273143b9aSmrg 229373143b9aSmrg{ 2294ac57ed83Smrg prmsg (2,"SocketINETClose(%p,%d)\n", (void *) ciptr, ciptr->fd); 229573143b9aSmrg 229673143b9aSmrg#ifdef WIN32 229773143b9aSmrg { 229873143b9aSmrg int ret = close (ciptr->fd); 229973143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 230073143b9aSmrg return ret; 230173143b9aSmrg } 230273143b9aSmrg#else 230373143b9aSmrg return close (ciptr->fd); 230473143b9aSmrg#endif 230573143b9aSmrg} 230673143b9aSmrg 230773143b9aSmrg#endif /* TCPCONN */ 230873143b9aSmrg 230973143b9aSmrg 231073143b9aSmrg#ifdef UNIXCONN 231173143b9aSmrgstatic int 231273143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr) 231373143b9aSmrg{ 231473143b9aSmrg /* 231573143b9aSmrg * If this is the server side, then once the socket is closed, 231673143b9aSmrg * it must be unlinked to completely close it 231773143b9aSmrg */ 231873143b9aSmrg 231973143b9aSmrg struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; 232073143b9aSmrg int ret; 232173143b9aSmrg 2322ac57ed83Smrg prmsg (2,"SocketUNIXClose(%p,%d)\n", (void *) ciptr, ciptr->fd); 232373143b9aSmrg 232475ebec6dSmrg#if XTRANS_SEND_FDS 232575ebec6dSmrg cleanupFds(ciptr); 232675ebec6dSmrg#endif 232773143b9aSmrg ret = close(ciptr->fd); 232873143b9aSmrg 232973143b9aSmrg if (ciptr->flags 233073143b9aSmrg && sockname 233173143b9aSmrg && sockname->sun_family == AF_UNIX 233273143b9aSmrg && sockname->sun_path[0]) 233373143b9aSmrg { 233473143b9aSmrg if (!(ciptr->flags & TRANS_NOUNLINK 233573143b9aSmrg || ciptr->transptr->flags & TRANS_ABSTRACT)) 233673143b9aSmrg unlink (sockname->sun_path); 233773143b9aSmrg } 233873143b9aSmrg 233973143b9aSmrg return ret; 234073143b9aSmrg} 234173143b9aSmrg 234273143b9aSmrgstatic int 234373143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) 234473143b9aSmrg 234573143b9aSmrg{ 234673143b9aSmrg /* 234773143b9aSmrg * Don't unlink path. 234873143b9aSmrg */ 234973143b9aSmrg 235073143b9aSmrg int ret; 235173143b9aSmrg 2352fe567363Smrg prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", 2353ac57ed83Smrg (void *) ciptr, ciptr->fd); 235473143b9aSmrg 235575ebec6dSmrg#if XTRANS_SEND_FDS 235675ebec6dSmrg cleanupFds(ciptr); 235775ebec6dSmrg#endif 235873143b9aSmrg ret = close(ciptr->fd); 235973143b9aSmrg 236073143b9aSmrg return ret; 236173143b9aSmrg} 236273143b9aSmrg 236373143b9aSmrg#endif /* UNIXCONN */ 236473143b9aSmrg 236573143b9aSmrg 236673143b9aSmrg#ifdef TCPCONN 236773143b9aSmrg# ifdef TRANS_SERVER 2368fe567363Smrgstatic const char* tcp_nolisten[] = { 236973143b9aSmrg "inet", 2370ac57ed83Smrg#ifdef IPv6 237173143b9aSmrg "inet6", 237273143b9aSmrg#endif 237373143b9aSmrg NULL 237473143b9aSmrg}; 237573143b9aSmrg# endif 237673143b9aSmrg 2377ac57ed83Smrgstatic Xtransport TRANS(SocketTCPFuncs) = { 237873143b9aSmrg /* Socket Interface */ 237973143b9aSmrg "tcp", 238073143b9aSmrg TRANS_ALIAS, 238173143b9aSmrg#ifdef TRANS_CLIENT 238273143b9aSmrg TRANS(SocketOpenCOTSClient), 238373143b9aSmrg#endif /* TRANS_CLIENT */ 238473143b9aSmrg#ifdef TRANS_SERVER 238573143b9aSmrg tcp_nolisten, 238673143b9aSmrg TRANS(SocketOpenCOTSServer), 238773143b9aSmrg#endif /* TRANS_SERVER */ 238873143b9aSmrg#ifdef TRANS_REOPEN 238973143b9aSmrg TRANS(SocketReopenCOTSServer), 239073143b9aSmrg#endif 239173143b9aSmrg TRANS(SocketSetOption), 239273143b9aSmrg#ifdef TRANS_SERVER 239373143b9aSmrg TRANS(SocketINETCreateListener), 239473143b9aSmrg NULL, /* ResetListener */ 239573143b9aSmrg TRANS(SocketINETAccept), 239673143b9aSmrg#endif /* TRANS_SERVER */ 239773143b9aSmrg#ifdef TRANS_CLIENT 239873143b9aSmrg TRANS(SocketINETConnect), 239973143b9aSmrg#endif /* TRANS_CLIENT */ 240073143b9aSmrg TRANS(SocketBytesReadable), 240173143b9aSmrg TRANS(SocketRead), 240273143b9aSmrg TRANS(SocketWrite), 240373143b9aSmrg TRANS(SocketReadv), 240473143b9aSmrg TRANS(SocketWritev), 240575ebec6dSmrg#if XTRANS_SEND_FDS 240675ebec6dSmrg TRANS(SocketSendFdInvalid), 240775ebec6dSmrg TRANS(SocketRecvFdInvalid), 240875ebec6dSmrg#endif 240973143b9aSmrg TRANS(SocketDisconnect), 241073143b9aSmrg TRANS(SocketINETClose), 241173143b9aSmrg TRANS(SocketINETClose), 241273143b9aSmrg }; 241373143b9aSmrg 2414ac57ed83Smrgstatic Xtransport TRANS(SocketINETFuncs) = { 241573143b9aSmrg /* Socket Interface */ 241673143b9aSmrg "inet", 241773143b9aSmrg 0, 241873143b9aSmrg#ifdef TRANS_CLIENT 241973143b9aSmrg TRANS(SocketOpenCOTSClient), 242073143b9aSmrg#endif /* TRANS_CLIENT */ 242173143b9aSmrg#ifdef TRANS_SERVER 242273143b9aSmrg NULL, 242373143b9aSmrg TRANS(SocketOpenCOTSServer), 242473143b9aSmrg#endif /* TRANS_SERVER */ 242573143b9aSmrg#ifdef TRANS_REOPEN 242673143b9aSmrg TRANS(SocketReopenCOTSServer), 242773143b9aSmrg#endif 242873143b9aSmrg TRANS(SocketSetOption), 242973143b9aSmrg#ifdef TRANS_SERVER 243073143b9aSmrg TRANS(SocketINETCreateListener), 243173143b9aSmrg NULL, /* ResetListener */ 243273143b9aSmrg TRANS(SocketINETAccept), 243373143b9aSmrg#endif /* TRANS_SERVER */ 243473143b9aSmrg#ifdef TRANS_CLIENT 243573143b9aSmrg TRANS(SocketINETConnect), 243673143b9aSmrg#endif /* TRANS_CLIENT */ 243773143b9aSmrg TRANS(SocketBytesReadable), 243873143b9aSmrg TRANS(SocketRead), 243973143b9aSmrg TRANS(SocketWrite), 244073143b9aSmrg TRANS(SocketReadv), 244173143b9aSmrg TRANS(SocketWritev), 244275ebec6dSmrg#if XTRANS_SEND_FDS 244375ebec6dSmrg TRANS(SocketSendFdInvalid), 244475ebec6dSmrg TRANS(SocketRecvFdInvalid), 244575ebec6dSmrg#endif 244673143b9aSmrg TRANS(SocketDisconnect), 244773143b9aSmrg TRANS(SocketINETClose), 244873143b9aSmrg TRANS(SocketINETClose), 244973143b9aSmrg }; 245073143b9aSmrg 2451ac57ed83Smrg#ifdef IPv6 2452ac57ed83Smrgstatic Xtransport TRANS(SocketINET6Funcs) = { 245373143b9aSmrg /* Socket Interface */ 245473143b9aSmrg "inet6", 245573143b9aSmrg 0, 245673143b9aSmrg#ifdef TRANS_CLIENT 245773143b9aSmrg TRANS(SocketOpenCOTSClient), 245873143b9aSmrg#endif /* TRANS_CLIENT */ 245973143b9aSmrg#ifdef TRANS_SERVER 246073143b9aSmrg NULL, 246173143b9aSmrg TRANS(SocketOpenCOTSServer), 246273143b9aSmrg#endif /* TRANS_SERVER */ 246373143b9aSmrg#ifdef TRANS_REOPEN 246473143b9aSmrg TRANS(SocketReopenCOTSServer), 246573143b9aSmrg#endif 246673143b9aSmrg TRANS(SocketSetOption), 246773143b9aSmrg#ifdef TRANS_SERVER 246873143b9aSmrg TRANS(SocketINETCreateListener), 246973143b9aSmrg NULL, /* ResetListener */ 247073143b9aSmrg TRANS(SocketINETAccept), 247173143b9aSmrg#endif /* TRANS_SERVER */ 247273143b9aSmrg#ifdef TRANS_CLIENT 247373143b9aSmrg TRANS(SocketINETConnect), 247473143b9aSmrg#endif /* TRANS_CLIENT */ 247573143b9aSmrg TRANS(SocketBytesReadable), 247673143b9aSmrg TRANS(SocketRead), 247773143b9aSmrg TRANS(SocketWrite), 247873143b9aSmrg TRANS(SocketReadv), 247973143b9aSmrg TRANS(SocketWritev), 248075ebec6dSmrg#if XTRANS_SEND_FDS 248175ebec6dSmrg TRANS(SocketSendFdInvalid), 248275ebec6dSmrg TRANS(SocketRecvFdInvalid), 248375ebec6dSmrg#endif 248473143b9aSmrg TRANS(SocketDisconnect), 248573143b9aSmrg TRANS(SocketINETClose), 248673143b9aSmrg TRANS(SocketINETClose), 248773143b9aSmrg }; 248873143b9aSmrg#endif /* IPv6 */ 248973143b9aSmrg#endif /* TCPCONN */ 249073143b9aSmrg 249173143b9aSmrg#ifdef UNIXCONN 249273143b9aSmrg#if !defined(LOCALCONN) 2493ac57ed83Smrgstatic Xtransport TRANS(SocketLocalFuncs) = { 249473143b9aSmrg /* Socket Interface */ 249573143b9aSmrg "local", 249673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 249773143b9aSmrg TRANS_ABSTRACT, 249873143b9aSmrg#else 249973143b9aSmrg 0, 250073143b9aSmrg#endif 250173143b9aSmrg#ifdef TRANS_CLIENT 250273143b9aSmrg TRANS(SocketOpenCOTSClient), 250373143b9aSmrg#endif /* TRANS_CLIENT */ 250473143b9aSmrg#ifdef TRANS_SERVER 250573143b9aSmrg NULL, 250673143b9aSmrg TRANS(SocketOpenCOTSServer), 250773143b9aSmrg#endif /* TRANS_SERVER */ 250873143b9aSmrg#ifdef TRANS_REOPEN 250973143b9aSmrg TRANS(SocketReopenCOTSServer), 251073143b9aSmrg#endif 251173143b9aSmrg TRANS(SocketSetOption), 251273143b9aSmrg#ifdef TRANS_SERVER 251373143b9aSmrg TRANS(SocketUNIXCreateListener), 251473143b9aSmrg TRANS(SocketUNIXResetListener), 251573143b9aSmrg TRANS(SocketUNIXAccept), 251673143b9aSmrg#endif /* TRANS_SERVER */ 251773143b9aSmrg#ifdef TRANS_CLIENT 251873143b9aSmrg TRANS(SocketUNIXConnect), 251973143b9aSmrg#endif /* TRANS_CLIENT */ 252073143b9aSmrg TRANS(SocketBytesReadable), 252173143b9aSmrg TRANS(SocketRead), 252273143b9aSmrg TRANS(SocketWrite), 252373143b9aSmrg TRANS(SocketReadv), 252473143b9aSmrg TRANS(SocketWritev), 252575ebec6dSmrg#if XTRANS_SEND_FDS 252675ebec6dSmrg TRANS(SocketSendFd), 252775ebec6dSmrg TRANS(SocketRecvFd), 252875ebec6dSmrg#endif 252973143b9aSmrg TRANS(SocketDisconnect), 253073143b9aSmrg TRANS(SocketUNIXClose), 253173143b9aSmrg TRANS(SocketUNIXCloseForCloning), 253273143b9aSmrg }; 253373143b9aSmrg#endif /* !LOCALCONN */ 253473143b9aSmrg# ifdef TRANS_SERVER 253573143b9aSmrg# if !defined(LOCALCONN) 253675ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL }; 253773143b9aSmrg# endif 253873143b9aSmrg# endif 2539fe567363Smrg 2540ac57ed83Smrgstatic Xtransport TRANS(SocketUNIXFuncs) = { 254173143b9aSmrg /* Socket Interface */ 254273143b9aSmrg "unix", 254373143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS) 254473143b9aSmrg TRANS_ALIAS, 254573143b9aSmrg#else 254673143b9aSmrg 0, 254773143b9aSmrg#endif 254873143b9aSmrg#ifdef TRANS_CLIENT 254973143b9aSmrg TRANS(SocketOpenCOTSClient), 255073143b9aSmrg#endif /* TRANS_CLIENT */ 255173143b9aSmrg#ifdef TRANS_SERVER 255273143b9aSmrg#if !defined(LOCALCONN) 255373143b9aSmrg unix_nolisten, 255473143b9aSmrg#else 255573143b9aSmrg NULL, 255673143b9aSmrg#endif 255773143b9aSmrg TRANS(SocketOpenCOTSServer), 255873143b9aSmrg#endif /* TRANS_SERVER */ 255973143b9aSmrg#ifdef TRANS_REOPEN 256073143b9aSmrg TRANS(SocketReopenCOTSServer), 256173143b9aSmrg#endif 256273143b9aSmrg TRANS(SocketSetOption), 256373143b9aSmrg#ifdef TRANS_SERVER 256473143b9aSmrg TRANS(SocketUNIXCreateListener), 256573143b9aSmrg TRANS(SocketUNIXResetListener), 256673143b9aSmrg TRANS(SocketUNIXAccept), 256773143b9aSmrg#endif /* TRANS_SERVER */ 256873143b9aSmrg#ifdef TRANS_CLIENT 256973143b9aSmrg TRANS(SocketUNIXConnect), 257073143b9aSmrg#endif /* TRANS_CLIENT */ 257173143b9aSmrg TRANS(SocketBytesReadable), 257273143b9aSmrg TRANS(SocketRead), 257373143b9aSmrg TRANS(SocketWrite), 257473143b9aSmrg TRANS(SocketReadv), 257573143b9aSmrg TRANS(SocketWritev), 257675ebec6dSmrg#if XTRANS_SEND_FDS 257775ebec6dSmrg TRANS(SocketSendFd), 257875ebec6dSmrg TRANS(SocketRecvFd), 257975ebec6dSmrg#endif 258073143b9aSmrg TRANS(SocketDisconnect), 258173143b9aSmrg TRANS(SocketUNIXClose), 258273143b9aSmrg TRANS(SocketUNIXCloseForCloning), 258373143b9aSmrg }; 258473143b9aSmrg 258573143b9aSmrg#endif /* UNIXCONN */ 2586