Xtranssock.c revision 7448d6e9
1af928962Smrg/* 2af928962Smrg * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. 3af928962Smrg * 4af928962Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5af928962Smrg * copy of this software and associated documentation files (the "Software"), 6af928962Smrg * to deal in the Software without restriction, including without limitation 7af928962Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af928962Smrg * and/or sell copies of the Software, and to permit persons to whom the 9af928962Smrg * Software is furnished to do so, subject to the following conditions: 10af928962Smrg * 11af928962Smrg * The above copyright notice and this permission notice (including the next 12af928962Smrg * paragraph) shall be included in all copies or substantial portions of the 13af928962Smrg * Software. 14af928962Smrg * 15af928962Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af928962Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af928962Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af928962Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af928962Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20af928962Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21af928962Smrg * DEALINGS IN THE SOFTWARE. 22af928962Smrg */ 2373143b9aSmrg/* 2473143b9aSmrg 2573143b9aSmrgCopyright 1993, 1994, 1998 The Open Group 2673143b9aSmrg 2773143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its 2873143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that 2973143b9aSmrgthe above copyright notice appear in all copies and that both that 3073143b9aSmrgcopyright notice and this permission notice appear in supporting 3173143b9aSmrgdocumentation. 3273143b9aSmrg 3373143b9aSmrgThe above copyright notice and this permission notice shall be included 3473143b9aSmrgin all copies or substantial portions of the Software. 3573143b9aSmrg 3673143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 3773143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3873143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 3973143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 4073143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 4173143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 4273143b9aSmrgOTHER DEALINGS IN THE SOFTWARE. 4373143b9aSmrg 4473143b9aSmrgExcept as contained in this notice, the name of the copyright holders shall 4573143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or 4673143b9aSmrgother dealings in this Software without prior written authorization 4773143b9aSmrgfrom the copyright holders. 4873143b9aSmrg 4973143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA 5073143b9aSmrg * 5173143b9aSmrg * All Rights Reserved 5273143b9aSmrg * 5373143b9aSmrg * Permission to use, copy, modify, and distribute this software and its 5473143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided 5573143b9aSmrg * that the above copyright notice appear in all copies and that both that 5673143b9aSmrg * copyright notice and this permission notice appear in supporting 5773143b9aSmrg * documentation, and that the name NCR not be used in advertising 5873143b9aSmrg * or publicity pertaining to distribution of the software without specific, 5973143b9aSmrg * written prior permission. NCR makes no representations about the 6073143b9aSmrg * suitability of this software for any purpose. It is provided "as is" 6173143b9aSmrg * without express or implied warranty. 6273143b9aSmrg * 6373143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 6473143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 6573143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR 6673143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 6773143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 6873143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 6973143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 7073143b9aSmrg */ 7173143b9aSmrg 7273143b9aSmrg#include <ctype.h> 7373143b9aSmrg#ifdef XTHREADS 7473143b9aSmrg#include <X11/Xthreads.h> 7573143b9aSmrg#endif 7673143b9aSmrg 7773143b9aSmrg#ifndef WIN32 7873143b9aSmrg 7973143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8073143b9aSmrg#include <sys/socket.h> 8173143b9aSmrg#include <netinet/in.h> 8273143b9aSmrg#include <arpa/inet.h> 8373143b9aSmrg#endif 8473143b9aSmrg 8573143b9aSmrg#if defined(TCPCONN) || defined(UNIXCONN) 8673143b9aSmrg#define X_INCLUDE_NETDB_H 8773143b9aSmrg#define XOS_USE_NO_LOCKING 8873143b9aSmrg#include <X11/Xos_r.h> 8973143b9aSmrg#endif 9073143b9aSmrg 9173143b9aSmrg#ifdef UNIXCONN 9273143b9aSmrg#ifndef X_NO_SYS_UN 9373143b9aSmrg#include <sys/un.h> 9473143b9aSmrg#endif 9573143b9aSmrg#include <sys/stat.h> 9673143b9aSmrg#endif 9773143b9aSmrg 9873143b9aSmrg 9973143b9aSmrg#ifndef NO_TCP_H 100fe567363Smrg#if defined(linux) || defined(__GLIBC__) 10173143b9aSmrg#include <sys/param.h> 10273143b9aSmrg#endif /* osf */ 10373143b9aSmrg#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 10473143b9aSmrg#include <sys/param.h> 10573143b9aSmrg#include <machine/endian.h> 10673143b9aSmrg#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */ 10773143b9aSmrg#include <netinet/tcp.h> 10873143b9aSmrg#endif /* !NO_TCP_H */ 10973143b9aSmrg 11073143b9aSmrg#include <sys/ioctl.h> 111e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 11273143b9aSmrg#include <sys/filio.h> 11373143b9aSmrg#endif 11473143b9aSmrg 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 14473143b9aSmrg#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 19973143b9aSmrg#ifdef UNIXCONN 20073143b9aSmrg 20173143b9aSmrg 20273143b9aSmrg#if defined(X11_t) 20373143b9aSmrg#define UNIX_PATH "/tmp/.X11-unix/X" 20473143b9aSmrg#define UNIX_DIR "/tmp/.X11-unix" 20573143b9aSmrg#endif /* X11_t */ 20673143b9aSmrg#if defined(XIM_t) 20773143b9aSmrg#define UNIX_PATH "/tmp/.XIM-unix/XIM" 20873143b9aSmrg#define UNIX_DIR "/tmp/.XIM-unix" 20973143b9aSmrg#endif /* XIM_t */ 21073143b9aSmrg#if defined(FS_t) || defined(FONT_t) 21173143b9aSmrg#define UNIX_PATH "/tmp/.font-unix/fs" 21273143b9aSmrg#define UNIX_DIR "/tmp/.font-unix" 21373143b9aSmrg#endif /* FS_t || FONT_t */ 21473143b9aSmrg#if defined(ICE_t) 21573143b9aSmrg#define UNIX_PATH "/tmp/.ICE-unix/" 21673143b9aSmrg#define UNIX_DIR "/tmp/.ICE-unix" 21773143b9aSmrg#endif /* ICE_t */ 21873143b9aSmrg 21973143b9aSmrg 22073143b9aSmrg#endif /* UNIXCONN */ 22173143b9aSmrg 22273143b9aSmrg#define PORTBUFSIZE 32 22373143b9aSmrg 22473143b9aSmrg#ifndef MAXHOSTNAMELEN 22573143b9aSmrg#define MAXHOSTNAMELEN 255 22673143b9aSmrg#endif 22773143b9aSmrg 22873143b9aSmrg#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6)) 22973143b9aSmrg# define SOCKLEN_T socklen_t 230e8a71cdfSmrg#elif defined(SVR4) || defined(__SVR4) || defined(__SCO__) 231fe567363Smrg# define SOCKLEN_T size_t 23273143b9aSmrg#else 23373143b9aSmrg# define SOCKLEN_T int 23473143b9aSmrg#endif 23573143b9aSmrg 23673143b9aSmrg/* 23773143b9aSmrg * These are some utility function used by the real interface function below. 23873143b9aSmrg */ 23973143b9aSmrg 24073143b9aSmrgstatic int 241fe567363SmrgTRANS(SocketSelectFamily) (int first, const char *family) 24273143b9aSmrg 24373143b9aSmrg{ 24473143b9aSmrg int i; 24573143b9aSmrg 246fe567363Smrg prmsg (3,"SocketSelectFamily(%s)\n", family); 24773143b9aSmrg 24873143b9aSmrg for (i = first + 1; i < NUMSOCKETFAMILIES;i++) 24973143b9aSmrg { 25073143b9aSmrg if (!strcmp (family, Sockettrans2devtab[i].transname)) 25173143b9aSmrg return i; 25273143b9aSmrg } 25373143b9aSmrg 25473143b9aSmrg return (first == -1 ? -2 : -1); 25573143b9aSmrg} 25673143b9aSmrg 25773143b9aSmrg 25873143b9aSmrg/* 25973143b9aSmrg * This function gets the local address of the socket and stores it in the 26073143b9aSmrg * XtransConnInfo structure for the connection. 26173143b9aSmrg */ 26273143b9aSmrg 26373143b9aSmrgstatic int 26473143b9aSmrgTRANS(SocketINETGetAddr) (XtransConnInfo ciptr) 26573143b9aSmrg 26673143b9aSmrg{ 26773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 26873143b9aSmrg struct sockaddr_storage socknamev6; 269b53e5eeaSmrg#else 27073143b9aSmrg struct sockaddr_in socknamev4; 271b53e5eeaSmrg#endif 27273143b9aSmrg void *socknamePtr; 27373143b9aSmrg SOCKLEN_T namelen; 27473143b9aSmrg 275fe567363Smrg prmsg (3,"SocketINETGetAddr(%p)\n", ciptr); 27673143b9aSmrg 27773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 278b53e5eeaSmrg namelen = sizeof(socknamev6); 279b53e5eeaSmrg socknamePtr = &socknamev6; 280b53e5eeaSmrg#else 281b53e5eeaSmrg namelen = sizeof(socknamev4); 282b53e5eeaSmrg socknamePtr = &socknamev4; 28373143b9aSmrg#endif 28473143b9aSmrg 28573143b9aSmrg bzero(socknamePtr, namelen); 286fe567363Smrg 28773143b9aSmrg if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr, 28873143b9aSmrg (void *)&namelen) < 0) 28973143b9aSmrg { 29073143b9aSmrg#ifdef WIN32 29173143b9aSmrg errno = WSAGetLastError(); 29273143b9aSmrg#endif 293fe567363Smrg prmsg (1,"SocketINETGetAddr: getsockname() failed: %d\n", 294fe567363Smrg EGET()); 29573143b9aSmrg return -1; 29673143b9aSmrg } 29773143b9aSmrg 29873143b9aSmrg /* 29973143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 30073143b9aSmrg */ 30173143b9aSmrg 302fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 30373143b9aSmrg { 304fe567363Smrg prmsg (1, 305fe567363Smrg "SocketINETGetAddr: Can't allocate space for the addr\n"); 30673143b9aSmrg return -1; 30773143b9aSmrg } 30873143b9aSmrg 30973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 310b53e5eeaSmrg ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family; 311b53e5eeaSmrg#else 312b53e5eeaSmrg ciptr->family = socknamev4.sin_family; 31373143b9aSmrg#endif 31473143b9aSmrg ciptr->addrlen = namelen; 31573143b9aSmrg memcpy (ciptr->addr, socknamePtr, ciptr->addrlen); 31673143b9aSmrg 31773143b9aSmrg return 0; 31873143b9aSmrg} 31973143b9aSmrg 32073143b9aSmrg 32173143b9aSmrg/* 32273143b9aSmrg * This function gets the remote address of the socket and stores it in the 32373143b9aSmrg * XtransConnInfo structure for the connection. 32473143b9aSmrg */ 32573143b9aSmrg 32673143b9aSmrgstatic int 32773143b9aSmrgTRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) 32873143b9aSmrg 32973143b9aSmrg{ 33073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 33173143b9aSmrg struct sockaddr_storage socknamev6; 33273143b9aSmrg#endif 33373143b9aSmrg struct sockaddr_in socknamev4; 33473143b9aSmrg void *socknamePtr; 33573143b9aSmrg SOCKLEN_T namelen; 33673143b9aSmrg 33773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 338b53e5eeaSmrg if (ciptr->family == AF_INET6) 33973143b9aSmrg { 34073143b9aSmrg namelen = sizeof(socknamev6); 34173143b9aSmrg socknamePtr = &socknamev6; 34273143b9aSmrg } 34373143b9aSmrg else 34473143b9aSmrg#endif 34573143b9aSmrg { 34673143b9aSmrg namelen = sizeof(socknamev4); 34773143b9aSmrg socknamePtr = &socknamev4; 34873143b9aSmrg } 34973143b9aSmrg 35073143b9aSmrg bzero(socknamePtr, namelen); 351fe567363Smrg 352fe567363Smrg prmsg (3,"SocketINETGetPeerAddr(%p)\n", ciptr); 35373143b9aSmrg 35473143b9aSmrg if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr, 35573143b9aSmrg (void *)&namelen) < 0) 35673143b9aSmrg { 35773143b9aSmrg#ifdef WIN32 35873143b9aSmrg errno = WSAGetLastError(); 35973143b9aSmrg#endif 360fe567363Smrg prmsg (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", 361fe567363Smrg EGET()); 36273143b9aSmrg return -1; 36373143b9aSmrg } 36473143b9aSmrg 36573143b9aSmrg /* 36673143b9aSmrg * Everything looks good: fill in the XtransConnInfo structure. 36773143b9aSmrg */ 36873143b9aSmrg 369fe567363Smrg if ((ciptr->peeraddr = malloc (namelen)) == NULL) 37073143b9aSmrg { 371fe567363Smrg prmsg (1, 372fe567363Smrg "SocketINETGetPeerAddr: Can't allocate space for the addr\n"); 37373143b9aSmrg return -1; 37473143b9aSmrg } 37573143b9aSmrg 37673143b9aSmrg ciptr->peeraddrlen = namelen; 37773143b9aSmrg memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen); 37873143b9aSmrg 37973143b9aSmrg return 0; 38073143b9aSmrg} 38173143b9aSmrg 38273143b9aSmrg 38373143b9aSmrgstatic XtransConnInfo 38473143b9aSmrgTRANS(SocketOpen) (int i, int type) 38573143b9aSmrg 38673143b9aSmrg{ 38773143b9aSmrg XtransConnInfo ciptr; 38873143b9aSmrg 389fe567363Smrg prmsg (3,"SocketOpen(%d,%d)\n", i, type); 39073143b9aSmrg 391fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 39273143b9aSmrg { 393fe567363Smrg prmsg (1, "SocketOpen: malloc failed\n"); 39473143b9aSmrg return NULL; 39573143b9aSmrg } 39673143b9aSmrg 39773143b9aSmrg if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type, 39873143b9aSmrg Sockettrans2devtab[i].protocol)) < 0 39973143b9aSmrg#ifndef WIN32 40073143b9aSmrg#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) 4018d4c0f7bSmrg || ciptr->fd >= sysconf(_SC_OPEN_MAX) 40273143b9aSmrg#endif 40373143b9aSmrg#endif 40473143b9aSmrg ) { 40573143b9aSmrg#ifdef WIN32 40673143b9aSmrg errno = WSAGetLastError(); 40773143b9aSmrg#endif 408fe567363Smrg prmsg (2, "SocketOpen: socket() failed for %s\n", 409fe567363Smrg Sockettrans2devtab[i].transname); 41073143b9aSmrg 411fe567363Smrg free (ciptr); 41273143b9aSmrg return NULL; 41373143b9aSmrg } 41473143b9aSmrg 41573143b9aSmrg#ifdef TCP_NODELAY 41673143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 41773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 41873143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 41973143b9aSmrg#endif 42073143b9aSmrg ) 42173143b9aSmrg { 42273143b9aSmrg /* 42373143b9aSmrg * turn off TCP coalescence for INET sockets 42473143b9aSmrg */ 42573143b9aSmrg 42673143b9aSmrg int tmp = 1; 42773143b9aSmrg setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY, 42873143b9aSmrg (char *) &tmp, sizeof (int)); 42973143b9aSmrg } 43073143b9aSmrg#endif 43173143b9aSmrg 4328a0d9095Smrg /* 4338a0d9095Smrg * Some systems provide a really small default buffer size for 4348a0d9095Smrg * UNIX sockets. Bump it up a bit such that large transfers don't 4358a0d9095Smrg * proceed at glacial speed. 4368a0d9095Smrg */ 4378a0d9095Smrg#ifdef SO_SNDBUF 4388a0d9095Smrg if (Sockettrans2devtab[i].family == AF_UNIX) 4398a0d9095Smrg { 4408a0d9095Smrg SOCKLEN_T len = sizeof (int); 4418a0d9095Smrg int val; 4428a0d9095Smrg 4438a0d9095Smrg if (getsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4448a0d9095Smrg (char *) &val, &len) == 0 && val < 64 * 1024) 4458a0d9095Smrg { 4468a0d9095Smrg val = 64 * 1024; 4478a0d9095Smrg setsockopt (ciptr->fd, SOL_SOCKET, SO_SNDBUF, 4488a0d9095Smrg (char *) &val, sizeof (int)); 4498a0d9095Smrg } 4508a0d9095Smrg } 4518a0d9095Smrg#endif 4528a0d9095Smrg 45373143b9aSmrg return ciptr; 45473143b9aSmrg} 45573143b9aSmrg 45673143b9aSmrg 45773143b9aSmrg#ifdef TRANS_REOPEN 45873143b9aSmrg 45973143b9aSmrgstatic XtransConnInfo 4606a3641a6SsnjTRANS(SocketReopen) (int i _X_UNUSED, int type, int fd, const char *port) 46173143b9aSmrg 46273143b9aSmrg{ 46373143b9aSmrg XtransConnInfo ciptr; 46473143b9aSmrg int portlen; 46573143b9aSmrg struct sockaddr *addr; 466fe567363Smrg size_t addrlen; 46773143b9aSmrg 468fe567363Smrg prmsg (3,"SocketReopen(%d,%d,%s)\n", type, fd, port); 46973143b9aSmrg 47073143b9aSmrg if (port == NULL) { 471fe567363Smrg prmsg (1, "SocketReopen: port was null!\n"); 47273143b9aSmrg return NULL; 47373143b9aSmrg } 47473143b9aSmrg 47573143b9aSmrg portlen = strlen(port) + 1; // include space for trailing null 47673143b9aSmrg#ifdef SOCK_MAXADDRLEN 47773143b9aSmrg if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) { 478fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 47973143b9aSmrg return NULL; 48073143b9aSmrg } 48173143b9aSmrg if (portlen < 14) portlen = 14; 48273143b9aSmrg#else 48373143b9aSmrg if (portlen < 0 || portlen > 14) { 484fe567363Smrg prmsg (1, "SocketReopen: invalid portlen %d\n", portlen); 48573143b9aSmrg return NULL; 48673143b9aSmrg } 48773143b9aSmrg#endif /*SOCK_MAXADDRLEN*/ 48873143b9aSmrg 489fe567363Smrg if ((ciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 49073143b9aSmrg { 491fe567363Smrg prmsg (1, "SocketReopen: malloc(ciptr) failed\n"); 49273143b9aSmrg return NULL; 49373143b9aSmrg } 49473143b9aSmrg 49573143b9aSmrg ciptr->fd = fd; 49673143b9aSmrg 497fe567363Smrg addrlen = portlen + offsetof(struct sockaddr, sa_data); 498fe567363Smrg if ((addr = calloc (1, addrlen)) == NULL) { 499fe567363Smrg prmsg (1, "SocketReopen: malloc(addr) failed\n"); 500fe567363Smrg free (ciptr); 50173143b9aSmrg return NULL; 50273143b9aSmrg } 5038d4c0f7bSmrg ciptr->addr = (char *) addr; 504fe567363Smrg ciptr->addrlen = addrlen; 50573143b9aSmrg 506fe567363Smrg if ((ciptr->peeraddr = calloc (1, addrlen)) == NULL) { 507fe567363Smrg prmsg (1, "SocketReopen: malloc(portaddr) failed\n"); 508fe567363Smrg free (addr); 509fe567363Smrg free (ciptr); 51073143b9aSmrg return NULL; 51173143b9aSmrg } 512fe567363Smrg ciptr->peeraddrlen = addrlen; 51373143b9aSmrg 51473143b9aSmrg /* Initialize ciptr structure as if it were a normally-opened unix socket */ 51573143b9aSmrg ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK; 51673143b9aSmrg#ifdef BSD44SOCKETS 517fe567363Smrg addr->sa_len = addrlen; 51873143b9aSmrg#endif 51973143b9aSmrg addr->sa_family = AF_UNIX; 5207448d6e9Smrg#if defined(HAVE_STRLCPY) || defined(HAS_STRLCPY) 52173143b9aSmrg strlcpy(addr->sa_data, port, portlen); 52273143b9aSmrg#else 52373143b9aSmrg strncpy(addr->sa_data, port, portlen); 52473143b9aSmrg#endif 52573143b9aSmrg ciptr->family = AF_UNIX; 526fe567363Smrg memcpy(ciptr->peeraddr, ciptr->addr, addrlen); 52773143b9aSmrg ciptr->port = rindex(addr->sa_data, ':'); 528e8a71cdfSmrg if (ciptr->port == NULL) { 529e8a71cdfSmrg if (is_numeric(addr->sa_data)) { 530e8a71cdfSmrg ciptr->port = addr->sa_data; 531e8a71cdfSmrg } 532e8a71cdfSmrg } else if (ciptr->port[0] == ':') { 533e8a71cdfSmrg ciptr->port++; 534e8a71cdfSmrg } 535e8a71cdfSmrg /* port should now point to portnum or NULL */ 53673143b9aSmrg return ciptr; 53773143b9aSmrg} 53873143b9aSmrg 53973143b9aSmrg#endif /* TRANS_REOPEN */ 54073143b9aSmrg 54173143b9aSmrg 54273143b9aSmrg/* 54373143b9aSmrg * These functions are the interface supplied in the Xtransport structure 54473143b9aSmrg */ 54573143b9aSmrg 54673143b9aSmrg#ifdef TRANS_CLIENT 54773143b9aSmrg 54873143b9aSmrgstatic XtransConnInfo 549fe567363SmrgTRANS(SocketOpenCOTSClientBase) (const char *transname, const char *protocol, 550fe567363Smrg const char *host, const char *port, int previndex) 55173143b9aSmrg{ 55273143b9aSmrg XtransConnInfo ciptr; 55373143b9aSmrg int i = previndex; 55473143b9aSmrg 555fe567363Smrg prmsg (2, "SocketOpenCOTSClient(%s,%s,%s)\n", 55673143b9aSmrg protocol, host, port); 55773143b9aSmrg 55873143b9aSmrg SocketInitOnce(); 55973143b9aSmrg 56073143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) { 56173143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 562e8a71cdfSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) { 563e8a71cdfSmrg /* Save the index for later use */ 564e8a71cdfSmrg 565e8a71cdfSmrg ciptr->index = i; 56673143b9aSmrg break; 567e8a71cdfSmrg } 56873143b9aSmrg } 56973143b9aSmrg if (i < 0) { 57073143b9aSmrg if (i == -1) 571fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", 572fe567363Smrg transname); 57373143b9aSmrg else 574fe567363Smrg prmsg (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", 575fe567363Smrg transname); 57673143b9aSmrg return NULL; 57773143b9aSmrg } 57873143b9aSmrg 57973143b9aSmrg return ciptr; 58073143b9aSmrg} 58173143b9aSmrg 58273143b9aSmrgstatic XtransConnInfo 5836a3641a6SsnjTRANS(SocketOpenCOTSClient) (Xtransport *thistrans, const char *protocol, 5846a3641a6Ssnj const char *host, const char *port) 58573143b9aSmrg{ 58673143b9aSmrg return TRANS(SocketOpenCOTSClientBase)( 58773143b9aSmrg thistrans->TransName, protocol, host, port, -1); 58873143b9aSmrg} 58973143b9aSmrg 59073143b9aSmrg 59173143b9aSmrg#endif /* TRANS_CLIENT */ 59273143b9aSmrg 59373143b9aSmrg 59473143b9aSmrg#ifdef TRANS_SERVER 59573143b9aSmrg 59673143b9aSmrgstatic XtransConnInfo 5976a3641a6SsnjTRANS(SocketOpenCOTSServer) (Xtransport *thistrans, const char *protocol, 5986a3641a6Ssnj const char *host, const char *port) 59973143b9aSmrg 60073143b9aSmrg{ 60173143b9aSmrg XtransConnInfo ciptr; 60273143b9aSmrg int i = -1; 60373143b9aSmrg 604fe567363Smrg prmsg (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); 60573143b9aSmrg 60673143b9aSmrg SocketInitOnce(); 60773143b9aSmrg 60873143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 60973143b9aSmrg if ((ciptr = TRANS(SocketOpen) ( 61073143b9aSmrg i, Sockettrans2devtab[i].devcotsname)) != NULL) 61173143b9aSmrg break; 61273143b9aSmrg } 61373143b9aSmrg if (i < 0) { 61473143b9aSmrg if (i == -1) 615fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", 616fe567363Smrg thistrans->TransName); 61773143b9aSmrg else 618fe567363Smrg prmsg (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n", 619fe567363Smrg thistrans->TransName); 62073143b9aSmrg return NULL; 62173143b9aSmrg } 62273143b9aSmrg 62373143b9aSmrg /* 62473143b9aSmrg * Using this prevents the bind() check for an existing server listening 62573143b9aSmrg * on the same port, but it is required for other reasons. 62673143b9aSmrg */ 62773143b9aSmrg#ifdef SO_REUSEADDR 62873143b9aSmrg 62973143b9aSmrg /* 63073143b9aSmrg * SO_REUSEADDR only applied to AF_INET && AF_INET6 63173143b9aSmrg */ 63273143b9aSmrg 63373143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET 63473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 63573143b9aSmrg || Sockettrans2devtab[i].family == AF_INET6 63673143b9aSmrg#endif 63773143b9aSmrg ) 63873143b9aSmrg { 63973143b9aSmrg int one = 1; 64073143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, 64173143b9aSmrg (char *) &one, sizeof (int)); 64273143b9aSmrg } 64373143b9aSmrg#endif 64473143b9aSmrg#ifdef IPV6_V6ONLY 64573143b9aSmrg if (Sockettrans2devtab[i].family == AF_INET6) 64673143b9aSmrg { 64773143b9aSmrg int one = 1; 64873143b9aSmrg setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); 64973143b9aSmrg } 65073143b9aSmrg#endif 65173143b9aSmrg /* Save the index for later use */ 65273143b9aSmrg 65373143b9aSmrg ciptr->index = i; 65473143b9aSmrg 65573143b9aSmrg return ciptr; 65673143b9aSmrg} 65773143b9aSmrg 65873143b9aSmrg#endif /* TRANS_SERVER */ 65973143b9aSmrg 66073143b9aSmrg 66173143b9aSmrg#ifdef TRANS_REOPEN 66273143b9aSmrg 66373143b9aSmrgstatic XtransConnInfo 6646a3641a6SsnjTRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, const char *port) 66573143b9aSmrg 66673143b9aSmrg{ 66773143b9aSmrg XtransConnInfo ciptr; 66873143b9aSmrg int i = -1; 66973143b9aSmrg 670fe567363Smrg prmsg (2, 671fe567363Smrg "SocketReopenCOTSServer(%d, %s)\n", fd, port); 67273143b9aSmrg 67373143b9aSmrg SocketInitOnce(); 67473143b9aSmrg 67573143b9aSmrg while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { 67673143b9aSmrg if ((ciptr = TRANS(SocketReopen) ( 67773143b9aSmrg i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) 67873143b9aSmrg break; 67973143b9aSmrg } 68073143b9aSmrg if (i < 0) { 68173143b9aSmrg if (i == -1) 682fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to open socket for %s\n", 683fe567363Smrg thistrans->TransName); 68473143b9aSmrg else 685fe567363Smrg prmsg (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n", 686fe567363Smrg thistrans->TransName); 68773143b9aSmrg return NULL; 68873143b9aSmrg } 68973143b9aSmrg 69073143b9aSmrg /* Save the index for later use */ 69173143b9aSmrg 69273143b9aSmrg ciptr->index = i; 69373143b9aSmrg 69473143b9aSmrg return ciptr; 69573143b9aSmrg} 69673143b9aSmrg 69773143b9aSmrg#endif /* TRANS_REOPEN */ 69873143b9aSmrg 69973143b9aSmrg 70073143b9aSmrgstatic int 70173143b9aSmrgTRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg) 70273143b9aSmrg 70373143b9aSmrg{ 704fe567363Smrg prmsg (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); 70573143b9aSmrg 70673143b9aSmrg return -1; 70773143b9aSmrg} 70873143b9aSmrg 70973143b9aSmrg#ifdef UNIXCONN 71073143b9aSmrgstatic int 71173143b9aSmrgset_sun_path(const char *port, const char *upath, char *path, int abstract) 71273143b9aSmrg{ 71373143b9aSmrg struct sockaddr_un s; 71473143b9aSmrg int maxlen = sizeof(s.sun_path) - 1; 71573143b9aSmrg const char *at = ""; 71673143b9aSmrg 71773143b9aSmrg if (!port || !*port || !path) 71873143b9aSmrg return -1; 71973143b9aSmrg 72073143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 72173143b9aSmrg if (port[0] == '@') 72273143b9aSmrg upath = ""; 72373143b9aSmrg else if (abstract) 72473143b9aSmrg at = "@"; 72573143b9aSmrg#endif 72673143b9aSmrg 72773143b9aSmrg if (*port == '/') /* a full pathname */ 72873143b9aSmrg upath = ""; 72973143b9aSmrg 73073143b9aSmrg if (strlen(port) + strlen(upath) > maxlen) 73173143b9aSmrg return -1; 732fe567363Smrg snprintf(path, sizeof(s.sun_path), "%s%s%s", at, upath, port); 73373143b9aSmrg return 0; 73473143b9aSmrg} 73573143b9aSmrg#endif 73673143b9aSmrg 73773143b9aSmrg#ifdef TRANS_SERVER 73873143b9aSmrg 73973143b9aSmrgstatic int 740fe567363SmrgTRANS(SocketCreateListener) (XtransConnInfo ciptr, 74173143b9aSmrg struct sockaddr *sockname, 74273143b9aSmrg int socknamelen, unsigned int flags) 74373143b9aSmrg 74473143b9aSmrg{ 74573143b9aSmrg SOCKLEN_T namelen = socknamelen; 74673143b9aSmrg int fd = ciptr->fd; 74773143b9aSmrg int retry; 74873143b9aSmrg 749fe567363Smrg prmsg (3, "SocketCreateListener(%p,%d)\n", ciptr, fd); 75073143b9aSmrg 75173143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 75273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 75373143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 75473143b9aSmrg#endif 75573143b9aSmrg ) 75673143b9aSmrg retry = 20; 75773143b9aSmrg else 75873143b9aSmrg retry = 0; 75973143b9aSmrg 76073143b9aSmrg while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) 76173143b9aSmrg { 76273143b9aSmrg if (errno == EADDRINUSE) { 76373143b9aSmrg if (flags & ADDR_IN_USE_ALLOWED) 76473143b9aSmrg break; 76573143b9aSmrg else 76673143b9aSmrg return TRANS_ADDR_IN_USE; 76773143b9aSmrg } 768fe567363Smrg 76973143b9aSmrg if (retry-- == 0) { 770fe567363Smrg prmsg (1, "SocketCreateListener: failed to bind listener\n"); 77173143b9aSmrg close (fd); 77273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 77373143b9aSmrg } 77473143b9aSmrg#ifdef SO_REUSEADDR 77573143b9aSmrg sleep (1); 77673143b9aSmrg#else 77773143b9aSmrg sleep (10); 77873143b9aSmrg#endif /* SO_REUSEDADDR */ 77973143b9aSmrg } 78073143b9aSmrg 78173143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET 78273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 78373143b9aSmrg || Sockettrans2devtab[ciptr->index].family == AF_INET6 78473143b9aSmrg#endif 78573143b9aSmrg ) { 78673143b9aSmrg#ifdef SO_DONTLINGER 78773143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0); 78873143b9aSmrg#else 78973143b9aSmrg#ifdef SO_LINGER 79073143b9aSmrg { 79173143b9aSmrg static int linger[2] = { 0, 0 }; 79273143b9aSmrg setsockopt (fd, SOL_SOCKET, SO_LINGER, 79373143b9aSmrg (char *) linger, sizeof (linger)); 79473143b9aSmrg } 79573143b9aSmrg#endif 79673143b9aSmrg#endif 79773143b9aSmrg} 79873143b9aSmrg 79973143b9aSmrg if (listen (fd, BACKLOG) < 0) 80073143b9aSmrg { 801fe567363Smrg prmsg (1, "SocketCreateListener: listen() failed\n"); 80273143b9aSmrg close (fd); 80373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 80473143b9aSmrg } 805fe567363Smrg 80673143b9aSmrg /* Set a flag to indicate that this connection is a listener */ 80773143b9aSmrg 80873143b9aSmrg ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 80973143b9aSmrg 81073143b9aSmrg return 0; 81173143b9aSmrg} 81273143b9aSmrg 81373143b9aSmrg#ifdef TCPCONN 81473143b9aSmrgstatic int 8156a3641a6SsnjTRANS(SocketINETCreateListener) (XtransConnInfo ciptr, const char *port, 8166a3641a6Ssnj unsigned int flags) 81773143b9aSmrg 81873143b9aSmrg{ 81973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 82073143b9aSmrg struct sockaddr_storage sockname; 82173143b9aSmrg#else 82273143b9aSmrg struct sockaddr_in sockname; 82373143b9aSmrg#endif 82473143b9aSmrg unsigned short sport; 82573143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 82673143b9aSmrg int status; 82773143b9aSmrg long tmpport; 82873143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 82973143b9aSmrg _Xgetservbynameparams sparams; 83073143b9aSmrg#endif 83173143b9aSmrg struct servent *servp; 83273143b9aSmrg 83373143b9aSmrg#ifdef X11_t 83473143b9aSmrg char portbuf[PORTBUFSIZE]; 83573143b9aSmrg#endif 836fe567363Smrg 837fe567363Smrg prmsg (2, "SocketINETCreateListener(%s)\n", port); 83873143b9aSmrg 83973143b9aSmrg#ifdef X11_t 84073143b9aSmrg /* 84173143b9aSmrg * X has a well known port, that is transport dependent. It is easier 84273143b9aSmrg * to handle it here, than try and come up with a transport independent 84373143b9aSmrg * representation that can be passed in and resolved the usual way. 84473143b9aSmrg * 84573143b9aSmrg * The port that is passed here is really a string containing the idisplay 84673143b9aSmrg * from ConnectDisplay(). 84773143b9aSmrg */ 84873143b9aSmrg 84973143b9aSmrg if (is_numeric (port)) 85073143b9aSmrg { 85173143b9aSmrg /* fixup the server port address */ 85273143b9aSmrg tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 853fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 85473143b9aSmrg port = portbuf; 85573143b9aSmrg } 85673143b9aSmrg#endif 85773143b9aSmrg 85873143b9aSmrg if (port && *port) 85973143b9aSmrg { 86073143b9aSmrg /* Check to see if the port string is just a number (handles X11) */ 86173143b9aSmrg 86273143b9aSmrg if (!is_numeric (port)) 86373143b9aSmrg { 86473143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) 86573143b9aSmrg { 866fe567363Smrg prmsg (1, 86773143b9aSmrg "SocketINETCreateListener: Unable to get service for %s\n", 868fe567363Smrg port); 86973143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 87073143b9aSmrg } 87173143b9aSmrg /* we trust getservbyname to return a valid number */ 87273143b9aSmrg sport = servp->s_port; 87373143b9aSmrg } 87473143b9aSmrg else 87573143b9aSmrg { 87673143b9aSmrg tmpport = strtol (port, (char**)NULL, 10); 877fe567363Smrg /* 87873143b9aSmrg * check that somehow the port address isn't negative or in 87973143b9aSmrg * the range of reserved port addresses. This can happen and 880fe567363Smrg * be very bad if the server is suid-root and the user does 881fe567363Smrg * something (dumb) like `X :60049`. 88273143b9aSmrg */ 88373143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 88473143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 88573143b9aSmrg 88673143b9aSmrg sport = (unsigned short) tmpport; 88773143b9aSmrg } 88873143b9aSmrg } 88973143b9aSmrg else 89073143b9aSmrg sport = 0; 89173143b9aSmrg 89273143b9aSmrg bzero(&sockname, sizeof(sockname)); 89373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 89473143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 89573143b9aSmrg namelen = sizeof (struct sockaddr_in); 89673143b9aSmrg#ifdef BSD44SOCKETS 89773143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_len = namelen; 89873143b9aSmrg#endif 89973143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_family = AF_INET; 90073143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_port = htons(sport); 90173143b9aSmrg ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY); 90273143b9aSmrg } else { 90373143b9aSmrg namelen = sizeof (struct sockaddr_in6); 90473143b9aSmrg#ifdef SIN6_LEN 90573143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname); 90673143b9aSmrg#endif 90773143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6; 90873143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport); 90973143b9aSmrg ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any; 91073143b9aSmrg } 91173143b9aSmrg#else 91273143b9aSmrg#ifdef BSD44SOCKETS 91373143b9aSmrg sockname.sin_len = sizeof (sockname); 91473143b9aSmrg#endif 91573143b9aSmrg sockname.sin_family = AF_INET; 91673143b9aSmrg sockname.sin_port = htons (sport); 91773143b9aSmrg sockname.sin_addr.s_addr = htonl (INADDR_ANY); 91873143b9aSmrg#endif 91973143b9aSmrg 92073143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 92173143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 92273143b9aSmrg { 923fe567363Smrg prmsg (1, 924fe567363Smrg "SocketINETCreateListener: ...SocketCreateListener() failed\n"); 92573143b9aSmrg return status; 92673143b9aSmrg } 92773143b9aSmrg 92873143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 92973143b9aSmrg { 930fe567363Smrg prmsg (1, 931fe567363Smrg "SocketINETCreateListener: ...SocketINETGetAddr() failed\n"); 93273143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 93373143b9aSmrg } 93473143b9aSmrg 93573143b9aSmrg return 0; 93673143b9aSmrg} 93773143b9aSmrg 93873143b9aSmrg#endif /* TCPCONN */ 93973143b9aSmrg 94073143b9aSmrg 94173143b9aSmrg#ifdef UNIXCONN 94273143b9aSmrg 94373143b9aSmrgstatic int 9446a3641a6SsnjTRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, const char *port, 94573143b9aSmrg unsigned int flags) 94673143b9aSmrg 94773143b9aSmrg{ 94873143b9aSmrg struct sockaddr_un sockname; 94973143b9aSmrg int namelen; 95073143b9aSmrg int oldUmask; 95173143b9aSmrg int status; 95273143b9aSmrg unsigned int mode; 95373143b9aSmrg char tmpport[108]; 95473143b9aSmrg 95573143b9aSmrg int abstract = 0; 95673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 95773143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 95873143b9aSmrg#endif 95973143b9aSmrg 960fe567363Smrg prmsg (2, "SocketUNIXCreateListener(%s)\n", 961fe567363Smrg port ? port : "NULL"); 96273143b9aSmrg 96373143b9aSmrg /* Make sure the directory is created */ 96473143b9aSmrg 96573143b9aSmrg oldUmask = umask (0); 96673143b9aSmrg 96773143b9aSmrg#ifdef UNIX_DIR 96873143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 96973143b9aSmrg mode = 01777; 97073143b9aSmrg#else 97173143b9aSmrg mode = 0777; 97273143b9aSmrg#endif 9738d4c0f7bSmrg if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) { 974fe567363Smrg prmsg (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n", 975fe567363Smrg UNIX_DIR, errno); 97673143b9aSmrg (void) umask (oldUmask); 97773143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 97873143b9aSmrg } 97973143b9aSmrg#endif 98073143b9aSmrg 98173143b9aSmrg memset(&sockname, 0, sizeof(sockname)); 98273143b9aSmrg sockname.sun_family = AF_UNIX; 98373143b9aSmrg 98473143b9aSmrg if (!(port && *port)) { 98573143b9aSmrg snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid()); 98673143b9aSmrg port = tmpport; 98773143b9aSmrg } 98873143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 989fe567363Smrg prmsg (1, "SocketUNIXCreateListener: path too long\n"); 99073143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 99173143b9aSmrg } 99273143b9aSmrg 993fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 99473143b9aSmrg sockname.sun_len = strlen(sockname.sun_path); 99573143b9aSmrg#endif 99673143b9aSmrg 99773143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 99873143b9aSmrg namelen = SUN_LEN(&sockname); 99973143b9aSmrg#else 100073143b9aSmrg namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 100173143b9aSmrg#endif 100273143b9aSmrg 100373143b9aSmrg if (abstract) { 100473143b9aSmrg sockname.sun_path[0] = '\0'; 100573143b9aSmrg namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]); 100673143b9aSmrg } 100773143b9aSmrg else 100873143b9aSmrg unlink (sockname.sun_path); 100973143b9aSmrg 101073143b9aSmrg if ((status = TRANS(SocketCreateListener) (ciptr, 101173143b9aSmrg (struct sockaddr *) &sockname, namelen, flags)) < 0) 101273143b9aSmrg { 1013fe567363Smrg prmsg (1, 1014fe567363Smrg "SocketUNIXCreateListener: ...SocketCreateListener() failed\n"); 101573143b9aSmrg (void) umask (oldUmask); 101673143b9aSmrg return status; 101773143b9aSmrg } 101873143b9aSmrg 101973143b9aSmrg /* 102073143b9aSmrg * Now that the listener is esablished, create the addr info for 102173143b9aSmrg * this connection. getpeername() doesn't work for UNIX Domain Sockets 102273143b9aSmrg * on some systems (hpux at least), so we will just do it manually, instead 102373143b9aSmrg * of calling something like TRANS(SocketUNIXGetAddr). 102473143b9aSmrg */ 102573143b9aSmrg 102673143b9aSmrg namelen = sizeof (sockname); /* this will always make it the same size */ 102773143b9aSmrg 1028fe567363Smrg if ((ciptr->addr = malloc (namelen)) == NULL) 102973143b9aSmrg { 1030fe567363Smrg prmsg (1, 1031fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 103273143b9aSmrg (void) umask (oldUmask); 103373143b9aSmrg return TRANS_CREATE_LISTENER_FAILED; 103473143b9aSmrg } 103573143b9aSmrg 103673143b9aSmrg if (abstract) 103773143b9aSmrg sockname.sun_path[0] = '@'; 103873143b9aSmrg 103973143b9aSmrg ciptr->family = sockname.sun_family; 104073143b9aSmrg ciptr->addrlen = namelen; 104173143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 104273143b9aSmrg 104373143b9aSmrg (void) umask (oldUmask); 104473143b9aSmrg 104573143b9aSmrg return 0; 104673143b9aSmrg} 104773143b9aSmrg 104873143b9aSmrg 104973143b9aSmrgstatic int 105073143b9aSmrgTRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) 105173143b9aSmrg 105273143b9aSmrg{ 105373143b9aSmrg /* 105473143b9aSmrg * See if the unix domain socket has disappeared. If it has, recreate it. 105573143b9aSmrg */ 105673143b9aSmrg 105773143b9aSmrg struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr; 105873143b9aSmrg struct stat statb; 105973143b9aSmrg int status = TRANS_RESET_NOOP; 106073143b9aSmrg unsigned int mode; 106173143b9aSmrg int abstract = 0; 106273143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 106373143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 106473143b9aSmrg#endif 106573143b9aSmrg 1066fe567363Smrg prmsg (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd); 106773143b9aSmrg 106873143b9aSmrg if (!abstract && ( 106973143b9aSmrg stat (unsock->sun_path, &statb) == -1 || 107073143b9aSmrg ((statb.st_mode & S_IFMT) != 1071e8a71cdfSmrg#if defined(NCR) || defined(SCO325) || !defined(S_IFSOCK) 107273143b9aSmrg S_IFIFO 107373143b9aSmrg#else 107473143b9aSmrg S_IFSOCK 107573143b9aSmrg#endif 107673143b9aSmrg ))) 107773143b9aSmrg { 107873143b9aSmrg int oldUmask = umask (0); 107973143b9aSmrg 108073143b9aSmrg#ifdef UNIX_DIR 108173143b9aSmrg#ifdef HAS_STICKY_DIR_BIT 108273143b9aSmrg mode = 01777; 108373143b9aSmrg#else 108473143b9aSmrg mode = 0777; 108573143b9aSmrg#endif 108673143b9aSmrg if (trans_mkdir(UNIX_DIR, mode) == -1) { 1087fe567363Smrg prmsg (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n", 1088fe567363Smrg UNIX_DIR, errno); 108973143b9aSmrg (void) umask (oldUmask); 109073143b9aSmrg return TRANS_RESET_FAILURE; 109173143b9aSmrg } 109273143b9aSmrg#endif 109373143b9aSmrg 109473143b9aSmrg close (ciptr->fd); 109573143b9aSmrg unlink (unsock->sun_path); 109673143b9aSmrg 109773143b9aSmrg if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) 109873143b9aSmrg { 109973143b9aSmrg TRANS(FreeConnInfo) (ciptr); 110073143b9aSmrg (void) umask (oldUmask); 110173143b9aSmrg return TRANS_RESET_FAILURE; 110273143b9aSmrg } 110373143b9aSmrg 110473143b9aSmrg if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0) 110573143b9aSmrg { 110673143b9aSmrg close (ciptr->fd); 110773143b9aSmrg TRANS(FreeConnInfo) (ciptr); 110873143b9aSmrg return TRANS_RESET_FAILURE; 110973143b9aSmrg } 111073143b9aSmrg 111173143b9aSmrg if (listen (ciptr->fd, BACKLOG) < 0) 111273143b9aSmrg { 111373143b9aSmrg close (ciptr->fd); 111473143b9aSmrg TRANS(FreeConnInfo) (ciptr); 111573143b9aSmrg (void) umask (oldUmask); 111673143b9aSmrg return TRANS_RESET_FAILURE; 111773143b9aSmrg } 111873143b9aSmrg 111973143b9aSmrg umask (oldUmask); 112073143b9aSmrg 112173143b9aSmrg status = TRANS_RESET_NEW_FD; 112273143b9aSmrg } 112373143b9aSmrg 112473143b9aSmrg return status; 112573143b9aSmrg} 112673143b9aSmrg 112773143b9aSmrg#endif /* UNIXCONN */ 112873143b9aSmrg 112973143b9aSmrg 113073143b9aSmrg#ifdef TCPCONN 113173143b9aSmrg 113273143b9aSmrgstatic XtransConnInfo 113373143b9aSmrgTRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) 113473143b9aSmrg 113573143b9aSmrg{ 113673143b9aSmrg XtransConnInfo newciptr; 113773143b9aSmrg struct sockaddr_in sockname; 113873143b9aSmrg SOCKLEN_T namelen = sizeof(sockname); 113973143b9aSmrg 1140fe567363Smrg prmsg (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd); 114173143b9aSmrg 1142fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 114373143b9aSmrg { 1144fe567363Smrg prmsg (1, "SocketINETAccept: malloc failed\n"); 114573143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 114673143b9aSmrg return NULL; 114773143b9aSmrg } 114873143b9aSmrg 114973143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 115073143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 115173143b9aSmrg { 115273143b9aSmrg#ifdef WIN32 115373143b9aSmrg errno = WSAGetLastError(); 115473143b9aSmrg#endif 1155fe567363Smrg prmsg (1, "SocketINETAccept: accept() failed\n"); 1156fe567363Smrg free (newciptr); 115773143b9aSmrg *status = TRANS_ACCEPT_FAILED; 115873143b9aSmrg return NULL; 115973143b9aSmrg } 116073143b9aSmrg 116173143b9aSmrg#ifdef TCP_NODELAY 116273143b9aSmrg { 116373143b9aSmrg /* 116473143b9aSmrg * turn off TCP coalescence for INET sockets 116573143b9aSmrg */ 116673143b9aSmrg 116773143b9aSmrg int tmp = 1; 116873143b9aSmrg setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, 116973143b9aSmrg (char *) &tmp, sizeof (int)); 117073143b9aSmrg } 117173143b9aSmrg#endif 117273143b9aSmrg 117373143b9aSmrg /* 1174fe567363Smrg * Get this address again because the transport may give a more 117573143b9aSmrg * specific address now that a connection is established. 117673143b9aSmrg */ 117773143b9aSmrg 117873143b9aSmrg if (TRANS(SocketINETGetAddr) (newciptr) < 0) 117973143b9aSmrg { 1180fe567363Smrg prmsg (1, 1181fe567363Smrg "SocketINETAccept: ...SocketINETGetAddr() failed:\n"); 118273143b9aSmrg close (newciptr->fd); 1183fe567363Smrg free (newciptr); 118473143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 118573143b9aSmrg return NULL; 118673143b9aSmrg } 118773143b9aSmrg 118873143b9aSmrg if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) 118973143b9aSmrg { 1190fe567363Smrg prmsg (1, 1191fe567363Smrg "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n"); 119273143b9aSmrg close (newciptr->fd); 1193fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1194fe567363Smrg free (newciptr); 119573143b9aSmrg *status = TRANS_ACCEPT_MISC_ERROR; 119673143b9aSmrg return NULL; 119773143b9aSmrg } 119873143b9aSmrg 119973143b9aSmrg *status = 0; 120073143b9aSmrg 120173143b9aSmrg return newciptr; 120273143b9aSmrg} 120373143b9aSmrg 120473143b9aSmrg#endif /* TCPCONN */ 120573143b9aSmrg 120673143b9aSmrg 120773143b9aSmrg#ifdef UNIXCONN 120873143b9aSmrgstatic XtransConnInfo 120973143b9aSmrgTRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) 121073143b9aSmrg 121173143b9aSmrg{ 121273143b9aSmrg XtransConnInfo newciptr; 121373143b9aSmrg struct sockaddr_un sockname; 121473143b9aSmrg SOCKLEN_T namelen = sizeof sockname; 121573143b9aSmrg 1216fe567363Smrg prmsg (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd); 121773143b9aSmrg 1218fe567363Smrg if ((newciptr = calloc (1, sizeof(struct _XtransConnInfo))) == NULL) 121973143b9aSmrg { 1220fe567363Smrg prmsg (1, "SocketUNIXAccept: malloc() failed\n"); 122173143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 122273143b9aSmrg return NULL; 122373143b9aSmrg } 122473143b9aSmrg 122573143b9aSmrg if ((newciptr->fd = accept (ciptr->fd, 122673143b9aSmrg (struct sockaddr *) &sockname, (void *)&namelen)) < 0) 122773143b9aSmrg { 1228fe567363Smrg prmsg (1, "SocketUNIXAccept: accept() failed\n"); 1229fe567363Smrg free (newciptr); 123073143b9aSmrg *status = TRANS_ACCEPT_FAILED; 123173143b9aSmrg return NULL; 123273143b9aSmrg } 123373143b9aSmrg 123473143b9aSmrg ciptr->addrlen = namelen; 123573143b9aSmrg /* 123673143b9aSmrg * Get the socket name and the peer name from the listener socket, 123773143b9aSmrg * since this is unix domain. 123873143b9aSmrg */ 123973143b9aSmrg 1240fe567363Smrg if ((newciptr->addr = malloc (ciptr->addrlen)) == NULL) 124173143b9aSmrg { 1242fe567363Smrg prmsg (1, 1243fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 124473143b9aSmrg close (newciptr->fd); 1245fe567363Smrg free (newciptr); 124673143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 124773143b9aSmrg return NULL; 124873143b9aSmrg } 124973143b9aSmrg 125073143b9aSmrg /* 125173143b9aSmrg * if the socket is abstract, we already modified the address to have a 125273143b9aSmrg * @ instead of the initial NUL, so no need to do that again here. 125373143b9aSmrg */ 125473143b9aSmrg 125573143b9aSmrg newciptr->addrlen = ciptr->addrlen; 125673143b9aSmrg memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); 125773143b9aSmrg 1258fe567363Smrg if ((newciptr->peeraddr = malloc (ciptr->addrlen)) == NULL) 125973143b9aSmrg { 1260fe567363Smrg prmsg (1, 1261fe567363Smrg "SocketUNIXAccept: Can't allocate space for the addr\n"); 126273143b9aSmrg close (newciptr->fd); 1263fe567363Smrg if (newciptr->addr) free (newciptr->addr); 1264fe567363Smrg free (newciptr); 126573143b9aSmrg *status = TRANS_ACCEPT_BAD_MALLOC; 126673143b9aSmrg return NULL; 126773143b9aSmrg } 1268fe567363Smrg 126973143b9aSmrg newciptr->peeraddrlen = ciptr->addrlen; 127073143b9aSmrg memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); 127173143b9aSmrg 127273143b9aSmrg newciptr->family = AF_UNIX; 127373143b9aSmrg 127473143b9aSmrg *status = 0; 127573143b9aSmrg 127673143b9aSmrg return newciptr; 127773143b9aSmrg} 127873143b9aSmrg 127973143b9aSmrg#endif /* UNIXCONN */ 128073143b9aSmrg 128173143b9aSmrg#endif /* TRANS_SERVER */ 128273143b9aSmrg 128373143b9aSmrg 128473143b9aSmrg#ifdef TRANS_CLIENT 128573143b9aSmrg 128673143b9aSmrg#ifdef TCPCONN 128773143b9aSmrg 128873143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 128973143b9aSmrgstruct addrlist { 129073143b9aSmrg struct addrinfo * addr; 1291fe567363Smrg struct addrinfo * firstaddr; 129273143b9aSmrg char port[PORTBUFSIZE]; 129373143b9aSmrg char host[MAXHOSTNAMELEN]; 129473143b9aSmrg}; 129573143b9aSmrgstatic struct addrlist *addrlist = NULL; 129673143b9aSmrg#endif 129773143b9aSmrg 129873143b9aSmrg 129973143b9aSmrgstatic int 13006a3641a6SsnjTRANS(SocketINETConnect) (XtransConnInfo ciptr, 13016a3641a6Ssnj const char *host, const char *port) 130273143b9aSmrg 130373143b9aSmrg{ 130473143b9aSmrg struct sockaddr * socketaddr = NULL; 130573143b9aSmrg int socketaddrlen = 0; 130673143b9aSmrg int res; 130773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 130873143b9aSmrg struct addrinfo hints; 130973143b9aSmrg char ntopbuf[INET6_ADDRSTRLEN]; 131073143b9aSmrg int resetonce = 0; 1311fe567363Smrg#else 131273143b9aSmrg struct sockaddr_in sockname; 1313fe567363Smrg struct hostent *hostp; 1314fe567363Smrg struct servent *servp; 1315fe567363Smrg unsigned long tmpaddr; 1316fe567363Smrg#endif 131773143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 131873143b9aSmrg _Xgethostbynameparams hparams; 131973143b9aSmrg _Xgetservbynameparams sparams; 132073143b9aSmrg#endif 132173143b9aSmrg#ifdef X11_t 132273143b9aSmrg char portbuf[PORTBUFSIZE]; 132373143b9aSmrg#endif 132473143b9aSmrg 132573143b9aSmrg char hostnamebuf[256]; /* tmp space */ 132673143b9aSmrg 1327fe567363Smrg prmsg (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); 132873143b9aSmrg 132973143b9aSmrg if (!host) 133073143b9aSmrg { 133173143b9aSmrg hostnamebuf[0] = '\0'; 133273143b9aSmrg (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); 133373143b9aSmrg host = hostnamebuf; 133473143b9aSmrg } 133573143b9aSmrg 133673143b9aSmrg#ifdef X11_t 133773143b9aSmrg /* 133873143b9aSmrg * X has a well known port, that is transport dependent. It is easier 133973143b9aSmrg * to handle it here, than try and come up with a transport independent 134073143b9aSmrg * representation that can be passed in and resolved the usual way. 134173143b9aSmrg * 134273143b9aSmrg * The port that is passed here is really a string containing the idisplay 134373143b9aSmrg * from ConnectDisplay(). 134473143b9aSmrg */ 134573143b9aSmrg 134673143b9aSmrg if (is_numeric (port)) 134773143b9aSmrg { 1348fe567363Smrg long tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10); 1349fe567363Smrg snprintf (portbuf, sizeof(portbuf), "%lu", tmpport); 135073143b9aSmrg port = portbuf; 135173143b9aSmrg } 135273143b9aSmrg#endif 135373143b9aSmrg 135473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1355b53e5eeaSmrg { 135673143b9aSmrg if (addrlist != NULL) { 135773143b9aSmrg if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) { 135873143b9aSmrg if (addrlist->firstaddr) 135973143b9aSmrg freeaddrinfo(addrlist->firstaddr); 136073143b9aSmrg addrlist->firstaddr = NULL; 136173143b9aSmrg } 136273143b9aSmrg } else { 136373143b9aSmrg addrlist = malloc(sizeof(struct addrlist)); 136473143b9aSmrg addrlist->firstaddr = NULL; 136573143b9aSmrg } 136673143b9aSmrg 136773143b9aSmrg if (addrlist->firstaddr == NULL) { 136873143b9aSmrg strncpy(addrlist->port, port, sizeof(addrlist->port)); 136973143b9aSmrg addrlist->port[sizeof(addrlist->port) - 1] = '\0'; 137073143b9aSmrg strncpy(addrlist->host, host, sizeof(addrlist->host)); 137173143b9aSmrg addrlist->host[sizeof(addrlist->host) - 1] = '\0'; 137273143b9aSmrg 137373143b9aSmrg bzero(&hints,sizeof(hints)); 137473143b9aSmrg hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname; 137573143b9aSmrg 137673143b9aSmrg res = getaddrinfo(host,port,&hints,&addrlist->firstaddr); 137773143b9aSmrg if (res != 0) { 1378fe567363Smrg prmsg (1, "SocketINETConnect() can't get address " 137973143b9aSmrg "for %s:%s: %s\n", host, port, gai_strerror(res)); 138073143b9aSmrg ESET(EINVAL); 138173143b9aSmrg return TRANS_CONNECT_FAILED; 138273143b9aSmrg } 138373143b9aSmrg for (res = 0, addrlist->addr = addrlist->firstaddr; 138473143b9aSmrg addrlist->addr ; res++) { 138573143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 138673143b9aSmrg } 1387fe567363Smrg prmsg(4,"Got New Address list with %d addresses\n", res); 138873143b9aSmrg res = 0; 138973143b9aSmrg addrlist->addr = NULL; 139073143b9aSmrg } 139173143b9aSmrg 139273143b9aSmrg while (socketaddr == NULL) { 139373143b9aSmrg if (addrlist->addr == NULL) { 1394fe567363Smrg if (resetonce) { 139573143b9aSmrg /* Already checked entire list - no usable addresses */ 1396fe567363Smrg prmsg (1, "SocketINETConnect() no usable address " 1397fe567363Smrg "for %s:%s\n", host, port); 139873143b9aSmrg return TRANS_CONNECT_FAILED; 139973143b9aSmrg } else { 140073143b9aSmrg /* Go back to beginning of list */ 140173143b9aSmrg resetonce = 1; 140273143b9aSmrg addrlist->addr = addrlist->firstaddr; 140373143b9aSmrg } 1404fe567363Smrg } 140573143b9aSmrg 140673143b9aSmrg socketaddr = addrlist->addr->ai_addr; 140773143b9aSmrg socketaddrlen = addrlist->addr->ai_addrlen; 140873143b9aSmrg 140973143b9aSmrg if (addrlist->addr->ai_family == AF_INET) { 141073143b9aSmrg struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr; 141173143b9aSmrg 1412fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_addr = %s\n", 141373143b9aSmrg inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, 1414fe567363Smrg ntopbuf,sizeof(ntopbuf))); 141573143b9aSmrg 1416fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin_port = %d\n", 1417fe567363Smrg ntohs(sin->sin_port)); 141873143b9aSmrg 141973143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { 142073143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 142173143b9aSmrg "tcp") == 0) { 142273143b9aSmrg XtransConnInfo newciptr; 142373143b9aSmrg 142473143b9aSmrg /* 142573143b9aSmrg * Our socket is an IPv6 socket, but the address is 142673143b9aSmrg * IPv4. Close it and get an IPv4 socket. This is 142773143b9aSmrg * needed for IPv4 connections to work on platforms 142873143b9aSmrg * that don't allow IPv4 over IPv6 sockets. 142973143b9aSmrg */ 143073143b9aSmrg TRANS(SocketINETClose)(ciptr); 143173143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 143273143b9aSmrg "tcp", "tcp", host, port, ciptr->index); 143373143b9aSmrg if (newciptr) 143473143b9aSmrg ciptr->fd = newciptr->fd; 143573143b9aSmrg if (!newciptr || 143673143b9aSmrg Sockettrans2devtab[newciptr->index].family != 143773143b9aSmrg AF_INET) { 143873143b9aSmrg socketaddr = NULL; 1439fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv4 " 1440fe567363Smrg " socketfor IPv4 address\n"); 144173143b9aSmrg } 144273143b9aSmrg if (newciptr) 1443fe567363Smrg free(newciptr); 144473143b9aSmrg } else { 144573143b9aSmrg socketaddr = NULL; 1446fe567363Smrg prmsg (4,"SocketINETConnect Skipping IPv4 address\n"); 144773143b9aSmrg } 144873143b9aSmrg } 144973143b9aSmrg } else if (addrlist->addr->ai_family == AF_INET6) { 145073143b9aSmrg struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; 1451fe567363Smrg 1452fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_addr = %s\n", 145373143b9aSmrg inet_ntop(addrlist->addr->ai_family, 1454fe567363Smrg &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf))); 1455fe567363Smrg prmsg (4,"SocketINETConnect() sockname.sin6_port = %d\n", 1456fe567363Smrg ntohs(sin6->sin6_port)); 145773143b9aSmrg 145873143b9aSmrg if (Sockettrans2devtab[ciptr->index].family == AF_INET) { 145973143b9aSmrg if (strcmp(Sockettrans2devtab[ciptr->index].transname, 146073143b9aSmrg "tcp") == 0) { 146173143b9aSmrg XtransConnInfo newciptr; 146273143b9aSmrg 146373143b9aSmrg /* 146473143b9aSmrg * Close the IPv4 socket and try to open an IPv6 socket. 146573143b9aSmrg */ 146673143b9aSmrg TRANS(SocketINETClose)(ciptr); 146773143b9aSmrg newciptr = TRANS(SocketOpenCOTSClientBase)( 146873143b9aSmrg "tcp", "tcp", host, port, -1); 146973143b9aSmrg if (newciptr) 147073143b9aSmrg ciptr->fd = newciptr->fd; 147173143b9aSmrg if (!newciptr || 147273143b9aSmrg Sockettrans2devtab[newciptr->index].family != 147373143b9aSmrg AF_INET6) { 147473143b9aSmrg socketaddr = NULL; 1475fe567363Smrg prmsg (4,"SocketINETConnect() Cannot get IPv6 " 1476fe567363Smrg "socket for IPv6 address\n"); 147773143b9aSmrg } 147873143b9aSmrg if (newciptr) 1479fe567363Smrg free(newciptr); 148073143b9aSmrg } 148173143b9aSmrg else 148273143b9aSmrg { 148373143b9aSmrg socketaddr = NULL; 1484fe567363Smrg prmsg (4,"SocketINETConnect() Skipping IPv6 address\n"); 148573143b9aSmrg } 148673143b9aSmrg } 148773143b9aSmrg } else { 148873143b9aSmrg socketaddr = NULL; /* Unsupported address type */ 148973143b9aSmrg } 149073143b9aSmrg if (socketaddr == NULL) { 149173143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 149273143b9aSmrg } 1493fe567363Smrg } 1494b53e5eeaSmrg } 1495b53e5eeaSmrg#else 149673143b9aSmrg { 149773143b9aSmrg /* 149873143b9aSmrg * Build the socket name. 149973143b9aSmrg */ 150073143b9aSmrg 150173143b9aSmrg#ifdef BSD44SOCKETS 150273143b9aSmrg sockname.sin_len = sizeof (struct sockaddr_in); 150373143b9aSmrg#endif 150473143b9aSmrg sockname.sin_family = AF_INET; 150573143b9aSmrg 150673143b9aSmrg /* 150773143b9aSmrg * fill in sin_addr 150873143b9aSmrg */ 150973143b9aSmrg 151073143b9aSmrg#ifndef INADDR_NONE 151173143b9aSmrg#define INADDR_NONE ((in_addr_t) 0xffffffff) 151273143b9aSmrg#endif 151373143b9aSmrg 151473143b9aSmrg /* check for ww.xx.yy.zz host string */ 151573143b9aSmrg 151673143b9aSmrg if (isascii (host[0]) && isdigit (host[0])) { 151773143b9aSmrg tmpaddr = inet_addr (host); /* returns network byte order */ 151873143b9aSmrg } else { 151973143b9aSmrg tmpaddr = INADDR_NONE; 152073143b9aSmrg } 152173143b9aSmrg 152281d6fa61Srin prmsg (4,"SocketINETConnect() inet_addr(%s) = %lx\n", host, tmpaddr); 152373143b9aSmrg 152473143b9aSmrg if (tmpaddr == INADDR_NONE) { 152573143b9aSmrg if ((hostp = _XGethostbyname(host,hparams)) == NULL) { 1526fe567363Smrg prmsg (1,"SocketINETConnect: Can't get address for %s\n", 1527fe567363Smrg host); 152873143b9aSmrg ESET(EINVAL); 152973143b9aSmrg return TRANS_CONNECT_FAILED; 153073143b9aSmrg } 153173143b9aSmrg if (hostp->h_addrtype != AF_INET) { /* is IP host? */ 1532fe567363Smrg prmsg (1,"SocketINETConnect: not INET host%s\n", host); 153373143b9aSmrg ESET(EPROTOTYPE); 153473143b9aSmrg return TRANS_CONNECT_FAILED; 153573143b9aSmrg } 1536fe567363Smrg 153773143b9aSmrg memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, 153873143b9aSmrg sizeof (sockname.sin_addr)); 153973143b9aSmrg 154073143b9aSmrg } else { 154173143b9aSmrg sockname.sin_addr.s_addr = tmpaddr; 154273143b9aSmrg } 154373143b9aSmrg 154473143b9aSmrg /* 154573143b9aSmrg * fill in sin_port 154673143b9aSmrg */ 154773143b9aSmrg 154873143b9aSmrg /* Check for number in the port string */ 154973143b9aSmrg 155073143b9aSmrg if (!is_numeric (port)) { 155173143b9aSmrg if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) { 1552fe567363Smrg prmsg (1,"SocketINETConnect: can't get service for %s\n", 1553fe567363Smrg port); 155473143b9aSmrg return TRANS_CONNECT_FAILED; 155573143b9aSmrg } 155673143b9aSmrg sockname.sin_port = htons (servp->s_port); 155773143b9aSmrg } else { 1558fe567363Smrg long tmpport = strtol (port, (char**)NULL, 10); 155973143b9aSmrg if (tmpport < 1024 || tmpport > USHRT_MAX) 156073143b9aSmrg return TRANS_CONNECT_FAILED; 156173143b9aSmrg sockname.sin_port = htons (((unsigned short) tmpport)); 156273143b9aSmrg } 156373143b9aSmrg 1564fe567363Smrg prmsg (4,"SocketINETConnect: sockname.sin_port = %d\n", 1565fe567363Smrg ntohs(sockname.sin_port)); 156673143b9aSmrg socketaddr = (struct sockaddr *) &sockname; 156773143b9aSmrg socketaddrlen = sizeof(sockname); 156873143b9aSmrg } 1569b53e5eeaSmrg#endif 157073143b9aSmrg 157173143b9aSmrg /* 157273143b9aSmrg * Turn on socket keepalive so the client process will eventually 157373143b9aSmrg * be notified with a SIGPIPE signal if the display server fails 157473143b9aSmrg * to respond to a periodic transmission of messages 157573143b9aSmrg * on the connected socket. 157673143b9aSmrg * This is useful to avoid hung application processes when the 157773143b9aSmrg * processes are not spawned from the xdm session and 157873143b9aSmrg * the display server terminates abnormally. 157973143b9aSmrg * (Someone turned off the power switch.) 158073143b9aSmrg */ 158173143b9aSmrg 158273143b9aSmrg { 158373143b9aSmrg int tmp = 1; 158473143b9aSmrg setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE, 158573143b9aSmrg (char *) &tmp, sizeof (int)); 158673143b9aSmrg } 158773143b9aSmrg 158873143b9aSmrg /* 158973143b9aSmrg * Do the connect() 159073143b9aSmrg */ 159173143b9aSmrg 159273143b9aSmrg if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) 159373143b9aSmrg { 159473143b9aSmrg#ifdef WIN32 159573143b9aSmrg int olderrno = WSAGetLastError(); 159673143b9aSmrg#else 159773143b9aSmrg int olderrno = errno; 159873143b9aSmrg#endif 159973143b9aSmrg 160073143b9aSmrg /* 160173143b9aSmrg * If the error was ECONNREFUSED, the server may be overloaded 160273143b9aSmrg * and we should try again. 160373143b9aSmrg * 160473143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 160573143b9aSmrg * was non-blocking and we should poll using select 160673143b9aSmrg * 160773143b9aSmrg * If the error was EINTR, the connect was interrupted and we 160873143b9aSmrg * should try again. 160973143b9aSmrg * 161073143b9aSmrg * If multiple addresses are found for a host then we should 161173143b9aSmrg * try to connect again with a different address for a larger 161273143b9aSmrg * number of errors that made us quit before, since those 161373143b9aSmrg * could be caused by trying to use an IPv6 address to contact 161473143b9aSmrg * a machine with an IPv4-only server or other reasons that 1615fe567363Smrg * only affect one of a set of addresses. 161673143b9aSmrg */ 161773143b9aSmrg 161873143b9aSmrg if (olderrno == ECONNREFUSED || olderrno == EINTR 161973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1620b53e5eeaSmrg || (((addrlist->addr->ai_next != NULL) || 162173143b9aSmrg (addrlist->addr != addrlist->firstaddr)) && 162273143b9aSmrg (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT || 162373143b9aSmrg olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT 162473143b9aSmrg#if defined(EHOSTDOWN) 162573143b9aSmrg || olderrno == EHOSTDOWN 162673143b9aSmrg#endif 162773143b9aSmrg )) 162873143b9aSmrg#endif 162973143b9aSmrg ) 163073143b9aSmrg res = TRANS_TRY_CONNECT_AGAIN; 163173143b9aSmrg else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 163273143b9aSmrg res = TRANS_IN_PROGRESS; 163373143b9aSmrg else 163473143b9aSmrg { 1635fe567363Smrg prmsg (2,"SocketINETConnect: Can't connect: errno = %d\n", 1636fe567363Smrg olderrno); 163773143b9aSmrg 1638fe567363Smrg res = TRANS_CONNECT_FAILED; 163973143b9aSmrg } 164073143b9aSmrg } else { 164173143b9aSmrg res = 0; 1642fe567363Smrg 164373143b9aSmrg 164473143b9aSmrg /* 164573143b9aSmrg * Sync up the address fields of ciptr. 164673143b9aSmrg */ 1647fe567363Smrg 164873143b9aSmrg if (TRANS(SocketINETGetAddr) (ciptr) < 0) 164973143b9aSmrg { 1650fe567363Smrg prmsg (1, 1651fe567363Smrg "SocketINETConnect: ...SocketINETGetAddr() failed:\n"); 165273143b9aSmrg res = TRANS_CONNECT_FAILED; 165373143b9aSmrg } 165473143b9aSmrg 165573143b9aSmrg else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) 165673143b9aSmrg { 1657fe567363Smrg prmsg (1, 1658fe567363Smrg "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n"); 165973143b9aSmrg res = TRANS_CONNECT_FAILED; 166073143b9aSmrg } 166173143b9aSmrg } 166273143b9aSmrg 166373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 1664b53e5eeaSmrg if (res != 0) { 166573143b9aSmrg addrlist->addr = addrlist->addr->ai_next; 166673143b9aSmrg } 166773143b9aSmrg#endif 166873143b9aSmrg 166973143b9aSmrg return res; 167073143b9aSmrg} 167173143b9aSmrg 167273143b9aSmrg#endif /* TCPCONN */ 167373143b9aSmrg 167473143b9aSmrg 167573143b9aSmrg 167673143b9aSmrg#ifdef UNIXCONN 167773143b9aSmrg 167873143b9aSmrg/* 167973143b9aSmrg * Make sure 'host' is really local. 168073143b9aSmrg */ 168173143b9aSmrg 168273143b9aSmrgstatic int 16836a3641a6SsnjUnixHostReallyLocal (const char *host) 168473143b9aSmrg 168573143b9aSmrg{ 168673143b9aSmrg char hostnamebuf[256]; 168773143b9aSmrg 168873143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 168973143b9aSmrg 169073143b9aSmrg if (strcmp (hostnamebuf, host) == 0) 169173143b9aSmrg { 169273143b9aSmrg return (1); 1693b53e5eeaSmrg } else { 169473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 169573143b9aSmrg struct addrinfo *localhostaddr; 169673143b9aSmrg struct addrinfo *otherhostaddr; 169773143b9aSmrg struct addrinfo *i, *j; 169873143b9aSmrg int equiv = 0; 169973143b9aSmrg 170073143b9aSmrg if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0) 170173143b9aSmrg return 0; 170273143b9aSmrg if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) { 170373143b9aSmrg freeaddrinfo(localhostaddr); 170473143b9aSmrg return 0; 170573143b9aSmrg } 170673143b9aSmrg 170773143b9aSmrg for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) { 170873143b9aSmrg for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) { 170973143b9aSmrg if (i->ai_family == j->ai_family) { 171073143b9aSmrg if (i->ai_family == AF_INET) { 1711fe567363Smrg struct sockaddr_in *sinA 171273143b9aSmrg = (struct sockaddr_in *) i->ai_addr; 171373143b9aSmrg struct sockaddr_in *sinB 171473143b9aSmrg = (struct sockaddr_in *) j->ai_addr; 171573143b9aSmrg struct in_addr *A = &sinA->sin_addr; 171673143b9aSmrg struct in_addr *B = &sinB->sin_addr; 171773143b9aSmrg 171873143b9aSmrg if (memcmp(A,B,sizeof(struct in_addr)) == 0) { 171973143b9aSmrg equiv = 1; 172073143b9aSmrg } 172173143b9aSmrg } else if (i->ai_family == AF_INET6) { 1722fe567363Smrg struct sockaddr_in6 *sinA 172373143b9aSmrg = (struct sockaddr_in6 *) i->ai_addr; 1724fe567363Smrg struct sockaddr_in6 *sinB 172573143b9aSmrg = (struct sockaddr_in6 *) j->ai_addr; 172673143b9aSmrg struct in6_addr *A = &sinA->sin6_addr; 172773143b9aSmrg struct in6_addr *B = &sinB->sin6_addr; 172873143b9aSmrg 172973143b9aSmrg if (memcmp(A,B,sizeof(struct in6_addr)) == 0) { 173073143b9aSmrg equiv = 1; 173173143b9aSmrg } 173273143b9aSmrg } 173373143b9aSmrg } 173473143b9aSmrg } 173573143b9aSmrg } 1736fe567363Smrg 173773143b9aSmrg freeaddrinfo(localhostaddr); 173873143b9aSmrg freeaddrinfo(otherhostaddr); 173973143b9aSmrg return equiv; 1740b53e5eeaSmrg#else 174173143b9aSmrg /* 174273143b9aSmrg * A host may have more than one network address. If any of the 174373143b9aSmrg * network addresses of 'host' (specified to the connect call) 174473143b9aSmrg * match any of the network addresses of 'hostname' (determined 174573143b9aSmrg * by TRANS(GetHostname)), then the two hostnames are equivalent, 174673143b9aSmrg * and we know that 'host' is really a local host. 174773143b9aSmrg */ 174873143b9aSmrg char specified_local_addr_list[10][4]; 174973143b9aSmrg int scount, equiv, i, j; 175073143b9aSmrg#ifdef XTHREADS_NEEDS_BYNAMEPARAMS 175173143b9aSmrg _Xgethostbynameparams hparams; 175273143b9aSmrg#endif 175373143b9aSmrg struct hostent *hostp; 175473143b9aSmrg 175573143b9aSmrg if ((hostp = _XGethostbyname (host,hparams)) == NULL) 175673143b9aSmrg return (0); 175773143b9aSmrg 175873143b9aSmrg scount = 0; 175973143b9aSmrg while (hostp->h_addr_list[scount] && scount <= 8) 176073143b9aSmrg { 176173143b9aSmrg /* 176273143b9aSmrg * The 2nd call to gethostname() overrides the data 176373143b9aSmrg * from the 1st call, so we must save the address list. 176473143b9aSmrg */ 176573143b9aSmrg 1766fe567363Smrg specified_local_addr_list[scount][0] = 176773143b9aSmrg hostp->h_addr_list[scount][0]; 1768fe567363Smrg specified_local_addr_list[scount][1] = 176973143b9aSmrg hostp->h_addr_list[scount][1]; 1770fe567363Smrg specified_local_addr_list[scount][2] = 177173143b9aSmrg hostp->h_addr_list[scount][2]; 1772fe567363Smrg specified_local_addr_list[scount][3] = 177373143b9aSmrg hostp->h_addr_list[scount][3]; 177473143b9aSmrg scount++; 177573143b9aSmrg } 177673143b9aSmrg if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL) 177773143b9aSmrg return (0); 177873143b9aSmrg 177973143b9aSmrg equiv = 0; 178073143b9aSmrg i = 0; 178173143b9aSmrg 178273143b9aSmrg while (i < scount && !equiv) 178373143b9aSmrg { 178473143b9aSmrg j = 0; 178573143b9aSmrg 178673143b9aSmrg while (hostp->h_addr_list[j]) 178773143b9aSmrg { 1788fe567363Smrg if ((specified_local_addr_list[i][0] == 178973143b9aSmrg hostp->h_addr_list[j][0]) && 1790fe567363Smrg (specified_local_addr_list[i][1] == 179173143b9aSmrg hostp->h_addr_list[j][1]) && 1792fe567363Smrg (specified_local_addr_list[i][2] == 179373143b9aSmrg hostp->h_addr_list[j][2]) && 1794fe567363Smrg (specified_local_addr_list[i][3] == 179573143b9aSmrg hostp->h_addr_list[j][3])) 179673143b9aSmrg { 179773143b9aSmrg /* They're equal, so we're done */ 1798fe567363Smrg 179973143b9aSmrg equiv = 1; 180073143b9aSmrg break; 180173143b9aSmrg } 180273143b9aSmrg 180373143b9aSmrg j++; 180473143b9aSmrg } 180573143b9aSmrg 180673143b9aSmrg i++; 180773143b9aSmrg } 180873143b9aSmrg return (equiv); 1809b53e5eeaSmrg#endif 181073143b9aSmrg } 181173143b9aSmrg} 181273143b9aSmrg 181373143b9aSmrgstatic int 18146a3641a6SsnjTRANS(SocketUNIXConnect) (XtransConnInfo ciptr, 18156a3641a6Ssnj const char *host, const char *port) 181673143b9aSmrg 181773143b9aSmrg{ 181873143b9aSmrg struct sockaddr_un sockname; 181973143b9aSmrg SOCKLEN_T namelen; 182073143b9aSmrg 182173143b9aSmrg 182273143b9aSmrg int abstract = 0; 182373143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 182473143b9aSmrg abstract = ciptr->transptr->flags & TRANS_ABSTRACT; 182573143b9aSmrg#endif 182673143b9aSmrg 1827fe567363Smrg prmsg (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); 1828fe567363Smrg 182973143b9aSmrg /* 183073143b9aSmrg * Make sure 'host' is really local. If not, we return failure. 183173143b9aSmrg * The reason we make this check is because a process may advertise 183273143b9aSmrg * a "local" network ID for which it can accept connections, but if 183373143b9aSmrg * a process on a remote machine tries to connect to this network ID, 183473143b9aSmrg * we know for sure it will fail. 183573143b9aSmrg */ 183673143b9aSmrg 183773143b9aSmrg if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) 183873143b9aSmrg { 1839fe567363Smrg prmsg (1, 184073143b9aSmrg "SocketUNIXConnect: Cannot connect to non-local host %s\n", 1841fe567363Smrg host); 184273143b9aSmrg return TRANS_CONNECT_FAILED; 184373143b9aSmrg } 184473143b9aSmrg 184573143b9aSmrg 184673143b9aSmrg /* 184773143b9aSmrg * Check the port. 184873143b9aSmrg */ 184973143b9aSmrg 185073143b9aSmrg if (!port || !*port) 185173143b9aSmrg { 1852fe567363Smrg prmsg (1,"SocketUNIXConnect: Missing port specification\n"); 185373143b9aSmrg return TRANS_CONNECT_FAILED; 185473143b9aSmrg } 185573143b9aSmrg 185673143b9aSmrg /* 185773143b9aSmrg * Build the socket name. 185873143b9aSmrg */ 1859fe567363Smrg 186073143b9aSmrg sockname.sun_family = AF_UNIX; 186173143b9aSmrg 186273143b9aSmrg if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) { 1863fe567363Smrg prmsg (1, "SocketUNIXConnect: path too long\n"); 186473143b9aSmrg return TRANS_CONNECT_FAILED; 186573143b9aSmrg } 186673143b9aSmrg 1867fe567363Smrg#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 186873143b9aSmrg sockname.sun_len = strlen (sockname.sun_path); 186973143b9aSmrg#endif 187073143b9aSmrg 187173143b9aSmrg#if defined(BSD44SOCKETS) || defined(SUN_LEN) 187273143b9aSmrg namelen = SUN_LEN (&sockname); 187373143b9aSmrg#else 187473143b9aSmrg namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path); 187573143b9aSmrg#endif 187673143b9aSmrg 187773143b9aSmrg 187873143b9aSmrg 187973143b9aSmrg /* 188073143b9aSmrg * Adjust the socket path if using abstract sockets. 188173143b9aSmrg * Done here because otherwise all the strlen() calls above would fail. 188273143b9aSmrg */ 188373143b9aSmrg 188473143b9aSmrg if (abstract) { 188573143b9aSmrg sockname.sun_path[0] = '\0'; 188673143b9aSmrg } 188773143b9aSmrg 188873143b9aSmrg /* 188973143b9aSmrg * Do the connect() 189073143b9aSmrg */ 189173143b9aSmrg 189273143b9aSmrg if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) 189373143b9aSmrg { 189473143b9aSmrg int olderrno = errno; 189573143b9aSmrg int connected = 0; 1896fe567363Smrg 189773143b9aSmrg if (!connected) 189873143b9aSmrg { 189973143b9aSmrg errno = olderrno; 1900fe567363Smrg 190173143b9aSmrg /* 190273143b9aSmrg * If the error was ENOENT, the server may be starting up; we used 190373143b9aSmrg * to suggest to try again in this case with 190473143b9aSmrg * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for 190573143b9aSmrg * processes still referencing stale sockets in their environment. 190673143b9aSmrg * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it 190773143b9aSmrg * is suggested that higher level stacks handle retries on their 190873143b9aSmrg * level when they face a slow starting server. 190973143b9aSmrg * 191073143b9aSmrg * If the error was EWOULDBLOCK or EINPROGRESS then the socket 191173143b9aSmrg * was non-blocking and we should poll using select 191273143b9aSmrg * 191373143b9aSmrg * If the error was EINTR, the connect was interrupted and we 191473143b9aSmrg * should try again. 191573143b9aSmrg */ 191673143b9aSmrg 191773143b9aSmrg if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) 191873143b9aSmrg return TRANS_IN_PROGRESS; 191973143b9aSmrg else if (olderrno == EINTR) 192073143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 19218d4c0f7bSmrg else if (olderrno == ENOENT || olderrno == ECONNREFUSED) { 192273143b9aSmrg /* If opening as abstract socket failed, try again normally */ 192373143b9aSmrg if (abstract) { 192473143b9aSmrg ciptr->transptr->flags &= ~(TRANS_ABSTRACT); 192573143b9aSmrg return TRANS_TRY_CONNECT_AGAIN; 192673143b9aSmrg } else { 192773143b9aSmrg return TRANS_CONNECT_FAILED; 192873143b9aSmrg } 192973143b9aSmrg } else { 1930fe567363Smrg prmsg (2,"SocketUNIXConnect: Can't connect: errno = %d\n", 1931fe567363Smrg EGET()); 193273143b9aSmrg 193373143b9aSmrg return TRANS_CONNECT_FAILED; 193473143b9aSmrg } 193573143b9aSmrg } 193673143b9aSmrg } 193773143b9aSmrg 193873143b9aSmrg /* 193973143b9aSmrg * Get the socket name and the peer name from the connect socket, 194073143b9aSmrg * since this is unix domain. 194173143b9aSmrg */ 194273143b9aSmrg 1943fe567363Smrg if ((ciptr->addr = malloc(namelen)) == NULL || 1944fe567363Smrg (ciptr->peeraddr = malloc(namelen)) == NULL) 194573143b9aSmrg { 1946fe567363Smrg prmsg (1, 1947fe567363Smrg "SocketUNIXCreateListener: Can't allocate space for the addr\n"); 194873143b9aSmrg return TRANS_CONNECT_FAILED; 194973143b9aSmrg } 195073143b9aSmrg 195173143b9aSmrg if (abstract) 195273143b9aSmrg sockname.sun_path[0] = '@'; 195373143b9aSmrg 195473143b9aSmrg ciptr->family = AF_UNIX; 195573143b9aSmrg ciptr->addrlen = namelen; 195673143b9aSmrg ciptr->peeraddrlen = namelen; 195773143b9aSmrg memcpy (ciptr->addr, &sockname, ciptr->addrlen); 195873143b9aSmrg memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); 195973143b9aSmrg 196073143b9aSmrg return 0; 196173143b9aSmrg} 196273143b9aSmrg 196373143b9aSmrg#endif /* UNIXCONN */ 196473143b9aSmrg 196573143b9aSmrg#endif /* TRANS_CLIENT */ 196673143b9aSmrg 196773143b9aSmrg 196873143b9aSmrgstatic int 196973143b9aSmrgTRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 197073143b9aSmrg 197173143b9aSmrg{ 1972fe567363Smrg prmsg (2,"SocketBytesReadable(%p,%d,%p)\n", 197373143b9aSmrg ciptr, ciptr->fd, pend); 197473143b9aSmrg#ifdef WIN32 197573143b9aSmrg { 197673143b9aSmrg int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); 197773143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 197873143b9aSmrg return ret; 197973143b9aSmrg } 198073143b9aSmrg#else 198173143b9aSmrg return ioctl (ciptr->fd, FIONREAD, (char *) pend); 198273143b9aSmrg#endif /* WIN32 */ 198373143b9aSmrg} 198473143b9aSmrg 198575ebec6dSmrg#if XTRANS_SEND_FDS 198675ebec6dSmrg 198775ebec6dSmrgstatic void 198875ebec6dSmrgappendFd(struct _XtransConnFd **prev, int fd, int do_close) 198975ebec6dSmrg{ 199075ebec6dSmrg struct _XtransConnFd *cf, *new; 199175ebec6dSmrg 199275ebec6dSmrg new = malloc (sizeof (struct _XtransConnFd)); 199375ebec6dSmrg if (!new) { 199475ebec6dSmrg /* XXX mark connection as broken */ 199575ebec6dSmrg close(fd); 199675ebec6dSmrg return; 199775ebec6dSmrg } 199875ebec6dSmrg new->next = 0; 199975ebec6dSmrg new->fd = fd; 200075ebec6dSmrg new->do_close = do_close; 200175ebec6dSmrg /* search to end of list */ 200275ebec6dSmrg for (; (cf = *prev); prev = &(cf->next)); 200375ebec6dSmrg *prev = new; 200475ebec6dSmrg} 200573143b9aSmrg 200673143b9aSmrgstatic int 200775ebec6dSmrgremoveFd(struct _XtransConnFd **prev) 200875ebec6dSmrg{ 200975ebec6dSmrg struct _XtransConnFd *cf; 201075ebec6dSmrg int fd; 201175ebec6dSmrg 201275ebec6dSmrg if ((cf = *prev)) { 201375ebec6dSmrg *prev = cf->next; 201475ebec6dSmrg fd = cf->fd; 201575ebec6dSmrg free(cf); 201675ebec6dSmrg } else 201775ebec6dSmrg fd = -1; 201875ebec6dSmrg return fd; 201975ebec6dSmrg} 202073143b9aSmrg 202175ebec6dSmrgstatic void 202275ebec6dSmrgdiscardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) 202373143b9aSmrg{ 202475ebec6dSmrg struct _XtransConnFd *cf, *next; 202573143b9aSmrg 202675ebec6dSmrg for (cf = *prev; cf != upto; cf = next) { 202775ebec6dSmrg next = cf->next; 202875ebec6dSmrg if (do_close || cf->do_close) 202975ebec6dSmrg close(cf->fd); 203075ebec6dSmrg free(cf); 203173143b9aSmrg } 203275ebec6dSmrg *prev = upto; 203373143b9aSmrg} 203473143b9aSmrg 203575ebec6dSmrgstatic void 203675ebec6dSmrgcleanupFds(XtransConnInfo ciptr) 203775ebec6dSmrg{ 203875ebec6dSmrg /* Clean up the send list but don't close the fds */ 203975ebec6dSmrg discardFd(&ciptr->send_fds, NULL, 0); 204075ebec6dSmrg /* Clean up the recv list and *do* close the fds */ 204175ebec6dSmrg discardFd(&ciptr->recv_fds, NULL, 1); 204275ebec6dSmrg} 204373143b9aSmrg 204473143b9aSmrgstatic int 204575ebec6dSmrgnFd(struct _XtransConnFd **prev) 204675ebec6dSmrg{ 204775ebec6dSmrg struct _XtransConnFd *cf; 204875ebec6dSmrg int n = 0; 204975ebec6dSmrg 205075ebec6dSmrg for (cf = *prev; cf; cf = cf->next) 205175ebec6dSmrg n++; 205275ebec6dSmrg return n; 205375ebec6dSmrg} 205473143b9aSmrg 205575ebec6dSmrgstatic int 205675ebec6dSmrgTRANS(SocketRecvFd) (XtransConnInfo ciptr) 205773143b9aSmrg{ 205875ebec6dSmrg prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); 205975ebec6dSmrg return removeFd(&ciptr->recv_fds); 206075ebec6dSmrg} 206175ebec6dSmrg 206275ebec6dSmrgstatic int 206375ebec6dSmrgTRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) 206475ebec6dSmrg{ 206575ebec6dSmrg appendFd(&ciptr->send_fds, fd, do_close); 206675ebec6dSmrg return 0; 206775ebec6dSmrg} 206875ebec6dSmrg 206975ebec6dSmrgstatic int 207075ebec6dSmrgTRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) 207175ebec6dSmrg{ 207275ebec6dSmrg errno = EINVAL; 207375ebec6dSmrg return -1; 207475ebec6dSmrg} 207575ebec6dSmrg 207675ebec6dSmrgstatic int 207775ebec6dSmrgTRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) 207875ebec6dSmrg{ 207975ebec6dSmrg errno = EINVAL; 208075ebec6dSmrg return -1; 208175ebec6dSmrg} 208275ebec6dSmrg 208375ebec6dSmrg#define MAX_FDS 128 208475ebec6dSmrg 208575ebec6dSmrgunion fd_pass { 208675ebec6dSmrg struct cmsghdr cmsghdr; 208775ebec6dSmrg char buf[CMSG_SPACE(MAX_FDS * sizeof(int))]; 208875ebec6dSmrg}; 208975ebec6dSmrg 209075ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 209175ebec6dSmrg 209275ebec6dSmrgstatic int 209375ebec6dSmrgTRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) 209475ebec6dSmrg 209575ebec6dSmrg{ 209675ebec6dSmrg prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); 209773143b9aSmrg 2098fe567363Smrg#if defined(WIN32) 209973143b9aSmrg { 210075ebec6dSmrg int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); 210173143b9aSmrg#ifdef WIN32 210273143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 210373143b9aSmrg#endif 210473143b9aSmrg return ret; 210573143b9aSmrg } 210673143b9aSmrg#else 210775ebec6dSmrg#if XTRANS_SEND_FDS 210875ebec6dSmrg { 210975ebec6dSmrg struct iovec iov = { 211075ebec6dSmrg .iov_base = buf, 211175ebec6dSmrg .iov_len = size 211275ebec6dSmrg }; 211375ebec6dSmrg union fd_pass cmsgbuf; 211475ebec6dSmrg struct msghdr msg = { 211575ebec6dSmrg .msg_name = NULL, 211675ebec6dSmrg .msg_namelen = 0, 211775ebec6dSmrg .msg_iov = &iov, 211875ebec6dSmrg .msg_iovlen = 1, 211975ebec6dSmrg .msg_control = cmsgbuf.buf, 212075ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 212175ebec6dSmrg }; 212275ebec6dSmrg 212375ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 212475ebec6dSmrg if (size >= 0) { 212575ebec6dSmrg struct cmsghdr *hdr; 212675ebec6dSmrg 212775ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 212875ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 212975ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 213075ebec6dSmrg int i; 213175ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 213275ebec6dSmrg 213375ebec6dSmrg for (i = 0; i < nfd; i++) 213475ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 213575ebec6dSmrg } 213675ebec6dSmrg } 213775ebec6dSmrg } 213875ebec6dSmrg return size; 213975ebec6dSmrg } 214075ebec6dSmrg#else 214175ebec6dSmrg return read(ciptr->fd, buf, size); 214275ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 214373143b9aSmrg#endif /* WIN32 */ 214473143b9aSmrg} 214573143b9aSmrg 214673143b9aSmrgstatic int 214773143b9aSmrgTRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) 214873143b9aSmrg 214973143b9aSmrg{ 2150fe567363Smrg prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); 215173143b9aSmrg 215275ebec6dSmrg#if XTRANS_SEND_FDS 215375ebec6dSmrg { 215475ebec6dSmrg union fd_pass cmsgbuf; 215575ebec6dSmrg struct msghdr msg = { 215675ebec6dSmrg .msg_name = NULL, 215775ebec6dSmrg .msg_namelen = 0, 215875ebec6dSmrg .msg_iov = buf, 215975ebec6dSmrg .msg_iovlen = size, 216075ebec6dSmrg .msg_control = cmsgbuf.buf, 216175ebec6dSmrg .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) 216275ebec6dSmrg }; 216375ebec6dSmrg 216475ebec6dSmrg size = recvmsg(ciptr->fd, &msg, 0); 216575ebec6dSmrg if (size >= 0) { 216675ebec6dSmrg struct cmsghdr *hdr; 216775ebec6dSmrg 216875ebec6dSmrg for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { 216975ebec6dSmrg if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { 217075ebec6dSmrg int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); 217175ebec6dSmrg int i; 217275ebec6dSmrg int *fd = (int *) CMSG_DATA(hdr); 217375ebec6dSmrg 217475ebec6dSmrg for (i = 0; i < nfd; i++) 217575ebec6dSmrg appendFd(&ciptr->recv_fds, fd[i], 0); 217675ebec6dSmrg } 217775ebec6dSmrg } 217875ebec6dSmrg } 217975ebec6dSmrg return size; 218075ebec6dSmrg } 218175ebec6dSmrg#else 218273143b9aSmrg return READV (ciptr, buf, size); 218375ebec6dSmrg#endif 218473143b9aSmrg} 218573143b9aSmrg 218673143b9aSmrg 218773143b9aSmrgstatic int 218873143b9aSmrgTRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) 218973143b9aSmrg 219073143b9aSmrg{ 2191fe567363Smrg prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); 219273143b9aSmrg 219375ebec6dSmrg#if XTRANS_SEND_FDS 219475ebec6dSmrg if (ciptr->send_fds) 219575ebec6dSmrg { 219675ebec6dSmrg union fd_pass cmsgbuf; 219775ebec6dSmrg int nfd = nFd(&ciptr->send_fds); 219875ebec6dSmrg struct _XtransConnFd *cf = ciptr->send_fds; 219975ebec6dSmrg struct msghdr msg = { 220075ebec6dSmrg .msg_name = NULL, 220175ebec6dSmrg .msg_namelen = 0, 220275ebec6dSmrg .msg_iov = buf, 220375ebec6dSmrg .msg_iovlen = size, 220475ebec6dSmrg .msg_control = cmsgbuf.buf, 220575ebec6dSmrg .msg_controllen = CMSG_LEN(nfd * sizeof(int)) 220675ebec6dSmrg }; 220775ebec6dSmrg struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 220875ebec6dSmrg int i; 220975ebec6dSmrg int *fds; 221075ebec6dSmrg 221175ebec6dSmrg hdr->cmsg_len = msg.msg_controllen; 221275ebec6dSmrg hdr->cmsg_level = SOL_SOCKET; 221375ebec6dSmrg hdr->cmsg_type = SCM_RIGHTS; 221475ebec6dSmrg 221575ebec6dSmrg fds = (int *) CMSG_DATA(hdr); 221675ebec6dSmrg /* Set up fds */ 221775ebec6dSmrg for (i = 0; i < nfd; i++) { 221875ebec6dSmrg fds[i] = cf->fd; 221975ebec6dSmrg cf = cf->next; 222075ebec6dSmrg } 222175ebec6dSmrg 222275ebec6dSmrg i = sendmsg(ciptr->fd, &msg, 0); 222375ebec6dSmrg if (i > 0) 222475ebec6dSmrg discardFd(&ciptr->send_fds, cf, 0); 222575ebec6dSmrg return i; 222675ebec6dSmrg } 222775ebec6dSmrg#endif 222873143b9aSmrg return WRITEV (ciptr, buf, size); 222973143b9aSmrg} 223073143b9aSmrg 223173143b9aSmrg 223275ebec6dSmrgstatic int 223375ebec6dSmrgTRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) 223475ebec6dSmrg 223575ebec6dSmrg{ 223675ebec6dSmrg prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); 223775ebec6dSmrg 223875ebec6dSmrg#if defined(WIN32) 223975ebec6dSmrg { 224075ebec6dSmrg int ret = send ((SOCKET)ciptr->fd, buf, size, 0); 224175ebec6dSmrg#ifdef WIN32 224275ebec6dSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 224375ebec6dSmrg#endif 224475ebec6dSmrg return ret; 224575ebec6dSmrg } 224675ebec6dSmrg#else 224775ebec6dSmrg#if XTRANS_SEND_FDS 224875ebec6dSmrg if (ciptr->send_fds) 224975ebec6dSmrg { 225075ebec6dSmrg struct iovec iov; 225175ebec6dSmrg 225275ebec6dSmrg iov.iov_base = buf; 225375ebec6dSmrg iov.iov_len = size; 225475ebec6dSmrg return TRANS(SocketWritev)(ciptr, &iov, 1); 225575ebec6dSmrg } 225675ebec6dSmrg#endif /* XTRANS_SEND_FDS */ 225775ebec6dSmrg return write (ciptr->fd, buf, size); 225875ebec6dSmrg#endif /* WIN32 */ 225975ebec6dSmrg} 226075ebec6dSmrg 226173143b9aSmrgstatic int 226273143b9aSmrgTRANS(SocketDisconnect) (XtransConnInfo ciptr) 226373143b9aSmrg 226473143b9aSmrg{ 2265fe567363Smrg prmsg (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd); 226673143b9aSmrg 226773143b9aSmrg#ifdef WIN32 2268fe567363Smrg { 226973143b9aSmrg int ret = shutdown (ciptr->fd, 2); 227073143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 227173143b9aSmrg return ret; 227273143b9aSmrg } 227373143b9aSmrg#else 227473143b9aSmrg return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ 227573143b9aSmrg#endif 227673143b9aSmrg} 227773143b9aSmrg 227873143b9aSmrg 227973143b9aSmrg#ifdef TCPCONN 228073143b9aSmrgstatic int 228173143b9aSmrgTRANS(SocketINETClose) (XtransConnInfo ciptr) 228273143b9aSmrg 228373143b9aSmrg{ 2284fe567363Smrg prmsg (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd); 228573143b9aSmrg 228673143b9aSmrg#ifdef WIN32 228773143b9aSmrg { 228873143b9aSmrg int ret = close (ciptr->fd); 228973143b9aSmrg if (ret == SOCKET_ERROR) errno = WSAGetLastError(); 229073143b9aSmrg return ret; 229173143b9aSmrg } 229273143b9aSmrg#else 229373143b9aSmrg return close (ciptr->fd); 229473143b9aSmrg#endif 229573143b9aSmrg} 229673143b9aSmrg 229773143b9aSmrg#endif /* TCPCONN */ 229873143b9aSmrg 229973143b9aSmrg 230073143b9aSmrg#ifdef UNIXCONN 230173143b9aSmrgstatic int 230273143b9aSmrgTRANS(SocketUNIXClose) (XtransConnInfo ciptr) 230373143b9aSmrg{ 230473143b9aSmrg /* 230573143b9aSmrg * If this is the server side, then once the socket is closed, 230673143b9aSmrg * it must be unlinked to completely close it 230773143b9aSmrg */ 230873143b9aSmrg 230973143b9aSmrg struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr; 231073143b9aSmrg int ret; 231173143b9aSmrg 2312fe567363Smrg prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd); 231373143b9aSmrg 231475ebec6dSmrg#if XTRANS_SEND_FDS 231575ebec6dSmrg cleanupFds(ciptr); 231675ebec6dSmrg#endif 231773143b9aSmrg ret = close(ciptr->fd); 231873143b9aSmrg 231973143b9aSmrg if (ciptr->flags 232073143b9aSmrg && sockname 232173143b9aSmrg && sockname->sun_family == AF_UNIX 232273143b9aSmrg && sockname->sun_path[0]) 232373143b9aSmrg { 232473143b9aSmrg if (!(ciptr->flags & TRANS_NOUNLINK 232573143b9aSmrg || ciptr->transptr->flags & TRANS_ABSTRACT)) 232673143b9aSmrg unlink (sockname->sun_path); 232773143b9aSmrg } 232873143b9aSmrg 232973143b9aSmrg return ret; 233073143b9aSmrg} 233173143b9aSmrg 233273143b9aSmrgstatic int 233373143b9aSmrgTRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) 233473143b9aSmrg 233573143b9aSmrg{ 233673143b9aSmrg /* 233773143b9aSmrg * Don't unlink path. 233873143b9aSmrg */ 233973143b9aSmrg 234073143b9aSmrg int ret; 234173143b9aSmrg 2342fe567363Smrg prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", 2343fe567363Smrg ciptr, ciptr->fd); 234473143b9aSmrg 234575ebec6dSmrg#if XTRANS_SEND_FDS 234675ebec6dSmrg cleanupFds(ciptr); 234775ebec6dSmrg#endif 234873143b9aSmrg ret = close(ciptr->fd); 234973143b9aSmrg 235073143b9aSmrg return ret; 235173143b9aSmrg} 235273143b9aSmrg 235373143b9aSmrg#endif /* UNIXCONN */ 235473143b9aSmrg 235573143b9aSmrg 235673143b9aSmrg#ifdef TCPCONN 235773143b9aSmrg# ifdef TRANS_SERVER 2358fe567363Smrgstatic const char* tcp_nolisten[] = { 235973143b9aSmrg "inet", 236073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 236173143b9aSmrg "inet6", 236273143b9aSmrg#endif 236373143b9aSmrg NULL 236473143b9aSmrg}; 236573143b9aSmrg# endif 236673143b9aSmrg 236773143b9aSmrgXtransport TRANS(SocketTCPFuncs) = { 236873143b9aSmrg /* Socket Interface */ 236973143b9aSmrg "tcp", 237073143b9aSmrg TRANS_ALIAS, 237173143b9aSmrg#ifdef TRANS_CLIENT 237273143b9aSmrg TRANS(SocketOpenCOTSClient), 237373143b9aSmrg#endif /* TRANS_CLIENT */ 237473143b9aSmrg#ifdef TRANS_SERVER 237573143b9aSmrg tcp_nolisten, 237673143b9aSmrg TRANS(SocketOpenCOTSServer), 237773143b9aSmrg#endif /* TRANS_SERVER */ 237873143b9aSmrg#ifdef TRANS_REOPEN 237973143b9aSmrg TRANS(SocketReopenCOTSServer), 238073143b9aSmrg#endif 238173143b9aSmrg TRANS(SocketSetOption), 238273143b9aSmrg#ifdef TRANS_SERVER 238373143b9aSmrg TRANS(SocketINETCreateListener), 238473143b9aSmrg NULL, /* ResetListener */ 238573143b9aSmrg TRANS(SocketINETAccept), 238673143b9aSmrg#endif /* TRANS_SERVER */ 238773143b9aSmrg#ifdef TRANS_CLIENT 238873143b9aSmrg TRANS(SocketINETConnect), 238973143b9aSmrg#endif /* TRANS_CLIENT */ 239073143b9aSmrg TRANS(SocketBytesReadable), 239173143b9aSmrg TRANS(SocketRead), 239273143b9aSmrg TRANS(SocketWrite), 239373143b9aSmrg TRANS(SocketReadv), 239473143b9aSmrg TRANS(SocketWritev), 239575ebec6dSmrg#if XTRANS_SEND_FDS 239675ebec6dSmrg TRANS(SocketSendFdInvalid), 239775ebec6dSmrg TRANS(SocketRecvFdInvalid), 239875ebec6dSmrg#endif 239973143b9aSmrg TRANS(SocketDisconnect), 240073143b9aSmrg TRANS(SocketINETClose), 240173143b9aSmrg TRANS(SocketINETClose), 240273143b9aSmrg }; 240373143b9aSmrg 240473143b9aSmrgXtransport TRANS(SocketINETFuncs) = { 240573143b9aSmrg /* Socket Interface */ 240673143b9aSmrg "inet", 240773143b9aSmrg 0, 240873143b9aSmrg#ifdef TRANS_CLIENT 240973143b9aSmrg TRANS(SocketOpenCOTSClient), 241073143b9aSmrg#endif /* TRANS_CLIENT */ 241173143b9aSmrg#ifdef TRANS_SERVER 241273143b9aSmrg NULL, 241373143b9aSmrg TRANS(SocketOpenCOTSServer), 241473143b9aSmrg#endif /* TRANS_SERVER */ 241573143b9aSmrg#ifdef TRANS_REOPEN 241673143b9aSmrg TRANS(SocketReopenCOTSServer), 241773143b9aSmrg#endif 241873143b9aSmrg TRANS(SocketSetOption), 241973143b9aSmrg#ifdef TRANS_SERVER 242073143b9aSmrg TRANS(SocketINETCreateListener), 242173143b9aSmrg NULL, /* ResetListener */ 242273143b9aSmrg TRANS(SocketINETAccept), 242373143b9aSmrg#endif /* TRANS_SERVER */ 242473143b9aSmrg#ifdef TRANS_CLIENT 242573143b9aSmrg TRANS(SocketINETConnect), 242673143b9aSmrg#endif /* TRANS_CLIENT */ 242773143b9aSmrg TRANS(SocketBytesReadable), 242873143b9aSmrg TRANS(SocketRead), 242973143b9aSmrg TRANS(SocketWrite), 243073143b9aSmrg TRANS(SocketReadv), 243173143b9aSmrg TRANS(SocketWritev), 243275ebec6dSmrg#if XTRANS_SEND_FDS 243375ebec6dSmrg TRANS(SocketSendFdInvalid), 243475ebec6dSmrg TRANS(SocketRecvFdInvalid), 243575ebec6dSmrg#endif 243673143b9aSmrg TRANS(SocketDisconnect), 243773143b9aSmrg TRANS(SocketINETClose), 243873143b9aSmrg TRANS(SocketINETClose), 243973143b9aSmrg }; 244073143b9aSmrg 244173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 244273143b9aSmrgXtransport TRANS(SocketINET6Funcs) = { 244373143b9aSmrg /* Socket Interface */ 244473143b9aSmrg "inet6", 244573143b9aSmrg 0, 244673143b9aSmrg#ifdef TRANS_CLIENT 244773143b9aSmrg TRANS(SocketOpenCOTSClient), 244873143b9aSmrg#endif /* TRANS_CLIENT */ 244973143b9aSmrg#ifdef TRANS_SERVER 245073143b9aSmrg NULL, 245173143b9aSmrg TRANS(SocketOpenCOTSServer), 245273143b9aSmrg#endif /* TRANS_SERVER */ 245373143b9aSmrg#ifdef TRANS_REOPEN 245473143b9aSmrg TRANS(SocketReopenCOTSServer), 245573143b9aSmrg#endif 245673143b9aSmrg TRANS(SocketSetOption), 245773143b9aSmrg#ifdef TRANS_SERVER 245873143b9aSmrg TRANS(SocketINETCreateListener), 245973143b9aSmrg NULL, /* ResetListener */ 246073143b9aSmrg TRANS(SocketINETAccept), 246173143b9aSmrg#endif /* TRANS_SERVER */ 246273143b9aSmrg#ifdef TRANS_CLIENT 246373143b9aSmrg TRANS(SocketINETConnect), 246473143b9aSmrg#endif /* TRANS_CLIENT */ 246573143b9aSmrg TRANS(SocketBytesReadable), 246673143b9aSmrg TRANS(SocketRead), 246773143b9aSmrg TRANS(SocketWrite), 246873143b9aSmrg TRANS(SocketReadv), 246973143b9aSmrg TRANS(SocketWritev), 247075ebec6dSmrg#if XTRANS_SEND_FDS 247175ebec6dSmrg TRANS(SocketSendFdInvalid), 247275ebec6dSmrg TRANS(SocketRecvFdInvalid), 247375ebec6dSmrg#endif 247473143b9aSmrg TRANS(SocketDisconnect), 247573143b9aSmrg TRANS(SocketINETClose), 247673143b9aSmrg TRANS(SocketINETClose), 247773143b9aSmrg }; 247873143b9aSmrg#endif /* IPv6 */ 247973143b9aSmrg#endif /* TCPCONN */ 248073143b9aSmrg 248173143b9aSmrg#ifdef UNIXCONN 248273143b9aSmrg#if !defined(LOCALCONN) 248373143b9aSmrgXtransport TRANS(SocketLocalFuncs) = { 248473143b9aSmrg /* Socket Interface */ 248573143b9aSmrg "local", 248673143b9aSmrg#ifdef HAVE_ABSTRACT_SOCKETS 248773143b9aSmrg TRANS_ABSTRACT, 248873143b9aSmrg#else 248973143b9aSmrg 0, 249073143b9aSmrg#endif 249173143b9aSmrg#ifdef TRANS_CLIENT 249273143b9aSmrg TRANS(SocketOpenCOTSClient), 249373143b9aSmrg#endif /* TRANS_CLIENT */ 249473143b9aSmrg#ifdef TRANS_SERVER 249573143b9aSmrg NULL, 249673143b9aSmrg TRANS(SocketOpenCOTSServer), 249773143b9aSmrg#endif /* TRANS_SERVER */ 249873143b9aSmrg#ifdef TRANS_REOPEN 249973143b9aSmrg TRANS(SocketReopenCOTSServer), 250073143b9aSmrg#endif 250173143b9aSmrg TRANS(SocketSetOption), 250273143b9aSmrg#ifdef TRANS_SERVER 250373143b9aSmrg TRANS(SocketUNIXCreateListener), 250473143b9aSmrg TRANS(SocketUNIXResetListener), 250573143b9aSmrg TRANS(SocketUNIXAccept), 250673143b9aSmrg#endif /* TRANS_SERVER */ 250773143b9aSmrg#ifdef TRANS_CLIENT 250873143b9aSmrg TRANS(SocketUNIXConnect), 250973143b9aSmrg#endif /* TRANS_CLIENT */ 251073143b9aSmrg TRANS(SocketBytesReadable), 251173143b9aSmrg TRANS(SocketRead), 251273143b9aSmrg TRANS(SocketWrite), 251373143b9aSmrg TRANS(SocketReadv), 251473143b9aSmrg TRANS(SocketWritev), 251575ebec6dSmrg#if XTRANS_SEND_FDS 251675ebec6dSmrg TRANS(SocketSendFd), 251775ebec6dSmrg TRANS(SocketRecvFd), 251875ebec6dSmrg#endif 251973143b9aSmrg TRANS(SocketDisconnect), 252073143b9aSmrg TRANS(SocketUNIXClose), 252173143b9aSmrg TRANS(SocketUNIXCloseForCloning), 252273143b9aSmrg }; 252373143b9aSmrg#endif /* !LOCALCONN */ 252473143b9aSmrg# ifdef TRANS_SERVER 252573143b9aSmrg# if !defined(LOCALCONN) 252675ebec6dSmrgstatic const char* unix_nolisten[] = { "local" , NULL }; 252773143b9aSmrg# endif 252873143b9aSmrg# endif 2529fe567363Smrg 253073143b9aSmrgXtransport TRANS(SocketUNIXFuncs) = { 253173143b9aSmrg /* Socket Interface */ 253273143b9aSmrg "unix", 253373143b9aSmrg#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS) 253473143b9aSmrg TRANS_ALIAS, 253573143b9aSmrg#else 253673143b9aSmrg 0, 253773143b9aSmrg#endif 253873143b9aSmrg#ifdef TRANS_CLIENT 253973143b9aSmrg TRANS(SocketOpenCOTSClient), 254073143b9aSmrg#endif /* TRANS_CLIENT */ 254173143b9aSmrg#ifdef TRANS_SERVER 254273143b9aSmrg#if !defined(LOCALCONN) 254373143b9aSmrg unix_nolisten, 254473143b9aSmrg#else 254573143b9aSmrg NULL, 254673143b9aSmrg#endif 254773143b9aSmrg TRANS(SocketOpenCOTSServer), 254873143b9aSmrg#endif /* TRANS_SERVER */ 254973143b9aSmrg#ifdef TRANS_REOPEN 255073143b9aSmrg TRANS(SocketReopenCOTSServer), 255173143b9aSmrg#endif 255273143b9aSmrg TRANS(SocketSetOption), 255373143b9aSmrg#ifdef TRANS_SERVER 255473143b9aSmrg TRANS(SocketUNIXCreateListener), 255573143b9aSmrg TRANS(SocketUNIXResetListener), 255673143b9aSmrg TRANS(SocketUNIXAccept), 255773143b9aSmrg#endif /* TRANS_SERVER */ 255873143b9aSmrg#ifdef TRANS_CLIENT 255973143b9aSmrg TRANS(SocketUNIXConnect), 256073143b9aSmrg#endif /* TRANS_CLIENT */ 256173143b9aSmrg TRANS(SocketBytesReadable), 256273143b9aSmrg TRANS(SocketRead), 256373143b9aSmrg TRANS(SocketWrite), 256473143b9aSmrg TRANS(SocketReadv), 256573143b9aSmrg TRANS(SocketWritev), 256675ebec6dSmrg#if XTRANS_SEND_FDS 256775ebec6dSmrg TRANS(SocketSendFd), 256875ebec6dSmrg TRANS(SocketRecvFd), 256975ebec6dSmrg#endif 257073143b9aSmrg TRANS(SocketDisconnect), 257173143b9aSmrg TRANS(SocketUNIXClose), 257273143b9aSmrg TRANS(SocketUNIXCloseForCloning), 257373143b9aSmrg }; 257473143b9aSmrg 257573143b9aSmrg#endif /* UNIXCONN */ 2576