Xtranssock.c revision a773ec55
1af928962Smrg/* 2a773ec55Smrg * Copyright (c) 2002, Oracle and/or its affiliates. 3af928962Smrg * 4af928962Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5af928962Smrg * copy of this software and associated documentation files (the "Software"), 6af928962Smrg * to deal in the Software without restriction, including without limitation 7af928962Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af928962Smrg * and/or sell copies of the Software, and to permit persons to whom the 9af928962Smrg * Software is furnished to do so, subject to the following conditions: 10af928962Smrg * 11af928962Smrg * The above copyright notice and this permission notice (including the next 12af928962Smrg * paragraph) shall be included in all copies or substantial portions of the 13af928962Smrg * Software. 14af928962Smrg * 15af928962Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af928962Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af928962Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af928962Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af928962Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20af928962Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21af928962Smrg * DEALINGS IN THE SOFTWARE. 22af928962Smrg */ 2373143b9aSmrg/* 2473143b9aSmrg 2573143b9aSmrgCopyright 1993, 1994, 1998 The Open Group 2673143b9aSmrg 2773143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its 2873143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that 2973143b9aSmrgthe above copyright notice appear in all copies and that both that 3073143b9aSmrgcopyright notice and this permission notice appear in supporting 3173143b9aSmrgdocumentation. 3273143b9aSmrg 3373143b9aSmrgThe above copyright notice and this permission notice shall be included 3473143b9aSmrgin all copies or substantial portions of the Software. 3573143b9aSmrg 3673143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 3773143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3873143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 3973143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 4073143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 4173143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 4273143b9aSmrgOTHER DEALINGS IN THE SOFTWARE. 4373143b9aSmrg 4473143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall 4573143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or 4673143b9aSmrgother dealings in this Software without prior written authorization 4773143b9aSmrgfrom the copyright holders. 4873143b9aSmrg 4973143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA 5073143b9aSmrg * 5173143b9aSmrg * All Rights Reserved 5273143b9aSmrg * 5373143b9aSmrg * Permission to use, copy, modify, and distribute this software and its 5473143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided 5573143b9aSmrg * that the above copyright notice appear in all copies and that both that 5673143b9aSmrg * copyright notice and this permission notice appear in supporting 5773143b9aSmrg * documentation, and that the name NCR not be used in advertising 5873143b9aSmrg * or publicity pertaining to distribution of the software without specific, 5973143b9aSmrg * written prior permission. NCR makes no representations about the 6073143b9aSmrg * suitability of this software for any purpose. It is provided "as is" 6173143b9aSmrg * without express or implied warranty. 6273143b9aSmrg * 6373143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 6473143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 6573143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR 6673143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 6773143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 6873143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 6973143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 7073143b9aSmrg */ 7173143b9aSmrg 7273143b9aSmrg#include <ctype.h> 7373143b9aSmrg#ifdef XTHREADS 7473143b9aSmrg#include <X11/Xthreads.h> 7573143b9aSmrg#endif 7673143b9aSmrg 7773143b9aSmrg#ifndef WIN32 7873143b9aSmrg 7973143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8073143b9aSmrg#include <sys/socket.h> 8173143b9aSmrg#include <netinet/in.h> 8273143b9aSmrg#include <arpa/inet.h> 8373143b9aSmrg#endif 8473143b9aSmrg 8573143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8673143b9aSmrg#define X_INCLUDE_NETDB_H 8773143b9aSmrg#define XOS_USE_NO_LOCKING 8873143b9aSmrg#include <X11/Xos_r.h> 8973143b9aSmrg#endif 9073143b9aSmrg 9173143b9aSmrg#ifdef UNIXCONN 9273143b9aSmrg#ifndef X_NO_SYS_UN 9373143b9aSmrg#include <sys/un.h> 9473143b9aSmrg#endif 9573143b9aSmrg#include <sys/stat.h> 9673143b9aSmrg#endif 9773143b9aSmrg 9873143b9aSmrg 9973143b9aSmrg#ifndef NO_TCP_H 100fe567363Smrg#if defined(linux) || defined(__GLIBC__) 10173143b9aSmrg#include <sys/param.h> 10273143b9aSmrg#endif /* osf */ 10373143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 10473143b9aSmrg#include <sys/param.h> 10573143b9aSmrg#include <machine/endian.h> 10673143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */ 10773143b9aSmrg#include <netinet/tcp.h> 10873143b9aSmrg#endif /* !NO_TCP_H */ 10973143b9aSmrg 11073143b9aSmrg#include <sys/ioctl.h> 111e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 11273143b9aSmrg#include <sys/filio.h> 11373143b9aSmrg#endif 11473143b9aSmrg 1158d4c0f7bSmrg#include <unistd.h> 1168d4c0f7bSmrg 11773143b9aSmrg#else /* !WIN32 */ 11873143b9aSmrg 11973143b9aSmrg#include <X11/Xwinsock.h> 12073143b9aSmrg#include <X11/Xwindows.h> 12173143b9aSmrg#include <X11/Xw32defs.h> 12273143b9aSmrg#undef close 12373143b9aSmrg#define close closesocket 12473143b9aSmrg#define ECONNREFUSED WSAECONNREFUSED 12573143b9aSmrg#define EADDRINUSE WSAEADDRINUSE 12673143b9aSmrg#define EPROTOTYPE WSAEPROTOTYPE 12773143b9aSmrg#undef EWOULDBLOCK 12873143b9aSmrg#define EWOULDBLOCK WSAEWOULDBLOCK 12973143b9aSmrg#define EINPROGRESS WSAEINPROGRESS 13073143b9aSmrg#undef EINTR 13173143b9aSmrg#define EINTR WSAEINTR 13273143b9aSmrg#define X_INCLUDE_NETDB_H 13373143b9aSmrg#define XOS_USE_MTSAFE_NETDBAPI 13473143b9aSmrg#include <X11/Xos_r.h> 13573143b9aSmrg#endif /* WIN32 */ 13673143b9aSmrg 13773143b9aSmrg#if defined(SO_DONTLINGER) && defined(SO_LINGER) 13873143b9aSmrg#undef SO_DONTLINGER 13973143b9aSmrg#endif 14073143b9aSmrg 14173143b9aSmrg/* others don't need this */ 14273143b9aSmrg#define SocketInitOnce() /**/ 14373143b9aSmrg 144a773ec55Smrg#ifdef __linux__ 14573143b9aSmrg#define HAVE_ABSTRACT_SOCKETS 14673143b9aSmrg#endif 14773143b9aSmrg 14873143b9aSmrg#define MIN_BACKLOG 128 14973143b9aSmrg#ifdef SOMAXCONN 15073143b9aSmrg#if SOMAXCONN > MIN_BACKLOG 15173143b9aSmrg#define BACKLOG SOMAXCONN 15273143b9aSmrg#endif 15373143b9aSmrg#endif 15473143b9aSmrg#ifndef BACKLOG 15573143b9aSmrg#define BACKLOG MIN_BACKLOG 15673143b9aSmrg#endif 15773143b9aSmrg 15873143b9aSmrg/* 15973143b9aSmrg * This is the Socket implementation of the X Transport service layer 16073143b9aSmrg * 16173143b9aSmrg * This file contains the implementation for both the UNIX and INET domains, 16273143b9aSmrg * and can be built for either one, or both. 16373143b9aSmrg * 16473143b9aSmrg */ 16573143b9aSmrg 166fe567363Smrgtypedef struct _Sockettrans2dev { 167fe567363Smrg const char *transname; 16873143b9aSmrg int family; 16973143b9aSmrg int devcotsname; 17073143b9aSmrg int devcltsname; 17173143b9aSmrg int protocol; 17273143b9aSmrg} Sockettrans2dev; 17373143b9aSmrg 17473143b9aSmrgstatic Sockettrans2dev Sockettrans2devtab[] = { 17573143b9aSmrg#ifdef TCPCONN 17673143b9aSmrg {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 17773143b9aSmrg#if !defined(IPv6) || !defined(AF_INET6) 17873143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, 17973143b9aSmrg#else /* IPv6 */ 18073143b9aSmrg {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 18173143b9aSmrg {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ 18273143b9aSmrg {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, 18373143b9aSmrg#endif 18473143b9aSmrg#endif /* TCPCONN */ 18573143b9aSmrg#ifdef UNIXCONN 18673143b9aSmrg {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 18773143b9aSmrg#if !defined(LOCALCONN) 18873143b9aSmrg {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, 18973143b9aSmrg#endif /* !LOCALCONN */ 19073143b9aSmrg#endif /* UNIXCONN */ 19173143b9aSmrg}; 19273143b9aSmrg 19373143b9aSmrg#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev)) 19473143b9aSmrg 19573143b9aSmrg#ifdef TCPCONN 19673143b9aSmrgstatic int TRANS(SocketINETClose) (XtransConnInfo ciptr); 19773143b9aSmrg#endif 19873143b9aSmrg 199a773ec55Smrg#if defined(TCPCONN) || defined(TRANS_REOPEN) 200a773ec55Smrgstatic int 201a773ec55Smrgis_numeric (const char *str) 202a773ec55Smrg{ 203a773ec55Smrg int i; 204a773ec55Smrg 205a773ec55Smrg for (i = 0; i < (int) strlen (str); i++) 206a773ec55Smrg if (!isdigit (str[i])) 207a773ec55Smrg return (0); 208a773ec55Smrg 209a773ec55Smrg return (1); 210a773ec55Smrg} 211a773ec55Smrg#endif 212a773ec55Smrg 21373143b9aSmrg#ifdef UNIXCONN 21473143b9aSmrg 21573143b9aSmrg 21673143b9aSmrg#if defined(X11_t) 21773143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 21873143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 21973143b9aSmrg#endif /* X11_t */ 22073143b9aSmrg#if defined(XIM_t) 22173143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM" 22273143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix" 22373143b9aSmrg#endif /* XIM_t */ 22473143b9aSmrg#if defined(FS_t) || defined(FONT_t) 22573143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs" 22673143b9aSmrg#define UNIX_DIR "/tmp/.font-unix" 22773143b9aSmrg#endif /* FS_t || FONT_t */ 22873143b9aSmrg#if defined(ICE_t) 22973143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/" 23073143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix" 23173143b9aSmrg#endif /* ICE_t */ 23273143b9aSmrg 23373143b9aSmrg 23473143b9aSmrg#endif /* UNIXCONN */ 23573143b9aSmrg 23673143b9aSmrg#define PORTBUFSIZE 32 23773143b9aSmrg 23873143b9aSmrg#ifndef MAXHOSTNAMELEN 23973143b9aSmrg#define MAXHOSTNAMELEN 255 24073143b9aSmrg#endif 24173143b9aSmrg 24273143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6)) 24373143b9aSmrg# define SOCKLEN_T socklen_t 244a773ec55Smrg#elif defined(SVR4) || defined(__SVR4) 245fe567363Smrg# define SOCKLEN_T size_t 24673143b9aSmrg#else 24773143b9aSmrg# define SOCKLEN_T int 24873143b9aSmrg#endif 24973143b9aSmrg 25073143b9aSmrg/* 25173143b9aSmrg * These are some utility function used by the real interface function below. 25273143b9aSmrg */ 25373143b9aSmrg 25473143b9aSmrgstatic int 255fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family) 25673143b9aSmrg 25773143b9aSmrg{ 25873143b9aSmrg int i; 25973143b9aSmrg 260fe567363Smrg prmsg (3,"SocketSelectFamily(%s)\n", family); 26173143b9aSmrg 26273143b9aSmrg for (i = first + 1; i < NUMSOCKETFAMILIES;i++) 26373143b9aSmrg { 26473143b9aSmrg if (!strcmp (family, Sockettrans2devtab[i].transname)) 26573143b9aSmrg return i; 26673143b9aSmrg } 26773143b9aSmrg 26873143b9aSmrg return (first == -1 ? -2 : -1); 26973143b9aSmrg} 27073143b9aSmrg 27173143b9aSmrg 27273143b9aSmrg/* 27373143b9aSmrg * This function gets the local address of the socket and stores it in the 27473143b9aSmrg * XtransConnInfo structure for the connection. 27573143b9aSmrg */ 27673143b9aSmrg 27773143b9aSmrgstatic int 27873143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr) 27973143b9aSmrg 28073143b9aSmrg{ 28173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 28273143b9aSmrg struct sockaddr_storage socknamev6; 283b53e5eeaSmrg#else 28473143b9aSmrg struct sockaddr_in socknamev4; 285b53e5eeaSmrg#endif 28673143b9aSmrg void *socknamePtr; 28773143b9aSmrg SOCKLEN_T namelen; 28873143b9aSmrg 289fe567363Smrg prmsg (3,"SocketINETGetAddr(%p)\n", ciptr); 29073143b9aSmrg 29173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 292b53e5eeaSmrg namelen = sizeof(socknamev6); 293b53e5eeaSmrg socknamePtr = &socknamev6; 294b53e5eeaSmrg#else 295b53e5eeaSmrg namelen = sizeof(socknamev4); 296b53e5eeaSmrg socknamePtr = &socknamev4; 29773143b9aSmrg#endif 29873143b9aSmrg 29973143b9aSmrg bzero(socknamePtr, namelen); 300fe567363Smrg 30173143b9aSmrg if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, 30273143b9aSmrg (void *)&namelen) < 0) 30373143b9aSmrg { 30473143b9aSmrg#ifdef WIN32 30573143b9aSmrg errno = WSAGetLastError(); 30673143b9aSmrg#endif 307fe567363Smrg prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n", 308fe567363Smrg EGET()); 30973143b9aSmrg return -1; 31073143b9aSmrg } 31173143b9aSmrg 31273143b9aSmrg /* 31373143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 31473143b9aSmrg */ 31573143b9aSmrg 316fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 31773143b9aSmrg { 318fe567363Smrg prmsg (1, 319fe567363Smrg "SocketINETGetAddr: Can't allocate space for the addr\n"); 32073143b9aSmrg return -1; 32173143b9aSmrg } 32273143b9aSmrg 32373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 324b53e5eeaSmrg ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; 325b53e5eeaSmrg#else 326b53e5eeaSmrg ciptr->family = socknamev4.sin_family; 32773143b9aSmrg#endif 32873143b9aSmrg ciptr->addrlen = namelen; 32973143b9aSmrg memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); 33073143b9aSmrg 33173143b9aSmrg return 0; 33273143b9aSmrg} 33373143b9aSmrg 33473143b9aSmrg 33573143b9aSmrg/* 33673143b9aSmrg * This function gets the remote address of the socket and stores it in the 33773143b9aSmrg * XtransConnInfo structure for the connection. 33873143b9aSmrg */ 33973143b9aSmrg 34073143b9aSmrgstatic int 34173143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) 34273143b9aSmrg 34373143b9aSmrg{ 34473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 34573143b9aSmrg struct sockaddr_storage socknamev6; 34673143b9aSmrg#endif 34773143b9aSmrg struct sockaddr_in socknamev4; 34873143b9aSmrg void *socknamePtr; 34973143b9aSmrg SOCKLEN_T namelen; 35073143b9aSmrg 35173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 352b53e5eeaSmrg if (ciptr->family == AF_INET6) 35373143b9aSmrg { 35473143b9aSmrg namelen = sizeof(socknamev6); 35573143b9aSmrg socknamePtr = &socknamev6; 35673143b9aSmrg } 35773143b9aSmrg else 35873143b9aSmrg#endif 35973143b9aSmrg { 36073143b9aSmrg namelen = sizeof(socknamev4); 36173143b9aSmrg socknamePtr = &socknamev4; 36273143b9aSmrg } 36373143b9aSmrg 36473143b9aSmrg bzero(socknamePtr, namelen); 365fe567363Smrg 366fe567363Smrg prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr); 36773143b9aSmrg 36873143b9aSmrg if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, 36973143b9aSmrg (void *)&namelen) < 0) 37073143b9aSmrg { 37173143b9aSmrg#ifdef WIN32 37273143b9aSmrg errno = WSAGetLastError(); 37373143b9aSmrg#endif 374fe567363Smrg prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", 375fe567363Smrg EGET()); 37673143b9aSmrg return -1; 37773143b9aSmrg } 37873143b9aSmrg 37973143b9aSmrg /* 38073143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 38173143b9aSmrg */ 38273143b9aSmrg 383fe567363Smrg if ((ciptr->peeraddr = malloc (namelen)) == NULL) 38473143b9aSmrg { 385fe567363Smrg prmsg (1, 386fe567363Smrg "SocketINETGetPeerAddr: Can't allocate space for the addr\n"); 38773143b9aSmrg return -1; 38873143b9aSmrg } 38973143b9aSmrg 39073143b9aSmrg ciptr->peeraddrlen = namelen; 39173143b9aSmrg memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); 39273143b9aSmrg 39373143b9aSmrg return 0; 39473143b9aSmrg} 39573143b9aSmrg 39673143b9aSmrg 39773143b9aSmrgstatic XtransConnInfo 39873143b9aSmrgTRANS(SocketOpen) (int i, int type) 39973143b9aSmrg 40073143b9aSmrg{ 40173143b9aSmrg XtransConnInfo ciptr; 40273143b9aSmrg 403fe567363Smrg prmsg (3,"SocketOpen(%d,%d)\n", i, type); 40473143b9aSmrg 405fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 40673143b9aSmrg { 407fe567363Smrg prmsg (1, "SocketOpen: malloc failed\n"); 40873143b9aSmrg return NULL; 40973143b9aSmrg } 41073143b9aSmrg 41173143b9aSmrg if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type, 41273143b9aSmrg Sockettrans2devtab[i].protocol)) < 0 41373143b9aSmrg#ifndef WIN32 41473143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) 4158d4c0f7bSmrg || ciptr->fd >= sysconf(_SC_OPEN_MAX) 41673143b9aSmrg#endif 41773143b9aSmrg#endif 41873143b9aSmrg ) { 41973143b9aSmrg#ifdef WIN32 42073143b9aSmrg errno = WSAGetLastError(); 42173143b9aSmrg#endif 422fe567363Smrg prmsg (2, "SocketOpen: socket() failed for %s\n", 423fe567363Smrg Sockettrans2devtab[i].transname); 42473143b9aSmrg 425fe567363Smrg free (ciptr); 42673143b9aSmrg return NULL; 42773143b9aSmrg } 42873143b9aSmrg 42973143b9aSmrg#ifdef TCP_NODELAY 43073143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 43173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 43273143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 43373143b9aSmrg#endif 43473143b9aSmrg ) 43573143b9aSmrg { 43673143b9aSmrg /* 43773143b9aSmrg * turn off TCP coalescence for INET sockets 43873143b9aSmrg */ 43973143b9aSmrg 44073143b9aSmrg int tmp = 1; 44173143b9aSmrg setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, 44273143b9aSmrg (char *) &tmp, sizeof (int)); 44373143b9aSmrg } 44473143b9aSmrg#endif 44573143b9aSmrg 4468a0d9095Smrg /* 4478a0d9095Smrg * Some systems provide a really small default buffer size for 4488a0d9095Smrg * UNIX sockets. Bump it up a bit such that large transfers don't 4498a0d9095Smrg * proceed at glacial speed. 4508a0d9095Smrg */ 4518a0d9095Smrg#ifdef SO_SNDBUF 4528a0d9095Smrg if (Sockettrans2devtab[i].family == AF_UNIX) 4538a0d9095Smrg { 4548a0d9095Smrg SOCKLEN_T len = sizeof (int); 4558a0d9095Smrg int val; 4568a0d9095Smrg 4578a0d9095Smrg if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4588a0d9095Smrg (char *) &val, &len) == 0 && val < 64 * 1024) 4598a0d9095Smrg { 4608a0d9095Smrg val = 64 * 1024; 4618a0d9095Smrg setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4628a0d9095Smrg (char *) &val, sizeof (int)); 4638a0d9095Smrg } 4648a0d9095Smrg } 4658a0d9095Smrg#endif 4668a0d9095Smrg 46773143b9aSmrg return ciptr; 46873143b9aSmrg} 46973143b9aSmrg 47073143b9aSmrg 47173143b9aSmrg#ifdef TRANS_REOPEN 47273143b9aSmrg 47373143b9aSmrgstatic XtransConnInfo 4746a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port) 47573143b9aSmrg 47673143b9aSmrg{ 47773143b9aSmrg XtransConnInfo ciptr; 47873143b9aSmrg int portlen; 47973143b9aSmrg struct sockaddr *addr; 480fe567363Smrg size_t addrlen; 48173143b9aSmrg 482fe567363Smrg prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); 48373143b9aSmrg 48473143b9aSmrg if (port == NULL) { 485fe567363Smrg prmsg (1, "SocketReopen: port was null!\n"); 48673143b9aSmrg return NULL; 48773143b9aSmrg } 48873143b9aSmrg 48973143b9aSmrg portlen = strlen(port) + 1; // include space for trailing null 49073143b9aSmrg#ifdef SOCK_MAXADDRLEN 49173143b9aSmrg if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { 492fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 49373143b9aSmrg return NULL; 49473143b9aSmrg } 49573143b9aSmrg if (portlen < 14) portlen = 14; 49673143b9aSmrg#else 49773143b9aSmrg if (portlen < 0 || portlen > 14) { 498fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 49973143b9aSmrg return NULL; 50073143b9aSmrg } 50173143b9aSmrg#endif /*SOCK_MAXADDRLEN*/ 50273143b9aSmrg 503fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 50473143b9aSmrg { 505fe567363Smrg prmsg (1, "SocketReopen: malloc(ciptr) failed\n"); 50673143b9aSmrg return NULL; 50773143b9aSmrg } 50873143b9aSmrg 50973143b9aSmrg ciptr->fd = fd; 51073143b9aSmrg 511fe567363Smrg addrlen = portlen + offsetof(struct sockaddr, sa_data); 512fe567363Smrg if ((addr = calloc (1, addrlen)) == NULL) { 513fe567363Smrg prmsg (1, "SocketReopen: malloc(addr) failed\n"); 514fe567363Smrg free (ciptr); 51573143b9aSmrg return NULL; 51673143b9aSmrg } 5178d4c0f7bSmrg ciptr->addr = (char *) addr; 518fe567363Smrg ciptr->addrlen = addrlen; 51973143b9aSmrg 520fe567363Smrg if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { 521fe567363Smrg prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); 522fe567363Smrg free (addr); 523fe567363Smrg free (ciptr); 52473143b9aSmrg return NULL; 52573143b9aSmrg } 526fe567363Smrg ciptr->peeraddrlen = addrlen; 52773143b9aSmrg 52873143b9aSmrg /* Initialize ciptr structure as if it were a normally-opened unix socket */ 52973143b9aSmrg ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; 53073143b9aSmrg#ifdef BSD44SOCKETS 531fe567363Smrg addr->sa_len = addrlen; 53273143b9aSmrg#endif 53373143b9aSmrg addr->sa_family = AF_UNIX; 5347448d6e9Smrg#if defined(HAVE_STRLCPY) || defined(HAS_STRLCPY) 53573143b9aSmrg strlcpy(addr->sa_data, port, portlen); 53673143b9aSmrg#else 53773143b9aSmrg strncpy(addr->sa_data, port, portlen); 53873143b9aSmrg#endif 53973143b9aSmrg ciptr->family = AF_UNIX; 540fe567363Smrg memcpy(ciptr->peeraddr, ciptr->addr, addrlen); 54173143b9aSmrg ciptr->port = rindex(addr->sa_data, ':'); 542e8a71cdfSmrg if (ciptr->port == NULL) { 543e8a71cdfSmrg if (is_numeric(addr->sa_data)) { 544e8a71cdfSmrg ciptr->port = addr->sa_data; 545e8a71cdfSmrg } 546e8a71cdfSmrg } else if (ciptr->port[0] == ':') { 547e8a71cdfSmrg ciptr->port++; 548e8a71cdfSmrg } 549e8a71cdfSmrg /* port should now point to portnum or NULL */ 55073143b9aSmrg return ciptr; 55173143b9aSmrg} 55273143b9aSmrg 55373143b9aSmrg#endif /* TRANS_REOPEN */ 55473143b9aSmrg 55573143b9aSmrg 55673143b9aSmrg/* 55773143b9aSmrg * These functions are the interface supplied in the Xtransport structure 55873143b9aSmrg */ 55973143b9aSmrg 56073143b9aSmrg#ifdef TRANS_CLIENT 56173143b9aSmrg 56273143b9aSmrgstatic XtransConnInfo 563fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol, 564fe567363Smrg const char *host, const char *port, int previndex) 56573143b9aSmrg{ 56673143b9aSmrg XtransConnInfo ciptr; 56773143b9aSmrg int i = previndex; 56873143b9aSmrg 569fe567363Smrg prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n", 57073143b9aSmrg protocol, host, port); 57173143b9aSmrg 57273143b9aSmrg SocketInitOnce(); 57373143b9aSmrg 57473143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { 57573143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 576e8a71cdfSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) { 577e8a71cdfSmrg /* Save the index for later use */ 578e8a71cdfSmrg 579e8a71cdfSmrg ciptr->index = i; 58073143b9aSmrg break; 581e8a71cdfSmrg } 58273143b9aSmrg } 58373143b9aSmrg if (i < 0) { 58473143b9aSmrg if (i == -1) 585fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", 586fe567363Smrg transname); 58773143b9aSmrg else 588fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", 589fe567363Smrg transname); 59073143b9aSmrg return NULL; 59173143b9aSmrg } 59273143b9aSmrg 59373143b9aSmrg return ciptr; 59473143b9aSmrg} 59573143b9aSmrg 59673143b9aSmrgstatic XtransConnInfo 5976a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol, 5986a3641a6Ssnj const char *host, const char *port) 59973143b9aSmrg{ 60073143b9aSmrg return TRANS(SocketOpenCOTSClientBase)( 60173143b9aSmrg thistrans->TransName, protocol, host, port, -1); 60273143b9aSmrg} 60373143b9aSmrg 60473143b9aSmrg 60573143b9aSmrg#endif /* TRANS_CLIENT */ 60673143b9aSmrg 60773143b9aSmrg 60873143b9aSmrg#ifdef TRANS_SERVER 60973143b9aSmrg 61073143b9aSmrgstatic XtransConnInfo 6116a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol, 6126a3641a6Ssnj const char *host, const char *port) 61373143b9aSmrg 61473143b9aSmrg{ 61573143b9aSmrg XtransConnInfo ciptr; 61673143b9aSmrg int i = -1; 61773143b9aSmrg 618fe567363Smrg prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); 61973143b9aSmrg 62073143b9aSmrg SocketInitOnce(); 62173143b9aSmrg 62273143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 62373143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 62473143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 62573143b9aSmrg break; 62673143b9aSmrg } 62773143b9aSmrg if (i < 0) { 628a773ec55Smrg if (i == -1) { 629a773ec55Smrg if (errno == EAFNOSUPPORT) { 630a773ec55Smrg thistrans->flags |= TRANS_NOLISTEN; 631a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Socket for %s unsupported on this system.\n", 632a773ec55Smrg thistrans->TransName); 633a773ec55Smrg } else { 634a773ec55Smrg prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", 635a773ec55Smrg thistrans->TransName); 636a773ec55Smrg } 637a773ec55Smrg } else { 638fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", 639fe567363Smrg thistrans->TransName); 640a773ec55Smrg } 64173143b9aSmrg return NULL; 64273143b9aSmrg } 64373143b9aSmrg 64473143b9aSmrg /* 64573143b9aSmrg * Using this prevents the bind() check for an existing server listening 64673143b9aSmrg * on the same port, but it is required for other reasons. 64773143b9aSmrg */ 64873143b9aSmrg#ifdef SO_REUSEADDR 64973143b9aSmrg 65073143b9aSmrg /* 65173143b9aSmrg * SO_REUSEADDR only applied to AF_INET && AF_INET6 65273143b9aSmrg */ 65373143b9aSmrg 65473143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 65573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 65673143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 65773143b9aSmrg#endif 65873143b9aSmrg ) 65973143b9aSmrg { 66073143b9aSmrg int one = 1; 66173143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, 66273143b9aSmrg (char *) &one, sizeof (int)); 66373143b9aSmrg } 66473143b9aSmrg#endif 66573143b9aSmrg#ifdef IPV6_V6ONLY 66673143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 66773143b9aSmrg { 66873143b9aSmrg int one = 1; 66973143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 67073143b9aSmrg } 67173143b9aSmrg#endif 67273143b9aSmrg /* Save the index for later use */ 67373143b9aSmrg 67473143b9aSmrg ciptr->index = i; 67573143b9aSmrg 67673143b9aSmrg return ciptr; 67773143b9aSmrg} 67873143b9aSmrg 67973143b9aSmrg#endif /* TRANS_SERVER */ 68073143b9aSmrg 68173143b9aSmrg 68273143b9aSmrg#ifdef TRANS_REOPEN 68373143b9aSmrg 68473143b9aSmrgstatic XtransConnInfo 6856a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port) 68673143b9aSmrg 68773143b9aSmrg{ 68873143b9aSmrg XtransConnInfo ciptr; 68973143b9aSmrg int i = -1; 69073143b9aSmrg 691fe567363Smrg prmsg (2, 692fe567363Smrg "SocketReopenCOTSServer(%d, %s)\n", fd, port); 69373143b9aSmrg 69473143b9aSmrg SocketInitOnce(); 69573143b9aSmrg 69673143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 69773143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 69873143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 69973143b9aSmrg break; 70073143b9aSmrg } 70173143b9aSmrg if (i < 0) { 70273143b9aSmrg if (i == -1) 703fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", 704fe567363Smrg thistrans->TransName); 70573143b9aSmrg else 706fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", 707fe567363Smrg thistrans->TransName); 70873143b9aSmrg return NULL; 70973143b9aSmrg } 71073143b9aSmrg 71173143b9aSmrg /* Save the index for later use */ 71273143b9aSmrg 71373143b9aSmrg ciptr->index = i; 71473143b9aSmrg 71573143b9aSmrg return ciptr; 71673143b9aSmrg} 71773143b9aSmrg 71873143b9aSmrg#endif /* TRANS_REOPEN */ 71973143b9aSmrg 72073143b9aSmrg 72173143b9aSmrgstatic int 72273143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) 72373143b9aSmrg 72473143b9aSmrg{ 725fe567363Smrg prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); 72673143b9aSmrg 72773143b9aSmrg return -1; 72873143b9aSmrg} 72973143b9aSmrg 73073143b9aSmrg#ifdef UNIXCONN 73173143b9aSmrgstatic int 73273143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract) 73373143b9aSmrg{ 73473143b9aSmrg struct sockaddr_un s; 73573143b9aSmrg int maxlen = sizeof(s.sun_path) - 1; 73673143b9aSmrg const char *at = ""; 73773143b9aSmrg 73873143b9aSmrg if (!port || !*port || !path) 73973143b9aSmrg return -1; 74073143b9aSmrg 74173143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 74273143b9aSmrg if (port[0] == '@') 74373143b9aSmrg upath = ""; 74473143b9aSmrg else if (abstract) 74573143b9aSmrg at = "@"; 74673143b9aSmrg#endif 74773143b9aSmrg 74873143b9aSmrg if (*port == '/') /* a full pathname */ 74973143b9aSmrg upath = ""; 75073143b9aSmrg 75173143b9aSmrg if (strlen(port) + strlen(upath) > maxlen) 75273143b9aSmrg return -1; 753fe567363Smrg snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port); 75473143b9aSmrg return 0; 75573143b9aSmrg} 75673143b9aSmrg#endif 75773143b9aSmrg 75873143b9aSmrg#ifdef TRANS_SERVER 75973143b9aSmrg 76073143b9aSmrgstatic int 761fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr, 76273143b9aSmrg struct sockaddr *sockname, 76373143b9aSmrg int socknamelen, unsigned int flags) 76473143b9aSmrg 76573143b9aSmrg{ 76673143b9aSmrg SOCKLEN_T namelen = socknamelen; 76773143b9aSmrg int fd = ciptr->fd; 76873143b9aSmrg int retry; 76973143b9aSmrg 770fe567363Smrg prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd); 77173143b9aSmrg 77273143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 77373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 77473143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 77573143b9aSmrg#endif 77673143b9aSmrg ) 77773143b9aSmrg retry = 20; 77873143b9aSmrg else 77973143b9aSmrg retry = 0; 78073143b9aSmrg 78173143b9aSmrg while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) 78273143b9aSmrg { 78373143b9aSmrg if (errno == EADDRINUSE) { 78473143b9aSmrg if (flags & ADDR_IN_USE_ALLOWED) 78573143b9aSmrg break; 78673143b9aSmrg else 78773143b9aSmrg return TRANS_ADDR_IN_USE; 78873143b9aSmrg } 789fe567363Smrg 79073143b9aSmrg if (retry-- == 0) { 791fe567363Smrg prmsg (1, "SocketCreateListener: failed to bind listener\n"); 79273143b9aSmrg close (fd); 79373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 79473143b9aSmrg } 79573143b9aSmrg#ifdef SO_REUSEADDR 79673143b9aSmrg sleep (1); 79773143b9aSmrg#else 79873143b9aSmrg sleep (10); 79973143b9aSmrg#endif /* SO_REUSEDADDR */ 80073143b9aSmrg } 80173143b9aSmrg 80273143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 80373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 80473143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 80573143b9aSmrg#endif 80673143b9aSmrg ) { 80773143b9aSmrg#ifdef SO_DONTLINGER 80873143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); 80973143b9aSmrg#else 81073143b9aSmrg#ifdef SO_LINGER 81173143b9aSmrg { 81273143b9aSmrg static int linger[2] = { 0, 0 }; 81373143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_LINGER, 81473143b9aSmrg (char *) linger, sizeof (linger)); 81573143b9aSmrg } 81673143b9aSmrg#endif 81773143b9aSmrg#endif 81873143b9aSmrg} 81973143b9aSmrg 82073143b9aSmrg if (listen (fd, BACKLOG) < 0) 82173143b9aSmrg { 822fe567363Smrg prmsg (1, "SocketCreateListener: listen() failed\n"); 82373143b9aSmrg close (fd); 82473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 82573143b9aSmrg } 826fe567363Smrg 82773143b9aSmrg /* Set a flag to indicate that this connection is a listener */ 82873143b9aSmrg 82973143b9aSmrg ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 83073143b9aSmrg 83173143b9aSmrg return 0; 83273143b9aSmrg} 83373143b9aSmrg 83473143b9aSmrg#ifdef TCPCONN 83573143b9aSmrgstatic int 8366a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port, 8376a3641a6Ssnj unsigned int flags) 83873143b9aSmrg 83973143b9aSmrg{ 84073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 84173143b9aSmrg struct sockaddr_storage sockname; 84273143b9aSmrg#else 84373143b9aSmrg struct sockaddr_in sockname; 84473143b9aSmrg#endif 84573143b9aSmrg unsigned short sport; 84673143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 84773143b9aSmrg int status; 84873143b9aSmrg long tmpport; 84973143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 85073143b9aSmrg _Xgetservbynameparams sparams; 85173143b9aSmrg#endif 85273143b9aSmrg struct servent *servp; 85373143b9aSmrg 85473143b9aSmrg#ifdef X11_t 85573143b9aSmrg char portbuf[PORTBUFSIZE]; 85673143b9aSmrg#endif 857fe567363Smrg 858fe567363Smrg prmsg (2, "SocketINETCreateListener(%s)\n", port); 85973143b9aSmrg 86073143b9aSmrg#ifdef X11_t 86173143b9aSmrg /* 86273143b9aSmrg * X has a well known port, that is transport dependent. It is easier 86373143b9aSmrg * to handle it here, than try and come up with a transport independent 86473143b9aSmrg * representation that can be passed in and resolved the usual way. 86573143b9aSmrg * 86673143b9aSmrg * The port that is passed here is really a string containing the idisplay 86773143b9aSmrg * from ConnectDisplay(). 86873143b9aSmrg */ 86973143b9aSmrg 87073143b9aSmrg if (is_numeric (port)) 87173143b9aSmrg { 87273143b9aSmrg /* fixup the server port address */ 87373143b9aSmrg tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 874fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 87573143b9aSmrg port = portbuf; 87673143b9aSmrg } 87773143b9aSmrg#endif 87873143b9aSmrg 87973143b9aSmrg if (port && *port) 88073143b9aSmrg { 88173143b9aSmrg /* Check to see if the port string is just a number (handles X11) */ 88273143b9aSmrg 88373143b9aSmrg if (!is_numeric (port)) 88473143b9aSmrg { 88573143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) 88673143b9aSmrg { 887fe567363Smrg prmsg (1, 88873143b9aSmrg "SocketINETCreateListener: Unable to get service for %s\n", 889fe567363Smrg port); 89073143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 89173143b9aSmrg } 89273143b9aSmrg /* we trust getservbyname to return a valid number */ 89373143b9aSmrg sport = servp->s_port; 89473143b9aSmrg } 89573143b9aSmrg else 89673143b9aSmrg { 89773143b9aSmrg tmpport = strtol (port, (char**)NULL, 10); 898fe567363Smrg /* 89973143b9aSmrg * check that somehow the port address isn't negative or in 90073143b9aSmrg * the range of reserved port addresses. This can happen and 901fe567363Smrg * be very bad if the server is suid-root and the user does 902fe567363Smrg * something (dumb) like `X :60049`. 90373143b9aSmrg */ 90473143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 90573143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 90673143b9aSmrg 90773143b9aSmrg sport = (unsigned short) tmpport; 90873143b9aSmrg } 90973143b9aSmrg } 91073143b9aSmrg else 91173143b9aSmrg sport = 0; 91273143b9aSmrg 91373143b9aSmrg bzero(&sockname, sizeof(sockname)); 91473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 91573143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 91673143b9aSmrg namelen = sizeof (struct sockaddr_in); 91773143b9aSmrg#ifdef BSD44SOCKETS 91873143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_len = namelen; 91973143b9aSmrg#endif 92073143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; 92173143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); 92273143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); 92373143b9aSmrg } else { 92473143b9aSmrg namelen = sizeof (struct sockaddr_in6); 92573143b9aSmrg#ifdef SIN6_LEN 92673143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); 92773143b9aSmrg#endif 92873143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; 92973143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); 93073143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; 93173143b9aSmrg } 93273143b9aSmrg#else 93373143b9aSmrg#ifdef BSD44SOCKETS 93473143b9aSmrg sockname.sin_len = sizeof (sockname); 93573143b9aSmrg#endif 93673143b9aSmrg sockname.sin_family = AF_INET; 93773143b9aSmrg sockname.sin_port = htons (sport); 93873143b9aSmrg sockname.sin_addr.s_addr = htonl (INADDR_ANY); 93973143b9aSmrg#endif 94073143b9aSmrg 94173143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 94273143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 94373143b9aSmrg { 944fe567363Smrg prmsg (1, 945fe567363Smrg "SocketINETCreateListener: ...SocketCreateListener() failed\n"); 94673143b9aSmrg return status; 94773143b9aSmrg } 94873143b9aSmrg 94973143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 95073143b9aSmrg { 951fe567363Smrg prmsg (1, 952fe567363Smrg "SocketINETCreateListener: ...SocketINETGetAddr() failed\n"); 95373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 95473143b9aSmrg } 95573143b9aSmrg 95673143b9aSmrg return 0; 95773143b9aSmrg} 95873143b9aSmrg 95973143b9aSmrg#endif /* TCPCONN */ 96073143b9aSmrg 96173143b9aSmrg 96273143b9aSmrg#ifdef UNIXCONN 96373143b9aSmrg 96473143b9aSmrgstatic int 9656a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port, 96673143b9aSmrg unsigned int flags) 96773143b9aSmrg 96873143b9aSmrg{ 96973143b9aSmrg struct sockaddr_un sockname; 97073143b9aSmrg int namelen; 97173143b9aSmrg int oldUmask; 97273143b9aSmrg int status; 97373143b9aSmrg unsigned int mode; 97473143b9aSmrg char tmpport[108]; 97573143b9aSmrg 97673143b9aSmrg int abstract = 0; 97773143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 97873143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 97973143b9aSmrg#endif 98073143b9aSmrg 981fe567363Smrg prmsg (2, "SocketUNIXCreateListener(%s)\n", 982fe567363Smrg port ? port : "NULL"); 98373143b9aSmrg 98473143b9aSmrg /* Make sure the directory is created */ 98573143b9aSmrg 98673143b9aSmrg oldUmask = umask (0); 98773143b9aSmrg 98873143b9aSmrg#ifdef UNIX_DIR 98973143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 99073143b9aSmrg mode = 01777; 99173143b9aSmrg#else 99273143b9aSmrg mode = 0777; 99373143b9aSmrg#endif 9948d4c0f7bSmrg if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) { 995fe567363Smrg prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", 996fe567363Smrg UNIX_DIR, errno); 99773143b9aSmrg (void) umask (oldUmask); 99873143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 99973143b9aSmrg } 100073143b9aSmrg#endif 100173143b9aSmrg 100273143b9aSmrg memset(&sockname, 0, sizeof(sockname)); 100373143b9aSmrg sockname.sun_family = AF_UNIX; 100473143b9aSmrg 100573143b9aSmrg if (!(port && *port)) { 100673143b9aSmrg snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid()); 100773143b9aSmrg port = tmpport; 100873143b9aSmrg } 100973143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1010fe567363Smrg prmsg (1, "SocketUNIXCreateListener: path too long\n"); 101173143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 101273143b9aSmrg } 101373143b9aSmrg 1014a773ec55Smrg#if defined(BSD44SOCKETS) 101573143b9aSmrg sockname.sun_len = strlen(sockname.sun_path); 101673143b9aSmrg#endif 101773143b9aSmrg 101873143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 101973143b9aSmrg namelen = SUN_LEN(&sockname); 102073143b9aSmrg#else 102173143b9aSmrg namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 102273143b9aSmrg#endif 102373143b9aSmrg 102473143b9aSmrg if (abstract) { 102573143b9aSmrg sockname.sun_path[0] = '\0'; 102673143b9aSmrg namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]); 102773143b9aSmrg } 102873143b9aSmrg else 102973143b9aSmrg unlink (sockname.sun_path); 103073143b9aSmrg 103173143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 103273143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 103373143b9aSmrg { 1034fe567363Smrg prmsg (1, 1035fe567363Smrg "SocketUNIXCreateListener: ...SocketCreateListener() failed\n"); 103673143b9aSmrg (void) umask (oldUmask); 103773143b9aSmrg return status; 103873143b9aSmrg } 103973143b9aSmrg 104073143b9aSmrg /* 104173143b9aSmrg * Now that the listener is esablished, create the addr info for 104273143b9aSmrg * this connection. getpeername() doesn't work for UNIX Domain Sockets 104373143b9aSmrg * on some systems (hpux at least), so we will just do it manually, instead 104473143b9aSmrg * of calling something like TRANS(SocketUNIXGetAddr). 104573143b9aSmrg */ 104673143b9aSmrg 104773143b9aSmrg namelen = sizeof (sockname); /* this will always make it the same size */ 104873143b9aSmrg 1049fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 105073143b9aSmrg { 1051fe567363Smrg prmsg (1, 1052fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 105373143b9aSmrg (void) umask (oldUmask); 105473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 105573143b9aSmrg } 105673143b9aSmrg 105773143b9aSmrg if (abstract) 105873143b9aSmrg sockname.sun_path[0] = '@'; 105973143b9aSmrg 106073143b9aSmrg ciptr->family = sockname.sun_family; 106173143b9aSmrg ciptr->addrlen = namelen; 106273143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 106373143b9aSmrg 106473143b9aSmrg (void) umask (oldUmask); 106573143b9aSmrg 106673143b9aSmrg return 0; 106773143b9aSmrg} 106873143b9aSmrg 106973143b9aSmrg 107073143b9aSmrgstatic int 107173143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) 107273143b9aSmrg 107373143b9aSmrg{ 107473143b9aSmrg /* 107573143b9aSmrg * See if the unix domain socket has disappeared. If it has, recreate it. 107673143b9aSmrg */ 107773143b9aSmrg 107873143b9aSmrg struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; 107973143b9aSmrg struct stat statb; 108073143b9aSmrg int status = TRANS_RESET_NOOP; 108173143b9aSmrg unsigned int mode; 108273143b9aSmrg int abstract = 0; 108373143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 108473143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 108573143b9aSmrg#endif 108673143b9aSmrg 1087fe567363Smrg prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd); 108873143b9aSmrg 108973143b9aSmrg if (!abstract && ( 109073143b9aSmrg stat (unsock->sun_path, &statb) == -1 || 109173143b9aSmrg ((statb.st_mode & S_IFMT) != 1092a773ec55Smrg#if !defined(S_IFSOCK) 109373143b9aSmrg S_IFIFO 109473143b9aSmrg#else 109573143b9aSmrg S_IFSOCK 109673143b9aSmrg#endif 109773143b9aSmrg ))) 109873143b9aSmrg { 109973143b9aSmrg int oldUmask = umask (0); 110073143b9aSmrg 110173143b9aSmrg#ifdef UNIX_DIR 110273143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 110373143b9aSmrg mode = 01777; 110473143b9aSmrg#else 110573143b9aSmrg mode = 0777; 110673143b9aSmrg#endif 110773143b9aSmrg if (trans_mkdir(UNIX_DIR, mode) == -1) { 1108fe567363Smrg prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", 1109fe567363Smrg UNIX_DIR, errno); 111073143b9aSmrg (void) umask (oldUmask); 111173143b9aSmrg return TRANS_RESET_FAILURE; 111273143b9aSmrg } 111373143b9aSmrg#endif 111473143b9aSmrg 111573143b9aSmrg close (ciptr->fd); 111673143b9aSmrg unlink (unsock->sun_path); 111773143b9aSmrg 111873143b9aSmrg if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 111973143b9aSmrg { 112073143b9aSmrg TRANS(FreeConnInfo) (ciptr); 112173143b9aSmrg (void) umask (oldUmask); 112273143b9aSmrg return TRANS_RESET_FAILURE; 112373143b9aSmrg } 112473143b9aSmrg 112573143b9aSmrg if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) 112673143b9aSmrg { 112773143b9aSmrg close (ciptr->fd); 112873143b9aSmrg TRANS(FreeConnInfo) (ciptr); 112973143b9aSmrg return TRANS_RESET_FAILURE; 113073143b9aSmrg } 113173143b9aSmrg 113273143b9aSmrg if (listen (ciptr->fd, BACKLOG) < 0) 113373143b9aSmrg { 113473143b9aSmrg close (ciptr->fd); 113573143b9aSmrg TRANS(FreeConnInfo) (ciptr); 113673143b9aSmrg (void) umask (oldUmask); 113773143b9aSmrg return TRANS_RESET_FAILURE; 113873143b9aSmrg } 113973143b9aSmrg 114073143b9aSmrg umask (oldUmask); 114173143b9aSmrg 114273143b9aSmrg status = TRANS_RESET_NEW_FD; 114373143b9aSmrg } 114473143b9aSmrg 114573143b9aSmrg return status; 114673143b9aSmrg} 114773143b9aSmrg 114873143b9aSmrg#endif /* UNIXCONN */ 114973143b9aSmrg 115073143b9aSmrg 115173143b9aSmrg#ifdef TCPCONN 115273143b9aSmrg 115373143b9aSmrgstatic XtransConnInfo 115473143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) 115573143b9aSmrg 115673143b9aSmrg{ 115773143b9aSmrg XtransConnInfo newciptr; 115873143b9aSmrg struct sockaddr_in sockname; 115973143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 116073143b9aSmrg 1161fe567363Smrg prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd); 116273143b9aSmrg 1163fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 116473143b9aSmrg { 1165fe567363Smrg prmsg (1, "SocketINETAccept: malloc failed\n"); 116673143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 116773143b9aSmrg return NULL; 116873143b9aSmrg } 116973143b9aSmrg 117073143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 117173143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 117273143b9aSmrg { 117373143b9aSmrg#ifdef WIN32 117473143b9aSmrg errno = WSAGetLastError(); 117573143b9aSmrg#endif 1176fe567363Smrg prmsg (1, "SocketINETAccept: accept() failed\n"); 1177fe567363Smrg free (newciptr); 117873143b9aSmrg *status = TRANS_ACCEPT_FAILED; 117973143b9aSmrg return NULL; 118073143b9aSmrg } 118173143b9aSmrg 118273143b9aSmrg#ifdef TCP_NODELAY 118373143b9aSmrg { 118473143b9aSmrg /* 118573143b9aSmrg * turn off TCP coalescence for INET sockets 118673143b9aSmrg */ 118773143b9aSmrg 118873143b9aSmrg int tmp = 1; 118973143b9aSmrg setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, 119073143b9aSmrg (char *) &tmp, sizeof (int)); 119173143b9aSmrg } 119273143b9aSmrg#endif 119373143b9aSmrg 119473143b9aSmrg /* 1195fe567363Smrg * Get this address again because the transport may give a more 119673143b9aSmrg * specific address now that a connection is established. 119773143b9aSmrg */ 119873143b9aSmrg 119973143b9aSmrg if (TRANS(SocketINETGetAddr) (newciptr) < 0) 120073143b9aSmrg { 1201fe567363Smrg prmsg (1, 1202fe567363Smrg "SocketINETAccept: ...SocketINETGetAddr() failed:\n"); 120373143b9aSmrg close (newciptr->fd); 1204fe567363Smrg free (newciptr); 120573143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 120673143b9aSmrg return NULL; 120773143b9aSmrg } 120873143b9aSmrg 120973143b9aSmrg if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) 121073143b9aSmrg { 1211fe567363Smrg prmsg (1, 1212fe567363Smrg "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n"); 121373143b9aSmrg close (newciptr->fd); 1214fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1215fe567363Smrg free (newciptr); 121673143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 121773143b9aSmrg return NULL; 121873143b9aSmrg } 121973143b9aSmrg 122073143b9aSmrg *status = 0; 122173143b9aSmrg 122273143b9aSmrg return newciptr; 122373143b9aSmrg} 122473143b9aSmrg 122573143b9aSmrg#endif /* TCPCONN */ 122673143b9aSmrg 122773143b9aSmrg 122873143b9aSmrg#ifdef UNIXCONN 122973143b9aSmrgstatic XtransConnInfo 123073143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) 123173143b9aSmrg 123273143b9aSmrg{ 123373143b9aSmrg XtransConnInfo newciptr; 123473143b9aSmrg struct sockaddr_un sockname; 123573143b9aSmrg SOCKLEN_T namelen = sizeof sockname; 123673143b9aSmrg 1237fe567363Smrg prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd); 123873143b9aSmrg 1239fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 124073143b9aSmrg { 1241fe567363Smrg prmsg (1, "SocketUNIXAccept: malloc() failed\n"); 124273143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 124373143b9aSmrg return NULL; 124473143b9aSmrg } 124573143b9aSmrg 124673143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 124773143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 124873143b9aSmrg { 1249fe567363Smrg prmsg (1, "SocketUNIXAccept: accept() failed\n"); 1250fe567363Smrg free (newciptr); 125173143b9aSmrg *status = TRANS_ACCEPT_FAILED; 125273143b9aSmrg return NULL; 125373143b9aSmrg } 125473143b9aSmrg 125573143b9aSmrg ciptr->addrlen = namelen; 125673143b9aSmrg /* 125773143b9aSmrg * Get the socket name and the peer name from the listener socket, 125873143b9aSmrg * since this is unix domain. 125973143b9aSmrg */ 126073143b9aSmrg 1261fe567363Smrg if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL) 126273143b9aSmrg { 1263fe567363Smrg prmsg (1, 1264fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 126573143b9aSmrg close (newciptr->fd); 1266fe567363Smrg free (newciptr); 126773143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 126873143b9aSmrg return NULL; 126973143b9aSmrg } 127073143b9aSmrg 127173143b9aSmrg /* 127273143b9aSmrg * if the socket is abstract, we already modified the address to have a 127373143b9aSmrg * @ instead of the initial NUL, so no need to do that again here. 127473143b9aSmrg */ 127573143b9aSmrg 127673143b9aSmrg newciptr->addrlen = ciptr->addrlen; 127773143b9aSmrg memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); 127873143b9aSmrg 1279fe567363Smrg if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL) 128073143b9aSmrg { 1281fe567363Smrg prmsg (1, 1282fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 128373143b9aSmrg close (newciptr->fd); 1284fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1285fe567363Smrg free (newciptr); 128673143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 128773143b9aSmrg return NULL; 128873143b9aSmrg } 1289fe567363Smrg 129073143b9aSmrg newciptr->peeraddrlen = ciptr->addrlen; 129173143b9aSmrg memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); 129273143b9aSmrg 129373143b9aSmrg newciptr->family = AF_UNIX; 129473143b9aSmrg 129573143b9aSmrg *status = 0; 129673143b9aSmrg 129773143b9aSmrg return newciptr; 129873143b9aSmrg} 129973143b9aSmrg 130073143b9aSmrg#endif /* UNIXCONN */ 130173143b9aSmrg 130273143b9aSmrg#endif /* TRANS_SERVER */ 130373143b9aSmrg 130473143b9aSmrg 130573143b9aSmrg#ifdef TRANS_CLIENT 130673143b9aSmrg 130773143b9aSmrg#ifdef TCPCONN 130873143b9aSmrg 130973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 131073143b9aSmrgstruct addrlist { 131173143b9aSmrg struct addrinfo * addr; 1312fe567363Smrg struct addrinfo * firstaddr; 131373143b9aSmrg char port[PORTBUFSIZE]; 131473143b9aSmrg char host[MAXHOSTNAMELEN]; 131573143b9aSmrg}; 131673143b9aSmrgstatic struct addrlist *addrlist = NULL; 131773143b9aSmrg#endif 131873143b9aSmrg 131973143b9aSmrg 132073143b9aSmrgstatic int 13216a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr, 13226a3641a6Ssnj const char *host, const char *port) 132373143b9aSmrg 132473143b9aSmrg{ 132573143b9aSmrg struct sockaddr * socketaddr = NULL; 132673143b9aSmrg int socketaddrlen = 0; 132773143b9aSmrg int res; 132873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 132973143b9aSmrg struct addrinfo hints; 133073143b9aSmrg char ntopbuf[INET6_ADDRSTRLEN]; 133173143b9aSmrg int resetonce = 0; 1332fe567363Smrg#else 133373143b9aSmrg struct sockaddr_in sockname; 1334fe567363Smrg struct hostent *hostp; 1335fe567363Smrg struct servent *servp; 1336fe567363Smrg unsigned long tmpaddr; 1337fe567363Smrg#endif 133873143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 133973143b9aSmrg _Xgethostbynameparams hparams; 134073143b9aSmrg _Xgetservbynameparams sparams; 134173143b9aSmrg#endif 134273143b9aSmrg#ifdef X11_t 134373143b9aSmrg char portbuf[PORTBUFSIZE]; 134473143b9aSmrg#endif 134573143b9aSmrg 134673143b9aSmrg char hostnamebuf[256]; /* tmp space */ 134773143b9aSmrg 1348fe567363Smrg prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); 134973143b9aSmrg 135073143b9aSmrg if (!host) 135173143b9aSmrg { 135273143b9aSmrg hostnamebuf[0] = '\0'; 135373143b9aSmrg (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); 135473143b9aSmrg host = hostnamebuf; 135573143b9aSmrg } 135673143b9aSmrg 135773143b9aSmrg#ifdef X11_t 135873143b9aSmrg /* 135973143b9aSmrg * X has a well known port, that is transport dependent. It is easier 136073143b9aSmrg * to handle it here, than try and come up with a transport independent 136173143b9aSmrg * representation that can be passed in and resolved the usual way. 136273143b9aSmrg * 136373143b9aSmrg * The port that is passed here is really a string containing the idisplay 136473143b9aSmrg * from ConnectDisplay(). 136573143b9aSmrg */ 136673143b9aSmrg 136773143b9aSmrg if (is_numeric (port)) 136873143b9aSmrg { 1369fe567363Smrg long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 1370fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 137173143b9aSmrg port = portbuf; 137273143b9aSmrg } 137373143b9aSmrg#endif 137473143b9aSmrg 137573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1376b53e5eeaSmrg { 137773143b9aSmrg if (addrlist != NULL) { 137873143b9aSmrg if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { 137973143b9aSmrg if (addrlist->firstaddr) 138073143b9aSmrg freeaddrinfo(addrlist->firstaddr); 138173143b9aSmrg addrlist->firstaddr = NULL; 138273143b9aSmrg } 138373143b9aSmrg } else { 138473143b9aSmrg addrlist = malloc(sizeof(struct addrlist)); 138573143b9aSmrg addrlist->firstaddr = NULL; 138673143b9aSmrg } 138773143b9aSmrg 138873143b9aSmrg if (addrlist->firstaddr == NULL) { 138973143b9aSmrg strncpy(addrlist->port, port, sizeof(addrlist->port)); 139073143b9aSmrg addrlist->port[sizeof(addrlist->port) - 1] = '\0'; 139173143b9aSmrg strncpy(addrlist->host, host, sizeof(addrlist->host)); 139273143b9aSmrg addrlist->host[sizeof(addrlist->host) - 1] = '\0'; 139373143b9aSmrg 139473143b9aSmrg bzero(&hints,sizeof(hints)); 139573143b9aSmrg hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; 139673143b9aSmrg 139773143b9aSmrg res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); 139873143b9aSmrg if (res != 0) { 1399fe567363Smrg prmsg (1, "SocketINETConnect() can't get address " 140073143b9aSmrg "for %s:%s: %s\n", host, port, gai_strerror(res)); 140173143b9aSmrg ESET(EINVAL); 140273143b9aSmrg return TRANS_CONNECT_FAILED; 140373143b9aSmrg } 140473143b9aSmrg for (res = 0, addrlist->addr = addrlist->firstaddr; 140573143b9aSmrg addrlist->addr ; res++) { 140673143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 140773143b9aSmrg } 1408fe567363Smrg prmsg(4,"Got New Address list with %d addresses\n", res); 140973143b9aSmrg res = 0; 141073143b9aSmrg addrlist->addr = NULL; 141173143b9aSmrg } 141273143b9aSmrg 141373143b9aSmrg while (socketaddr == NULL) { 141473143b9aSmrg if (addrlist->addr == NULL) { 1415fe567363Smrg if (resetonce) { 141673143b9aSmrg /* Already checked entire list - no usable addresses */ 1417fe567363Smrg prmsg (1, "SocketINETConnect() no usable address " 1418fe567363Smrg "for %s:%s\n", host, port); 141973143b9aSmrg return TRANS_CONNECT_FAILED; 142073143b9aSmrg } else { 142173143b9aSmrg /* Go back to beginning of list */ 142273143b9aSmrg resetonce = 1; 142373143b9aSmrg addrlist->addr = addrlist->firstaddr; 142473143b9aSmrg } 1425fe567363Smrg } 142673143b9aSmrg 142773143b9aSmrg socketaddr = addrlist->addr->ai_addr; 142873143b9aSmrg socketaddrlen = addrlist->addr->ai_addrlen; 142973143b9aSmrg 143073143b9aSmrg if (addrlist->addr->ai_family == AF_INET) { 143173143b9aSmrg struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; 143273143b9aSmrg 1433fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n", 143473143b9aSmrg inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, 1435fe567363Smrg ntopbuf,sizeof(ntopbuf))); 143673143b9aSmrg 1437fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n", 1438fe567363Smrg ntohs(sin->sin_port)); 143973143b9aSmrg 144073143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { 144173143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 144273143b9aSmrg "tcp") == 0) { 144373143b9aSmrg XtransConnInfo newciptr; 144473143b9aSmrg 144573143b9aSmrg /* 144673143b9aSmrg * Our socket is an IPv6 socket, but the address is 144773143b9aSmrg * IPv4. Close it and get an IPv4 socket. This is 144873143b9aSmrg * needed for IPv4 connections to work on platforms 144973143b9aSmrg * that don't allow IPv4 over IPv6 sockets. 145073143b9aSmrg */ 145173143b9aSmrg TRANS(SocketINETClose)(ciptr); 145273143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 145373143b9aSmrg "tcp", "tcp", host, port, ciptr->index); 145473143b9aSmrg if (newciptr) 145573143b9aSmrg ciptr->fd = newciptr->fd; 145673143b9aSmrg if (!newciptr || 145773143b9aSmrg Sockettrans2devtab[newciptr->index].family != 145873143b9aSmrg AF_INET) { 145973143b9aSmrg socketaddr = NULL; 1460fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv4 " 1461fe567363Smrg " socketfor IPv4 address\n"); 146273143b9aSmrg } 146373143b9aSmrg if (newciptr) 1464fe567363Smrg free(newciptr); 146573143b9aSmrg } else { 146673143b9aSmrg socketaddr = NULL; 1467fe567363Smrg prmsg (4,"SocketINETConnect Skipping IPv4 address\n"); 146873143b9aSmrg } 146973143b9aSmrg } 147073143b9aSmrg } else if (addrlist->addr->ai_family == AF_INET6) { 147173143b9aSmrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; 1472fe567363Smrg 1473fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n", 147473143b9aSmrg inet_ntop(addrlist->addr->ai_family, 1475fe567363Smrg &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf))); 1476fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n", 1477fe567363Smrg ntohs(sin6->sin6_port)); 147873143b9aSmrg 147973143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 148073143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 148173143b9aSmrg "tcp") == 0) { 148273143b9aSmrg XtransConnInfo newciptr; 148373143b9aSmrg 148473143b9aSmrg /* 148573143b9aSmrg * Close the IPv4 socket and try to open an IPv6 socket. 148673143b9aSmrg */ 148773143b9aSmrg TRANS(SocketINETClose)(ciptr); 148873143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 148973143b9aSmrg "tcp", "tcp", host, port, -1); 149073143b9aSmrg if (newciptr) 149173143b9aSmrg ciptr->fd = newciptr->fd; 149273143b9aSmrg if (!newciptr || 149373143b9aSmrg Sockettrans2devtab[newciptr->index].family != 149473143b9aSmrg AF_INET6) { 149573143b9aSmrg socketaddr = NULL; 1496fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv6 " 1497fe567363Smrg "socket for IPv6 address\n"); 149873143b9aSmrg } 149973143b9aSmrg if (newciptr) 1500fe567363Smrg free(newciptr); 150173143b9aSmrg } 150273143b9aSmrg else 150373143b9aSmrg { 150473143b9aSmrg socketaddr = NULL; 1505fe567363Smrg prmsg (4,"SocketINETConnect() Skipping IPv6 address\n"); 150673143b9aSmrg } 150773143b9aSmrg } 150873143b9aSmrg } else { 150973143b9aSmrg socketaddr = NULL; /* Unsupported address type */ 151073143b9aSmrg } 151173143b9aSmrg if (socketaddr == NULL) { 151273143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 151373143b9aSmrg } 1514fe567363Smrg } 1515b53e5eeaSmrg } 1516b53e5eeaSmrg#else 151773143b9aSmrg { 151873143b9aSmrg /* 151973143b9aSmrg * Build the socket name. 152073143b9aSmrg */ 152173143b9aSmrg 152273143b9aSmrg#ifdef BSD44SOCKETS 152373143b9aSmrg sockname.sin_len = sizeof (struct sockaddr_in); 152473143b9aSmrg#endif 152573143b9aSmrg sockname.sin_family = AF_INET; 152673143b9aSmrg 152773143b9aSmrg /* 152873143b9aSmrg * fill in sin_addr 152973143b9aSmrg */ 153073143b9aSmrg 153173143b9aSmrg#ifndef INADDR_NONE 153273143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff) 153373143b9aSmrg#endif 153473143b9aSmrg 153573143b9aSmrg /* check for ww.xx.yy.zz host string */ 153673143b9aSmrg 153773143b9aSmrg if (isascii (host[0]) && isdigit (host[0])) { 153873143b9aSmrg tmpaddr = inet_addr (host); /* returns network byte order */ 153973143b9aSmrg } else { 154073143b9aSmrg tmpaddr = INADDR_NONE; 154173143b9aSmrg } 154273143b9aSmrg 154381d6fa61Srin prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr); 154473143b9aSmrg 154573143b9aSmrg if (tmpaddr == INADDR_NONE) { 154673143b9aSmrg if ((hostp = _XGethostbyname(host,hparams)) == NULL) { 1547fe567363Smrg prmsg (1,"SocketINETConnect: Can't get address for %s\n", 1548fe567363Smrg host); 154973143b9aSmrg ESET(EINVAL); 155073143b9aSmrg return TRANS_CONNECT_FAILED; 155173143b9aSmrg } 155273143b9aSmrg if (hostp->h_addrtype != AF_INET) { /* is IP host? */ 1553fe567363Smrg prmsg (1,"SocketINETConnect: not INET host%s\n", host); 155473143b9aSmrg ESET(EPROTOTYPE); 155573143b9aSmrg return TRANS_CONNECT_FAILED; 155673143b9aSmrg } 1557fe567363Smrg 155873143b9aSmrg memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, 155973143b9aSmrg sizeof (sockname.sin_addr)); 156073143b9aSmrg 156173143b9aSmrg } else { 156273143b9aSmrg sockname.sin_addr.s_addr = tmpaddr; 156373143b9aSmrg } 156473143b9aSmrg 156573143b9aSmrg /* 156673143b9aSmrg * fill in sin_port 156773143b9aSmrg */ 156873143b9aSmrg 156973143b9aSmrg /* Check for number in the port string */ 157073143b9aSmrg 157173143b9aSmrg if (!is_numeric (port)) { 157273143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) { 1573fe567363Smrg prmsg (1,"SocketINETConnect: can't get service for %s\n", 1574fe567363Smrg port); 157573143b9aSmrg return TRANS_CONNECT_FAILED; 157673143b9aSmrg } 157773143b9aSmrg sockname.sin_port = htons (servp->s_port); 157873143b9aSmrg } else { 1579fe567363Smrg long tmpport = strtol (port, (char**)NULL, 10); 158073143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 158173143b9aSmrg return TRANS_CONNECT_FAILED; 158273143b9aSmrg sockname.sin_port = htons (((unsigned short) tmpport)); 158373143b9aSmrg } 158473143b9aSmrg 1585fe567363Smrg prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n", 1586fe567363Smrg ntohs(sockname.sin_port)); 158773143b9aSmrg socketaddr = (struct sockaddr *) &sockname; 158873143b9aSmrg socketaddrlen = sizeof(sockname); 158973143b9aSmrg } 1590b53e5eeaSmrg#endif 159173143b9aSmrg 159273143b9aSmrg /* 159373143b9aSmrg * Turn on socket keepalive so the client process will eventually 159473143b9aSmrg * be notified with a SIGPIPE signal if the display server fails 159573143b9aSmrg * to respond to a periodic transmission of messages 159673143b9aSmrg * on the connected socket. 159773143b9aSmrg * This is useful to avoid hung application processes when the 159873143b9aSmrg * processes are not spawned from the xdm session and 159973143b9aSmrg * the display server terminates abnormally. 160073143b9aSmrg * (Someone turned off the power switch.) 160173143b9aSmrg */ 160273143b9aSmrg 160373143b9aSmrg { 160473143b9aSmrg int tmp = 1; 160573143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE, 160673143b9aSmrg (char *) &tmp, sizeof (int)); 160773143b9aSmrg } 160873143b9aSmrg 160973143b9aSmrg /* 161073143b9aSmrg * Do the connect() 161173143b9aSmrg */ 161273143b9aSmrg 161373143b9aSmrg if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) 161473143b9aSmrg { 161573143b9aSmrg#ifdef WIN32 161673143b9aSmrg int olderrno = WSAGetLastError(); 161773143b9aSmrg#else 161873143b9aSmrg int olderrno = errno; 161973143b9aSmrg#endif 162073143b9aSmrg 162173143b9aSmrg /* 162273143b9aSmrg * If the error was ECONNREFUSED, the server may be overloaded 162373143b9aSmrg * and we should try again. 162473143b9aSmrg * 162573143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 162673143b9aSmrg * was non-blocking and we should poll using select 162773143b9aSmrg * 162873143b9aSmrg * If the error was EINTR, the connect was interrupted and we 162973143b9aSmrg * should try again. 163073143b9aSmrg * 163173143b9aSmrg * If multiple addresses are found for a host then we should 163273143b9aSmrg * try to connect again with a different address for a larger 163373143b9aSmrg * number of errors that made us quit before, since those 163473143b9aSmrg * could be caused by trying to use an IPv6 address to contact 163573143b9aSmrg * a machine with an IPv4-only server or other reasons that 1636fe567363Smrg * only affect one of a set of addresses. 163773143b9aSmrg */ 163873143b9aSmrg 163973143b9aSmrg if (olderrno == ECONNREFUSED || olderrno == EINTR 164073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1641b53e5eeaSmrg || (((addrlist->addr->ai_next != NULL) || 164273143b9aSmrg (addrlist->addr != addrlist->firstaddr)) && 164373143b9aSmrg (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT || 164473143b9aSmrg olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT 164573143b9aSmrg#if defined(EHOSTDOWN) 164673143b9aSmrg || olderrno == EHOSTDOWN 164773143b9aSmrg#endif 164873143b9aSmrg )) 164973143b9aSmrg#endif 165073143b9aSmrg ) 165173143b9aSmrg res = TRANS_TRY_CONNECT_AGAIN; 165273143b9aSmrg else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 165373143b9aSmrg res = TRANS_IN_PROGRESS; 165473143b9aSmrg else 165573143b9aSmrg { 1656fe567363Smrg prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n", 1657fe567363Smrg olderrno); 165873143b9aSmrg 1659fe567363Smrg res = TRANS_CONNECT_FAILED; 166073143b9aSmrg } 166173143b9aSmrg } else { 166273143b9aSmrg res = 0; 1663fe567363Smrg 166473143b9aSmrg 166573143b9aSmrg /* 166673143b9aSmrg * Sync up the address fields of ciptr. 166773143b9aSmrg */ 1668fe567363Smrg 166973143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 167073143b9aSmrg { 1671fe567363Smrg prmsg (1, 1672fe567363Smrg "SocketINETConnect: ...SocketINETGetAddr() failed:\n"); 167373143b9aSmrg res = TRANS_CONNECT_FAILED; 167473143b9aSmrg } 167573143b9aSmrg 167673143b9aSmrg else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) 167773143b9aSmrg { 1678fe567363Smrg prmsg (1, 1679fe567363Smrg "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n"); 168073143b9aSmrg res = TRANS_CONNECT_FAILED; 168173143b9aSmrg } 168273143b9aSmrg } 168373143b9aSmrg 168473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1685b53e5eeaSmrg if (res != 0) { 168673143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 168773143b9aSmrg } 168873143b9aSmrg#endif 168973143b9aSmrg 169073143b9aSmrg return res; 169173143b9aSmrg} 169273143b9aSmrg 169373143b9aSmrg#endif /* TCPCONN */ 169473143b9aSmrg 169573143b9aSmrg 169673143b9aSmrg 169773143b9aSmrg#ifdef UNIXCONN 169873143b9aSmrg 169973143b9aSmrg/* 170073143b9aSmrg * Make sure 'host' is really local. 170173143b9aSmrg */ 170273143b9aSmrg 170373143b9aSmrgstatic int 17046a3641a6SsnjUnixHostReallyLocal (const char *host) 170573143b9aSmrg 170673143b9aSmrg{ 170773143b9aSmrg char hostnamebuf[256]; 170873143b9aSmrg 170973143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 171073143b9aSmrg 171173143b9aSmrg if (strcmp (hostnamebuf, host) == 0) 171273143b9aSmrg { 171373143b9aSmrg return (1); 1714b53e5eeaSmrg } else { 171573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 171673143b9aSmrg struct addrinfo *localhostaddr; 171773143b9aSmrg struct addrinfo *otherhostaddr; 171873143b9aSmrg struct addrinfo *i, *j; 171973143b9aSmrg int equiv = 0; 172073143b9aSmrg 172173143b9aSmrg if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0) 172273143b9aSmrg return 0; 172373143b9aSmrg if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) { 172473143b9aSmrg freeaddrinfo(localhostaddr); 172573143b9aSmrg return 0; 172673143b9aSmrg } 172773143b9aSmrg 172873143b9aSmrg for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) { 172973143b9aSmrg for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) { 173073143b9aSmrg if (i->ai_family == j->ai_family) { 173173143b9aSmrg if (i->ai_family == AF_INET) { 1732fe567363Smrg struct sockaddr_in *sinA 173373143b9aSmrg = (struct sockaddr_in *) i->ai_addr; 173473143b9aSmrg struct sockaddr_in *sinB 173573143b9aSmrg = (struct sockaddr_in *) j->ai_addr; 173673143b9aSmrg struct in_addr *A = &sinA->sin_addr; 173773143b9aSmrg struct in_addr *B = &sinB->sin_addr; 173873143b9aSmrg 173973143b9aSmrg if (memcmp(A,B,sizeof(struct in_addr)) == 0) { 174073143b9aSmrg equiv = 1; 174173143b9aSmrg } 174273143b9aSmrg } else if (i->ai_family == AF_INET6) { 1743fe567363Smrg struct sockaddr_in6 *sinA 174473143b9aSmrg = (struct sockaddr_in6 *) i->ai_addr; 1745fe567363Smrg struct sockaddr_in6 *sinB 174673143b9aSmrg = (struct sockaddr_in6 *) j->ai_addr; 174773143b9aSmrg struct in6_addr *A = &sinA->sin6_addr; 174873143b9aSmrg struct in6_addr *B = &sinB->sin6_addr; 174973143b9aSmrg 175073143b9aSmrg if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { 175173143b9aSmrg equiv = 1; 175273143b9aSmrg } 175373143b9aSmrg } 175473143b9aSmrg } 175573143b9aSmrg } 175673143b9aSmrg } 1757fe567363Smrg 175873143b9aSmrg freeaddrinfo(localhostaddr); 175973143b9aSmrg freeaddrinfo(otherhostaddr); 176073143b9aSmrg return equiv; 1761b53e5eeaSmrg#else 176273143b9aSmrg /* 176373143b9aSmrg * A host may have more than one network address. If any of the 176473143b9aSmrg * network addresses of 'host' (specified to the connect call) 176573143b9aSmrg * match any of the network addresses of 'hostname' (determined 176673143b9aSmrg * by TRANS(GetHostname)), then the two hostnames are equivalent, 176773143b9aSmrg * and we know that 'host' is really a local host. 176873143b9aSmrg */ 176973143b9aSmrg char specified_local_addr_list[10][4]; 177073143b9aSmrg int scount, equiv, i, j; 177173143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 177273143b9aSmrg _Xgethostbynameparams hparams; 177373143b9aSmrg#endif 177473143b9aSmrg struct hostent *hostp; 177573143b9aSmrg 177673143b9aSmrg if ((hostp = _XGethostbyname (host,hparams)) == NULL) 177773143b9aSmrg return (0); 177873143b9aSmrg 177973143b9aSmrg scount = 0; 178073143b9aSmrg while (hostp->h_addr_list[scount] && scount <= 8) 178173143b9aSmrg { 178273143b9aSmrg /* 178373143b9aSmrg * The 2nd call to gethostname() overrides the data 178473143b9aSmrg * from the 1st call, so we must save the address list. 178573143b9aSmrg */ 178673143b9aSmrg 1787fe567363Smrg specified_local_addr_list[scount][0] = 178873143b9aSmrg hostp->h_addr_list[scount][0]; 1789fe567363Smrg specified_local_addr_list[scount][1] = 179073143b9aSmrg hostp->h_addr_list[scount][1]; 1791fe567363Smrg specified_local_addr_list[scount][2] = 179273143b9aSmrg hostp->h_addr_list[scount][2]; 1793fe567363Smrg specified_local_addr_list[scount][3] = 179473143b9aSmrg hostp->h_addr_list[scount][3]; 179573143b9aSmrg scount++; 179673143b9aSmrg } 179773143b9aSmrg if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) 179873143b9aSmrg return (0); 179973143b9aSmrg 180073143b9aSmrg equiv = 0; 180173143b9aSmrg i = 0; 180273143b9aSmrg 180373143b9aSmrg while (i < scount && !equiv) 180473143b9aSmrg { 180573143b9aSmrg j = 0; 180673143b9aSmrg 180773143b9aSmrg while (hostp->h_addr_list[j]) 180873143b9aSmrg { 1809fe567363Smrg if ((specified_local_addr_list[i][0] == 181073143b9aSmrg hostp->h_addr_list[j][0]) && 1811fe567363Smrg (specified_local_addr_list[i][1] == 181273143b9aSmrg hostp->h_addr_list[j][1]) && 1813fe567363Smrg (specified_local_addr_list[i][2] == 181473143b9aSmrg hostp->h_addr_list[j][2]) && 1815fe567363Smrg (specified_local_addr_list[i][3] == 181673143b9aSmrg hostp->h_addr_list[j][3])) 181773143b9aSmrg { 181873143b9aSmrg /* They're equal, so we're done */ 1819fe567363Smrg 182073143b9aSmrg equiv = 1; 182173143b9aSmrg break; 182273143b9aSmrg } 182373143b9aSmrg 182473143b9aSmrg j++; 182573143b9aSmrg } 182673143b9aSmrg 182773143b9aSmrg i++; 182873143b9aSmrg } 182973143b9aSmrg return (equiv); 1830b53e5eeaSmrg#endif 183173143b9aSmrg } 183273143b9aSmrg} 183373143b9aSmrg 183473143b9aSmrgstatic int 18356a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, 18366a3641a6Ssnj const char *host, const char *port) 183773143b9aSmrg 183873143b9aSmrg{ 183973143b9aSmrg struct sockaddr_un sockname; 184073143b9aSmrg SOCKLEN_T namelen; 184173143b9aSmrg 1842fe567363Smrg prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); 1843fe567363Smrg 184473143b9aSmrg /* 184573143b9aSmrg * Make sure 'host' is really local. If not, we return failure. 184673143b9aSmrg * The reason we make this check is because a process may advertise 184773143b9aSmrg * a "local" network ID for which it can accept connections, but if 184873143b9aSmrg * a process on a remote machine tries to connect to this network ID, 184973143b9aSmrg * we know for sure it will fail. 185073143b9aSmrg */ 185173143b9aSmrg 185273143b9aSmrg if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) 185373143b9aSmrg { 1854fe567363Smrg prmsg (1, 185573143b9aSmrg "SocketUNIXConnect: Cannot connect to non-local host %s\n", 1856fe567363Smrg host); 185773143b9aSmrg return TRANS_CONNECT_FAILED; 185873143b9aSmrg } 185973143b9aSmrg 186073143b9aSmrg 186173143b9aSmrg /* 186273143b9aSmrg * Check the port. 186373143b9aSmrg */ 186473143b9aSmrg 186573143b9aSmrg if (!port || !*port) 186673143b9aSmrg { 1867fe567363Smrg prmsg (1,"SocketUNIXConnect: Missing port specification\n"); 186873143b9aSmrg return TRANS_CONNECT_FAILED; 186973143b9aSmrg } 187073143b9aSmrg 187173143b9aSmrg /* 187273143b9aSmrg * Build the socket name. 187373143b9aSmrg */ 1874fe567363Smrg 187573143b9aSmrg sockname.sun_family = AF_UNIX; 187673143b9aSmrg 1877a773ec55Smrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, 0) != 0) { 1878fe567363Smrg prmsg (1, "SocketUNIXConnect: path too long\n"); 187973143b9aSmrg return TRANS_CONNECT_FAILED; 188073143b9aSmrg } 188173143b9aSmrg 1882a773ec55Smrg#if defined(BSD44SOCKETS) 188373143b9aSmrg sockname.sun_len = strlen (sockname.sun_path); 188473143b9aSmrg#endif 188573143b9aSmrg 188673143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 188773143b9aSmrg namelen = SUN_LEN (&sockname); 188873143b9aSmrg#else 188973143b9aSmrg namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 189073143b9aSmrg#endif 189173143b9aSmrg 189273143b9aSmrg 189373143b9aSmrg /* 189473143b9aSmrg * Do the connect() 189573143b9aSmrg */ 189673143b9aSmrg 189773143b9aSmrg if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) 189873143b9aSmrg { 189973143b9aSmrg int olderrno = errno; 190073143b9aSmrg int connected = 0; 1901fe567363Smrg 190273143b9aSmrg if (!connected) 190373143b9aSmrg { 190473143b9aSmrg errno = olderrno; 1905fe567363Smrg 190673143b9aSmrg /* 190773143b9aSmrg * If the error was ENOENT, the server may be starting up; we used 190873143b9aSmrg * to suggest to try again in this case with 190973143b9aSmrg * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for 191073143b9aSmrg * processes still referencing stale sockets in their environment. 191173143b9aSmrg * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it 191273143b9aSmrg * is suggested that higher level stacks handle retries on their 191373143b9aSmrg * level when they face a slow starting server. 191473143b9aSmrg * 191573143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 191673143b9aSmrg * was non-blocking and we should poll using select 191773143b9aSmrg * 191873143b9aSmrg * If the error was EINTR, the connect was interrupted and we 191973143b9aSmrg * should try again. 192073143b9aSmrg */ 192173143b9aSmrg 192273143b9aSmrg if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 192373143b9aSmrg return TRANS_IN_PROGRESS; 192473143b9aSmrg else if (olderrno == EINTR) 192573143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 1926a773ec55Smrg else { 1927fe567363Smrg prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n", 1928fe567363Smrg EGET()); 192973143b9aSmrg 193073143b9aSmrg return TRANS_CONNECT_FAILED; 193173143b9aSmrg } 193273143b9aSmrg } 193373143b9aSmrg } 193473143b9aSmrg 193573143b9aSmrg /* 193673143b9aSmrg * Get the socket name and the peer name from the connect socket, 193773143b9aSmrg * since this is unix domain. 193873143b9aSmrg */ 193973143b9aSmrg 1940fe567363Smrg if ((ciptr->addr = malloc(namelen)) == NULL || 1941fe567363Smrg (ciptr->peeraddr = malloc(namelen)) == NULL) 194273143b9aSmrg { 1943fe567363Smrg prmsg (1, 1944fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 194573143b9aSmrg return TRANS_CONNECT_FAILED; 194673143b9aSmrg } 194773143b9aSmrg 194873143b9aSmrg ciptr->family = AF_UNIX; 194973143b9aSmrg ciptr->addrlen = namelen; 195073143b9aSmrg ciptr->peeraddrlen = namelen; 195173143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 195273143b9aSmrg memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); 195373143b9aSmrg 195473143b9aSmrg return 0; 195573143b9aSmrg} 195673143b9aSmrg 195773143b9aSmrg#endif /* UNIXCONN */ 195873143b9aSmrg 195973143b9aSmrg#endif /* TRANS_CLIENT */ 196073143b9aSmrg 196173143b9aSmrg 196273143b9aSmrgstatic int 196373143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 196473143b9aSmrg 196573143b9aSmrg{ 1966fe567363Smrg prmsg (2,"SocketBytesReadable(%p,%d,%p)\n", 196773143b9aSmrg ciptr, ciptr->fd, pend); 196873143b9aSmrg#ifdef WIN32 196973143b9aSmrg { 197073143b9aSmrg int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); 197173143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 197273143b9aSmrg return ret; 197373143b9aSmrg } 197473143b9aSmrg#else 197573143b9aSmrg return ioctl (ciptr->fd, FIONREAD, (char *) pend); 197673143b9aSmrg#endif /* WIN32 */ 197773143b9aSmrg} 197873143b9aSmrg 197975ebec6dSmrg#if XTRANS_SEND_FDS 198075ebec6dSmrg 198175ebec6dSmrgstatic void 198275ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close) 198375ebec6dSmrg{ 198475ebec6dSmrg struct _XtransConnFd *cf, *new; 198575ebec6dSmrg 198675ebec6dSmrg new = malloc (sizeof (struct _XtransConnFd)); 198775ebec6dSmrg if (!new) { 198875ebec6dSmrg /* XXX mark connection as broken */ 198975ebec6dSmrg close(fd); 199075ebec6dSmrg return; 199175ebec6dSmrg } 199275ebec6dSmrg new->next = 0; 199375ebec6dSmrg new->fd = fd; 199475ebec6dSmrg new->do_close = do_close; 199575ebec6dSmrg /* search to end of list */ 199675ebec6dSmrg for (; (cf = *prev); prev = &(cf->next)); 199775ebec6dSmrg *prev = new; 199875ebec6dSmrg} 199973143b9aSmrg 200073143b9aSmrgstatic int 200175ebec6dSmrgremoveFd(struct _XtransConnFd **prev) 200275ebec6dSmrg{ 200375ebec6dSmrg struct _XtransConnFd *cf; 200475ebec6dSmrg int fd; 200575ebec6dSmrg 200675ebec6dSmrg if ((cf = *prev)) { 200775ebec6dSmrg *prev = cf->next; 200875ebec6dSmrg fd = cf->fd; 200975ebec6dSmrg free(cf); 201075ebec6dSmrg } else 201175ebec6dSmrg fd = -1; 201275ebec6dSmrg return fd; 201375ebec6dSmrg} 201473143b9aSmrg 201575ebec6dSmrgstatic void 201675ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) 201773143b9aSmrg{ 201875ebec6dSmrg struct _XtransConnFd *cf, *next; 201973143b9aSmrg 202075ebec6dSmrg for (cf = *prev; cf != upto; cf = next) { 202175ebec6dSmrg next = cf->next; 202275ebec6dSmrg if (do_close || cf->do_close) 202375ebec6dSmrg close(cf->fd); 202475ebec6dSmrg free(cf); 202573143b9aSmrg } 202675ebec6dSmrg *prev = upto; 202773143b9aSmrg} 202873143b9aSmrg 202975ebec6dSmrgstatic void 203075ebec6dSmrgcleanupFds(XtransConnInfo ciptr) 203175ebec6dSmrg{ 203275ebec6dSmrg /* Clean up the send list but don't close the fds */ 203375ebec6dSmrg discardFd(&ciptr->send_fds, NULL, 0); 203475ebec6dSmrg /* Clean up the recv list and *do* close the fds */ 203575ebec6dSmrg discardFd(&ciptr->recv_fds, NULL, 1); 203675ebec6dSmrg} 203773143b9aSmrg 203873143b9aSmrgstatic int 203975ebec6dSmrgnFd(struct _XtransConnFd **prev) 204075ebec6dSmrg{ 204175ebec6dSmrg struct _XtransConnFd *cf; 204275ebec6dSmrg int n = 0; 204375ebec6dSmrg 204475ebec6dSmrg for (cf = *prev; cf; cf = cf->next) 204575ebec6dSmrg n++; 204675ebec6dSmrg return n; 204775ebec6dSmrg} 204873143b9aSmrg 204975ebec6dSmrgstatic int 205075ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr) 205173143b9aSmrg{ 205275ebec6dSmrg prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); 205375ebec6dSmrg return removeFd(&ciptr->recv_fds); 205475ebec6dSmrg} 205575ebec6dSmrg 205675ebec6dSmrgstatic int 205775ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) 205875ebec6dSmrg{ 205975ebec6dSmrg appendFd(&ciptr->send_fds, fd, do_close); 206075ebec6dSmrg return 0; 206175ebec6dSmrg} 206275ebec6dSmrg 206375ebec6dSmrgstatic int 206475ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) 206575ebec6dSmrg{ 206675ebec6dSmrg errno = EINVAL; 206775ebec6dSmrg return -1; 206875ebec6dSmrg} 206975ebec6dSmrg 207075ebec6dSmrgstatic int 207175ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) 207275ebec6dSmrg{ 207375ebec6dSmrg errno = EINVAL; 207475ebec6dSmrg return -1; 207575ebec6dSmrg} 207675ebec6dSmrg 207775ebec6dSmrg#define MAX_FDS 128 207875ebec6dSmrg 207975ebec6dSmrgunion fd_pass { 208075ebec6dSmrg struct cmsghdr cmsghdr; 208175ebec6dSmrg char buf[CMSG_SPACE(MAX_FDS * sizeof(int))]; 208275ebec6dSmrg}; 208375ebec6dSmrg 208475ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 208575ebec6dSmrg 208675ebec6dSmrgstatic int 208775ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) 208875ebec6dSmrg 208975ebec6dSmrg{ 209075ebec6dSmrg prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); 209173143b9aSmrg 2092fe567363Smrg#if defined(WIN32) 209373143b9aSmrg { 209475ebec6dSmrg int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); 209573143b9aSmrg#ifdef WIN32 209673143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 209773143b9aSmrg#endif 209873143b9aSmrg return ret; 209973143b9aSmrg } 210073143b9aSmrg#else 210175ebec6dSmrg#if XTRANS_SEND_FDS 210275ebec6dSmrg { 210375ebec6dSmrg struct iovec iov = { 210475ebec6dSmrg .iov_base = buf, 210575ebec6dSmrg .iov_len = size 210675ebec6dSmrg }; 210775ebec6dSmrg union fd_pass cmsgbuf; 210875ebec6dSmrg struct msghdr msg = { 210975ebec6dSmrg .msg_name = NULL, 211075ebec6dSmrg .msg_namelen = 0, 211175ebec6dSmrg .msg_iov = &iov, 211275ebec6dSmrg .msg_iovlen = 1, 211375ebec6dSmrg .msg_control = cmsgbuf.buf, 211475ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 211575ebec6dSmrg }; 211675ebec6dSmrg 211775ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 211875ebec6dSmrg if (size >= 0) { 211975ebec6dSmrg struct cmsghdr *hdr; 212075ebec6dSmrg 212175ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 212275ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 212375ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 212475ebec6dSmrg int i; 212575ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 212675ebec6dSmrg 212775ebec6dSmrg for (i = 0; i < nfd; i++) 212875ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 212975ebec6dSmrg } 213075ebec6dSmrg } 213175ebec6dSmrg } 213275ebec6dSmrg return size; 213375ebec6dSmrg } 213475ebec6dSmrg#else 213575ebec6dSmrg return read(ciptr->fd, buf, size); 213675ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 213773143b9aSmrg#endif /* WIN32 */ 213873143b9aSmrg} 213973143b9aSmrg 214073143b9aSmrgstatic int 214173143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) 214273143b9aSmrg 214373143b9aSmrg{ 2144fe567363Smrg prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); 214573143b9aSmrg 214675ebec6dSmrg#if XTRANS_SEND_FDS 214775ebec6dSmrg { 214875ebec6dSmrg union fd_pass cmsgbuf; 214975ebec6dSmrg struct msghdr msg = { 215075ebec6dSmrg .msg_name = NULL, 215175ebec6dSmrg .msg_namelen = 0, 215275ebec6dSmrg .msg_iov = buf, 215375ebec6dSmrg .msg_iovlen = size, 215475ebec6dSmrg .msg_control = cmsgbuf.buf, 215575ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 215675ebec6dSmrg }; 215775ebec6dSmrg 215875ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 215975ebec6dSmrg if (size >= 0) { 216075ebec6dSmrg struct cmsghdr *hdr; 216175ebec6dSmrg 216275ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 216375ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 216475ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 216575ebec6dSmrg int i; 216675ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 216775ebec6dSmrg 216875ebec6dSmrg for (i = 0; i < nfd; i++) 216975ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 217075ebec6dSmrg } 217175ebec6dSmrg } 217275ebec6dSmrg } 217375ebec6dSmrg return size; 217475ebec6dSmrg } 217575ebec6dSmrg#else 217673143b9aSmrg return READV (ciptr, buf, size); 217775ebec6dSmrg#endif 217873143b9aSmrg} 217973143b9aSmrg 218073143b9aSmrg 218173143b9aSmrgstatic int 218273143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) 218373143b9aSmrg 218473143b9aSmrg{ 2185fe567363Smrg prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); 218673143b9aSmrg 218775ebec6dSmrg#if XTRANS_SEND_FDS 218875ebec6dSmrg if (ciptr->send_fds) 218975ebec6dSmrg { 219075ebec6dSmrg union fd_pass cmsgbuf; 219175ebec6dSmrg int nfd = nFd(&ciptr->send_fds); 219275ebec6dSmrg struct _XtransConnFd *cf = ciptr->send_fds; 219375ebec6dSmrg struct msghdr msg = { 219475ebec6dSmrg .msg_name = NULL, 219575ebec6dSmrg .msg_namelen = 0, 219675ebec6dSmrg .msg_iov = buf, 219775ebec6dSmrg .msg_iovlen = size, 219875ebec6dSmrg .msg_control = cmsgbuf.buf, 219975ebec6dSmrg .msg_controllen = CMSG_LEN(nfd * sizeof(int)) 220075ebec6dSmrg }; 220175ebec6dSmrg struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 220275ebec6dSmrg int i; 220375ebec6dSmrg int *fds; 220475ebec6dSmrg 220575ebec6dSmrg hdr->cmsg_len = msg.msg_controllen; 220675ebec6dSmrg hdr->cmsg_level = SOL_SOCKET; 220775ebec6dSmrg hdr->cmsg_type = SCM_RIGHTS; 220875ebec6dSmrg 220975ebec6dSmrg fds = (int *) CMSG_DATA(hdr); 221075ebec6dSmrg /* Set up fds */ 221175ebec6dSmrg for (i = 0; i < nfd; i++) { 221275ebec6dSmrg fds[i] = cf->fd; 221375ebec6dSmrg cf = cf->next; 221475ebec6dSmrg } 221575ebec6dSmrg 221675ebec6dSmrg i = sendmsg(ciptr->fd, &msg, 0); 221775ebec6dSmrg if (i > 0) 221875ebec6dSmrg discardFd(&ciptr->send_fds, cf, 0); 221975ebec6dSmrg return i; 222075ebec6dSmrg } 222175ebec6dSmrg#endif 222273143b9aSmrg return WRITEV (ciptr, buf, size); 222373143b9aSmrg} 222473143b9aSmrg 222573143b9aSmrg 222675ebec6dSmrgstatic int 222775ebec6dSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) 222875ebec6dSmrg 222975ebec6dSmrg{ 223075ebec6dSmrg prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); 223175ebec6dSmrg 223275ebec6dSmrg#if defined(WIN32) 223375ebec6dSmrg { 223475ebec6dSmrg int ret = send ((SOCKET)ciptr->fd, buf, size, 0); 223575ebec6dSmrg#ifdef WIN32 223675ebec6dSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 223775ebec6dSmrg#endif 223875ebec6dSmrg return ret; 223975ebec6dSmrg } 224075ebec6dSmrg#else 224175ebec6dSmrg#if XTRANS_SEND_FDS 224275ebec6dSmrg if (ciptr->send_fds) 224375ebec6dSmrg { 224475ebec6dSmrg struct iovec iov; 224575ebec6dSmrg 224675ebec6dSmrg iov.iov_base = buf; 224775ebec6dSmrg iov.iov_len = size; 224875ebec6dSmrg return TRANS(SocketWritev)(ciptr, &iov, 1); 224975ebec6dSmrg } 225075ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 225175ebec6dSmrg return write (ciptr->fd, buf, size); 225275ebec6dSmrg#endif /* WIN32 */ 225375ebec6dSmrg} 225475ebec6dSmrg 225573143b9aSmrgstatic int 225673143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr) 225773143b9aSmrg 225873143b9aSmrg{ 2259fe567363Smrg prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd); 226073143b9aSmrg 226173143b9aSmrg#ifdef WIN32 2262fe567363Smrg { 226373143b9aSmrg int ret = shutdown (ciptr->fd, 2); 226473143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 226573143b9aSmrg return ret; 226673143b9aSmrg } 226773143b9aSmrg#else 226873143b9aSmrg return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ 226973143b9aSmrg#endif 227073143b9aSmrg} 227173143b9aSmrg 227273143b9aSmrg 227373143b9aSmrg#ifdef TCPCONN 227473143b9aSmrgstatic int 227573143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr) 227673143b9aSmrg 227773143b9aSmrg{ 2278fe567363Smrg prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd); 227973143b9aSmrg 228073143b9aSmrg#ifdef WIN32 228173143b9aSmrg { 228273143b9aSmrg int ret = close (ciptr->fd); 228373143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 228473143b9aSmrg return ret; 228573143b9aSmrg } 228673143b9aSmrg#else 228773143b9aSmrg return close (ciptr->fd); 228873143b9aSmrg#endif 228973143b9aSmrg} 229073143b9aSmrg 229173143b9aSmrg#endif /* TCPCONN */ 229273143b9aSmrg 229373143b9aSmrg 229473143b9aSmrg#ifdef UNIXCONN 229573143b9aSmrgstatic int 229673143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr) 229773143b9aSmrg{ 229873143b9aSmrg /* 229973143b9aSmrg * If this is the server side, then once the socket is closed, 230073143b9aSmrg * it must be unlinked to completely close it 230173143b9aSmrg */ 230273143b9aSmrg 230373143b9aSmrg struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; 230473143b9aSmrg int ret; 230573143b9aSmrg 2306fe567363Smrg prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd); 230773143b9aSmrg 230875ebec6dSmrg#if XTRANS_SEND_FDS 230975ebec6dSmrg cleanupFds(ciptr); 231075ebec6dSmrg#endif 231173143b9aSmrg ret = close(ciptr->fd); 231273143b9aSmrg 231373143b9aSmrg if (ciptr->flags 231473143b9aSmrg && sockname 231573143b9aSmrg && sockname->sun_family == AF_UNIX 231673143b9aSmrg && sockname->sun_path[0]) 231773143b9aSmrg { 231873143b9aSmrg if (!(ciptr->flags & TRANS_NOUNLINK 231973143b9aSmrg || ciptr->transptr->flags & TRANS_ABSTRACT)) 232073143b9aSmrg unlink (sockname->sun_path); 232173143b9aSmrg } 232273143b9aSmrg 232373143b9aSmrg return ret; 232473143b9aSmrg} 232573143b9aSmrg 232673143b9aSmrgstatic int 232773143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) 232873143b9aSmrg 232973143b9aSmrg{ 233073143b9aSmrg /* 233173143b9aSmrg * Don't unlink path. 233273143b9aSmrg */ 233373143b9aSmrg 233473143b9aSmrg int ret; 233573143b9aSmrg 2336fe567363Smrg prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", 2337fe567363Smrg ciptr, ciptr->fd); 233873143b9aSmrg 233975ebec6dSmrg#if XTRANS_SEND_FDS 234075ebec6dSmrg cleanupFds(ciptr); 234175ebec6dSmrg#endif 234273143b9aSmrg ret = close(ciptr->fd); 234373143b9aSmrg 234473143b9aSmrg return ret; 234573143b9aSmrg} 234673143b9aSmrg 234773143b9aSmrg#endif /* UNIXCONN */ 234873143b9aSmrg 234973143b9aSmrg 235073143b9aSmrg#ifdef TCPCONN 235173143b9aSmrg# ifdef TRANS_SERVER 2352fe567363Smrgstatic const char* tcp_nolisten[] = { 235373143b9aSmrg "inet", 235473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 235573143b9aSmrg "inet6", 235673143b9aSmrg#endif 235773143b9aSmrg NULL 235873143b9aSmrg}; 235973143b9aSmrg# endif 236073143b9aSmrg 236173143b9aSmrgXtransport TRANS(SocketTCPFuncs) = { 236273143b9aSmrg /* Socket Interface */ 236373143b9aSmrg "tcp", 236473143b9aSmrg TRANS_ALIAS, 236573143b9aSmrg#ifdef TRANS_CLIENT 236673143b9aSmrg TRANS(SocketOpenCOTSClient), 236773143b9aSmrg#endif /* TRANS_CLIENT */ 236873143b9aSmrg#ifdef TRANS_SERVER 236973143b9aSmrg tcp_nolisten, 237073143b9aSmrg TRANS(SocketOpenCOTSServer), 237173143b9aSmrg#endif /* TRANS_SERVER */ 237273143b9aSmrg#ifdef TRANS_REOPEN 237373143b9aSmrg TRANS(SocketReopenCOTSServer), 237473143b9aSmrg#endif 237573143b9aSmrg TRANS(SocketSetOption), 237673143b9aSmrg#ifdef TRANS_SERVER 237773143b9aSmrg TRANS(SocketINETCreateListener), 237873143b9aSmrg NULL, /* ResetListener */ 237973143b9aSmrg TRANS(SocketINETAccept), 238073143b9aSmrg#endif /* TRANS_SERVER */ 238173143b9aSmrg#ifdef TRANS_CLIENT 238273143b9aSmrg TRANS(SocketINETConnect), 238373143b9aSmrg#endif /* TRANS_CLIENT */ 238473143b9aSmrg TRANS(SocketBytesReadable), 238573143b9aSmrg TRANS(SocketRead), 238673143b9aSmrg TRANS(SocketWrite), 238773143b9aSmrg TRANS(SocketReadv), 238873143b9aSmrg TRANS(SocketWritev), 238975ebec6dSmrg#if XTRANS_SEND_FDS 239075ebec6dSmrg TRANS(SocketSendFdInvalid), 239175ebec6dSmrg TRANS(SocketRecvFdInvalid), 239275ebec6dSmrg#endif 239373143b9aSmrg TRANS(SocketDisconnect), 239473143b9aSmrg TRANS(SocketINETClose), 239573143b9aSmrg TRANS(SocketINETClose), 239673143b9aSmrg }; 239773143b9aSmrg 239873143b9aSmrgXtransport TRANS(SocketINETFuncs) = { 239973143b9aSmrg /* Socket Interface */ 240073143b9aSmrg "inet", 240173143b9aSmrg 0, 240273143b9aSmrg#ifdef TRANS_CLIENT 240373143b9aSmrg TRANS(SocketOpenCOTSClient), 240473143b9aSmrg#endif /* TRANS_CLIENT */ 240573143b9aSmrg#ifdef TRANS_SERVER 240673143b9aSmrg NULL, 240773143b9aSmrg TRANS(SocketOpenCOTSServer), 240873143b9aSmrg#endif /* TRANS_SERVER */ 240973143b9aSmrg#ifdef TRANS_REOPEN 241073143b9aSmrg TRANS(SocketReopenCOTSServer), 241173143b9aSmrg#endif 241273143b9aSmrg TRANS(SocketSetOption), 241373143b9aSmrg#ifdef TRANS_SERVER 241473143b9aSmrg TRANS(SocketINETCreateListener), 241573143b9aSmrg NULL, /* ResetListener */ 241673143b9aSmrg TRANS(SocketINETAccept), 241773143b9aSmrg#endif /* TRANS_SERVER */ 241873143b9aSmrg#ifdef TRANS_CLIENT 241973143b9aSmrg TRANS(SocketINETConnect), 242073143b9aSmrg#endif /* TRANS_CLIENT */ 242173143b9aSmrg TRANS(SocketBytesReadable), 242273143b9aSmrg TRANS(SocketRead), 242373143b9aSmrg TRANS(SocketWrite), 242473143b9aSmrg TRANS(SocketReadv), 242573143b9aSmrg TRANS(SocketWritev), 242675ebec6dSmrg#if XTRANS_SEND_FDS 242775ebec6dSmrg TRANS(SocketSendFdInvalid), 242875ebec6dSmrg TRANS(SocketRecvFdInvalid), 242975ebec6dSmrg#endif 243073143b9aSmrg TRANS(SocketDisconnect), 243173143b9aSmrg TRANS(SocketINETClose), 243273143b9aSmrg TRANS(SocketINETClose), 243373143b9aSmrg }; 243473143b9aSmrg 243573143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 243673143b9aSmrgXtransport TRANS(SocketINET6Funcs) = { 243773143b9aSmrg /* Socket Interface */ 243873143b9aSmrg "inet6", 243973143b9aSmrg 0, 244073143b9aSmrg#ifdef TRANS_CLIENT 244173143b9aSmrg TRANS(SocketOpenCOTSClient), 244273143b9aSmrg#endif /* TRANS_CLIENT */ 244373143b9aSmrg#ifdef TRANS_SERVER 244473143b9aSmrg NULL, 244573143b9aSmrg TRANS(SocketOpenCOTSServer), 244673143b9aSmrg#endif /* TRANS_SERVER */ 244773143b9aSmrg#ifdef TRANS_REOPEN 244873143b9aSmrg TRANS(SocketReopenCOTSServer), 244973143b9aSmrg#endif 245073143b9aSmrg TRANS(SocketSetOption), 245173143b9aSmrg#ifdef TRANS_SERVER 245273143b9aSmrg TRANS(SocketINETCreateListener), 245373143b9aSmrg NULL, /* ResetListener */ 245473143b9aSmrg TRANS(SocketINETAccept), 245573143b9aSmrg#endif /* TRANS_SERVER */ 245673143b9aSmrg#ifdef TRANS_CLIENT 245773143b9aSmrg TRANS(SocketINETConnect), 245873143b9aSmrg#endif /* TRANS_CLIENT */ 245973143b9aSmrg TRANS(SocketBytesReadable), 246073143b9aSmrg TRANS(SocketRead), 246173143b9aSmrg TRANS(SocketWrite), 246273143b9aSmrg TRANS(SocketReadv), 246373143b9aSmrg TRANS(SocketWritev), 246475ebec6dSmrg#if XTRANS_SEND_FDS 246575ebec6dSmrg TRANS(SocketSendFdInvalid), 246675ebec6dSmrg TRANS(SocketRecvFdInvalid), 246775ebec6dSmrg#endif 246873143b9aSmrg TRANS(SocketDisconnect), 246973143b9aSmrg TRANS(SocketINETClose), 247073143b9aSmrg TRANS(SocketINETClose), 247173143b9aSmrg }; 247273143b9aSmrg#endif /* IPv6 */ 247373143b9aSmrg#endif /* TCPCONN */ 247473143b9aSmrg 247573143b9aSmrg#ifdef UNIXCONN 247673143b9aSmrg#if !defined(LOCALCONN) 247773143b9aSmrgXtransport TRANS(SocketLocalFuncs) = { 247873143b9aSmrg /* Socket Interface */ 247973143b9aSmrg "local", 248073143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 248173143b9aSmrg TRANS_ABSTRACT, 248273143b9aSmrg#else 248373143b9aSmrg 0, 248473143b9aSmrg#endif 248573143b9aSmrg#ifdef TRANS_CLIENT 248673143b9aSmrg TRANS(SocketOpenCOTSClient), 248773143b9aSmrg#endif /* TRANS_CLIENT */ 248873143b9aSmrg#ifdef TRANS_SERVER 248973143b9aSmrg NULL, 249073143b9aSmrg TRANS(SocketOpenCOTSServer), 249173143b9aSmrg#endif /* TRANS_SERVER */ 249273143b9aSmrg#ifdef TRANS_REOPEN 249373143b9aSmrg TRANS(SocketReopenCOTSServer), 249473143b9aSmrg#endif 249573143b9aSmrg TRANS(SocketSetOption), 249673143b9aSmrg#ifdef TRANS_SERVER 249773143b9aSmrg TRANS(SocketUNIXCreateListener), 249873143b9aSmrg TRANS(SocketUNIXResetListener), 249973143b9aSmrg TRANS(SocketUNIXAccept), 250073143b9aSmrg#endif /* TRANS_SERVER */ 250173143b9aSmrg#ifdef TRANS_CLIENT 250273143b9aSmrg TRANS(SocketUNIXConnect), 250373143b9aSmrg#endif /* TRANS_CLIENT */ 250473143b9aSmrg TRANS(SocketBytesReadable), 250573143b9aSmrg TRANS(SocketRead), 250673143b9aSmrg TRANS(SocketWrite), 250773143b9aSmrg TRANS(SocketReadv), 250873143b9aSmrg TRANS(SocketWritev), 250975ebec6dSmrg#if XTRANS_SEND_FDS 251075ebec6dSmrg TRANS(SocketSendFd), 251175ebec6dSmrg TRANS(SocketRecvFd), 251275ebec6dSmrg#endif 251373143b9aSmrg TRANS(SocketDisconnect), 251473143b9aSmrg TRANS(SocketUNIXClose), 251573143b9aSmrg TRANS(SocketUNIXCloseForCloning), 251673143b9aSmrg }; 251773143b9aSmrg#endif /* !LOCALCONN */ 251873143b9aSmrg# ifdef TRANS_SERVER 251973143b9aSmrg# if !defined(LOCALCONN) 252075ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL }; 252173143b9aSmrg# endif 252273143b9aSmrg# endif 2523fe567363Smrg 252473143b9aSmrgXtransport TRANS(SocketUNIXFuncs) = { 252573143b9aSmrg /* Socket Interface */ 252673143b9aSmrg "unix", 252773143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS) 252873143b9aSmrg TRANS_ALIAS, 252973143b9aSmrg#else 253073143b9aSmrg 0, 253173143b9aSmrg#endif 253273143b9aSmrg#ifdef TRANS_CLIENT 253373143b9aSmrg TRANS(SocketOpenCOTSClient), 253473143b9aSmrg#endif /* TRANS_CLIENT */ 253573143b9aSmrg#ifdef TRANS_SERVER 253673143b9aSmrg#if !defined(LOCALCONN) 253773143b9aSmrg unix_nolisten, 253873143b9aSmrg#else 253973143b9aSmrg NULL, 254073143b9aSmrg#endif 254173143b9aSmrg TRANS(SocketOpenCOTSServer), 254273143b9aSmrg#endif /* TRANS_SERVER */ 254373143b9aSmrg#ifdef TRANS_REOPEN 254473143b9aSmrg TRANS(SocketReopenCOTSServer), 254573143b9aSmrg#endif 254673143b9aSmrg TRANS(SocketSetOption), 254773143b9aSmrg#ifdef TRANS_SERVER 254873143b9aSmrg TRANS(SocketUNIXCreateListener), 254973143b9aSmrg TRANS(SocketUNIXResetListener), 255073143b9aSmrg TRANS(SocketUNIXAccept), 255173143b9aSmrg#endif /* TRANS_SERVER */ 255273143b9aSmrg#ifdef TRANS_CLIENT 255373143b9aSmrg TRANS(SocketUNIXConnect), 255473143b9aSmrg#endif /* TRANS_CLIENT */ 255573143b9aSmrg TRANS(SocketBytesReadable), 255673143b9aSmrg TRANS(SocketRead), 255773143b9aSmrg TRANS(SocketWrite), 255873143b9aSmrg TRANS(SocketReadv), 255973143b9aSmrg TRANS(SocketWritev), 256075ebec6dSmrg#if XTRANS_SEND_FDS 256175ebec6dSmrg TRANS(SocketSendFd), 256275ebec6dSmrg TRANS(SocketRecvFd), 256375ebec6dSmrg#endif 256473143b9aSmrg TRANS(SocketDisconnect), 256573143b9aSmrg TRANS(SocketUNIXClose), 256673143b9aSmrg TRANS(SocketUNIXCloseForCloning), 256773143b9aSmrg }; 256873143b9aSmrg 256973143b9aSmrg#endif /* UNIXCONN */ 2570