|
|
/* $TOG: Xtranssock.c /main/61 1998/02/06 15:54:53 kaleb $ */
|
|
|
/*
|
|
|
|
|
|
Copyright 1993, 1994, 1998 The Open Group
|
|
|
|
|
|
All Rights Reserved.
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
|
other dealings in this Software without prior written authorization
|
|
|
from The Open Group.
|
|
|
|
|
|
*/
|
|
|
/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.45 1999/12/27 00:39:29 robin Exp $ */
|
|
|
|
|
|
/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
|
|
|
*
|
|
|
* All Rights Reserved
|
|
|
*
|
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
|
* that the above copyright notice appear in all copies and that both that
|
|
|
* copyright notice and this permission notice appear in supporting
|
|
|
* documentation, and that the name NCR not be used in advertising
|
|
|
* or publicity pertaining to distribution of the software without specific,
|
|
|
* written prior permission. NCR makes no representations about the
|
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
|
* without express or implied warranty.
|
|
|
*
|
|
|
* NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
|
* NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
*/
|
|
|
|
|
|
#include <ctype.h>
|
|
|
#include <unistd.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <stdio.h>
|
|
|
#ifndef _WIN32
|
|
|
|
|
|
#if defined(TCPCONN) || defined(UNIXCONN)
|
|
|
#include <netinet/in.h>
|
|
|
#else
|
|
|
#ifdef ESIX
|
|
|
#include <lan/in.h>
|
|
|
#endif
|
|
|
#endif
|
|
|
#if defined(TCPCONN) || defined(UNIXCONN)
|
|
|
#include <netdb.h>
|
|
|
#endif
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
#ifndef X_NO_SYS_UN
|
|
|
#ifndef Lynx
|
|
|
#include <sys/un.h>
|
|
|
#else
|
|
|
#include <un.h>
|
|
|
#endif
|
|
|
#endif
|
|
|
#include <sys/stat.h>
|
|
|
#endif
|
|
|
|
|
|
#if defined(hpux) || defined(__EMX__)
|
|
|
#define NO_TCP_H
|
|
|
#endif /* hpux */
|
|
|
#ifdef MOTOROLA
|
|
|
#ifdef SYSV
|
|
|
#define NO_TCP_H
|
|
|
#endif /* SYSV */
|
|
|
#endif /* MOTOROLA */
|
|
|
#ifndef NO_TCP_H
|
|
|
#ifdef __osf__
|
|
|
#include <sys/param.h>
|
|
|
#endif /* osf */
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
|
|
|
#include <machine/endian.h>
|
|
|
#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */
|
|
|
#include <netinet/tcp.h>
|
|
|
#endif /* !NO_TCP_H */
|
|
|
#include <sys/ioctl.h>
|
|
|
#if (defined(SVR4) || defined(__SVR4)) && !defined(SCO325) && !defined(DGUX)
|
|
|
#include <sys/filio.h>
|
|
|
#endif
|
|
|
#if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
|
|
|
#if !defined(_SEQUENT_) && !defined(ESIX) && !defined(sco)
|
|
|
#include <net/errno.h>
|
|
|
#endif /* _SEQUENT_ || ESIX || SCO */
|
|
|
#if !defined(ISC) || !defined(I_NREAD) || defined(SCO325)
|
|
|
#include <sys/stropts.h>
|
|
|
#endif
|
|
|
#endif /* i386 && SYSV || _SEQUENT_ */
|
|
|
|
|
|
#else /* !_WIN32 */
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
#if !defined(WIN32_LEAN_AND_MEAN)
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
#endif
|
|
|
#include <winsock2.h>
|
|
|
#include <sys/types.h>
|
|
|
#include <sys/stat.h>
|
|
|
#include <io.h>
|
|
|
#else
|
|
|
#include <X11/Xwinsock.h>
|
|
|
#include <X11/Xw32defs.h>
|
|
|
#endif
|
|
|
#undef close
|
|
|
#define close closesocket
|
|
|
#define ECONNREFUSED WSAECONNREFUSED
|
|
|
#define EADDRINUSE WSAEADDRINUSE
|
|
|
#define EPROTOTYPE WSAEPROTOTYPE
|
|
|
#define EINPROGRESS WSAEINPROGRESS
|
|
|
#undef EWOULDBLOCK
|
|
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
|
|
#undef EINTR
|
|
|
#define EINTR WSAEINTR
|
|
|
#include <netdb.h>
|
|
|
#endif /* _WIN32 */
|
|
|
|
|
|
#if defined(SO_DONTLINGER) && defined(SO_LINGER)
|
|
|
#undef SO_DONTLINGER
|
|
|
#endif
|
|
|
|
|
|
#if defined(__EMX__)
|
|
|
#if defined(NOT_EMX09A)
|
|
|
static int IBMsockInit = 0;
|
|
|
#define SocketInitOnce()\
|
|
|
if (!IBMsockInit) {\
|
|
|
sock_init();\
|
|
|
IBMsockInit = 1;\
|
|
|
}
|
|
|
#undef EINTR
|
|
|
#define EINTR SOCEINTR
|
|
|
#undef EINVAL
|
|
|
#define EINVAL SOCEINVAL
|
|
|
#undef errno
|
|
|
#define errno sock_errno()
|
|
|
#undef close
|
|
|
#define close soclose
|
|
|
#undef ioctl
|
|
|
#define ioctl sockioctl
|
|
|
#else
|
|
|
#define SocketInitOnce() /**/
|
|
|
#endif
|
|
|
/* this is still not there */
|
|
|
#define SOCKET int
|
|
|
#else
|
|
|
/* others don't need this */
|
|
|
#define SocketInitOnce() /**/
|
|
|
#endif
|
|
|
|
|
|
#define MIN_BACKLOG 128
|
|
|
#ifdef SOMAXCONN
|
|
|
#if SOMAXCONN > MIN_BACKLOG
|
|
|
#define BACKLOG SOMAXCONN
|
|
|
#endif
|
|
|
#endif
|
|
|
#ifndef BACKLOG
|
|
|
#define BACKLOG MIN_BACKLOG
|
|
|
#endif
|
|
|
/*
|
|
|
* This is the Socket implementation of the X Transport service layer
|
|
|
*
|
|
|
* This file contains the implementation for both the UNIX and INET domains,
|
|
|
* and can be built for either one, or both.
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
typedef struct _Sockettrans2dev {
|
|
|
char *transname;
|
|
|
int family;
|
|
|
int devcotsname;
|
|
|
int devcltsname;
|
|
|
int protocol;
|
|
|
} Sockettrans2dev;
|
|
|
|
|
|
static Sockettrans2dev Sockettrans2devtab[] = {
|
|
|
#ifdef TCPCONN
|
|
|
{(char *)"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
|
|
|
{(char *)"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
|
|
|
#endif /* TCPCONN */
|
|
|
#ifdef UNIXCONN
|
|
|
{(char *)"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
|
|
|
#if !defined(LOCALCONN)
|
|
|
{(char *)"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
|
|
|
#endif /* !LOCALCONN */
|
|
|
#endif /* UNIXCONN */
|
|
|
};
|
|
|
|
|
|
#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
|
|
|
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
|
|
|
#ifdef hpux
|
|
|
|
|
|
#if defined(X11_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/X11/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/X11"
|
|
|
#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
|
|
|
#endif /* X11_t */
|
|
|
#if defined(XIM_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/XIM/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/XIM"
|
|
|
#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
|
|
|
#endif /* XIM_t */
|
|
|
#if defined(FS_t) || defined(FONT_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/fontserv/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/fontserv"
|
|
|
#endif /* FS_t || FONT_t */
|
|
|
#if defined(ICE_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/ICE/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/ICE"
|
|
|
#endif /* ICE_t */
|
|
|
#if defined(TEST_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
|
|
|
#endif
|
|
|
#if defined(LBXPROXY_t)
|
|
|
#define UNIX_PATH "/usr/spool/sockets/X11/"
|
|
|
#define UNIX_DIR "/usr/spool/sockets/X11"
|
|
|
#endif
|
|
|
|
|
|
#else /* !hpux */
|
|
|
|
|
|
#if defined(X11_t)
|
|
|
#define UNIX_PATH "/tmp/.X11-unix/X"
|
|
|
#define UNIX_DIR "/tmp/.X11-unix"
|
|
|
#endif /* X11_t */
|
|
|
#if defined(XIM_t)
|
|
|
#define UNIX_PATH "/tmp/.XIM-unix/XIM"
|
|
|
#define UNIX_DIR "/tmp/.XIM-unix"
|
|
|
#endif /* XIM_t */
|
|
|
#if defined(FS_t) || defined(FONT_t)
|
|
|
#define UNIX_PATH "/tmp/.font-unix/fs"
|
|
|
#define UNIX_DIR "/tmp/.font-unix"
|
|
|
#endif /* FS_t || FONT_t */
|
|
|
#if defined(ICE_t)
|
|
|
#define UNIX_PATH "/tmp/.ICE-unix/"
|
|
|
#define UNIX_DIR "/tmp/.ICE-unix"
|
|
|
#endif /* ICE_t */
|
|
|
#if defined(TEST_t)
|
|
|
#define UNIX_PATH "/tmp/.Test-unix/test"
|
|
|
#define UNIX_DIR "/tmp/.Test-unix"
|
|
|
#endif
|
|
|
#if defined(LBXPROXY_t)
|
|
|
#define UNIX_PATH "/tmp/.X11-unix/X"
|
|
|
#define UNIX_DIR "/tmp/.X11-unix"
|
|
|
#endif
|
|
|
|
|
|
#endif /* hpux */
|
|
|
|
|
|
#endif /* UNIXCONN */
|
|
|
|
|
|
#define PORTBUFSIZE 32
|
|
|
|
|
|
/*
|
|
|
* These are some utility function used by the real interface function below.
|
|
|
*/
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketSelectFamily) (char *family)
|
|
|
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
PRMSG (3,(const char*)"[Xtranssock] SocketSelectFamily(%s)\n", family, 0, 0);
|
|
|
|
|
|
for (i = 0; i < (int) NUMSOCKETFAMILIES;i++)
|
|
|
{
|
|
|
if (!strcmp (family, Sockettrans2devtab[i].transname))
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
* This function gets the local address of the socket and stores it in the
|
|
|
* XtransConnInfo structure for the connection.
|
|
|
*/
|
|
|
#ifdef TCPCONN
|
|
|
static int
|
|
|
TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_in sockname;
|
|
|
#if defined(SVR4) || defined(SCO325)
|
|
|
size_t namelen = sizeof sockname;
|
|
|
#else
|
|
|
int namelen = sizeof sockname;
|
|
|
#endif
|
|
|
|
|
|
PRMSG (3,"[Xtranssock] SocketINETGetAddr(%x)\n", ciptr, 0, 0);
|
|
|
|
|
|
if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketINETGetAddr: getsockname() failed: %d\n",
|
|
|
EGET(),0, 0);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Everything looks good: fill in the XtransConnInfo structure.
|
|
|
*/
|
|
|
|
|
|
if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETGetAddr: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
ciptr->family = sockname.sin_family;
|
|
|
ciptr->addrlen = namelen;
|
|
|
memcpy (ciptr->addr, &sockname, ciptr->addrlen);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
* This function gets the remote address of the socket and stores it in the
|
|
|
* XtransConnInfo structure for the connection.
|
|
|
*/
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_in sockname;
|
|
|
#if defined(SVR4) || defined(SCO325)
|
|
|
size_t namelen = sizeof sockname;
|
|
|
#else
|
|
|
int namelen = sizeof sockname;
|
|
|
#endif
|
|
|
|
|
|
PRMSG (3,"[Xtranssock] SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0);
|
|
|
|
|
|
if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketINETGetPeerAddr: getpeername() failed: %d\n",
|
|
|
EGET(), 0, 0);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Everything looks good: fill in the XtransConnInfo structure.
|
|
|
*/
|
|
|
|
|
|
if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETGetPeerAddr: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
ciptr->peeraddrlen = namelen;
|
|
|
memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
#endif /* TCPCONN */
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketOpen) (int i, int type)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
|
|
|
PRMSG (3,"[Xtranssock] SocketOpen(%d,%d)\n", i, type, 0);
|
|
|
|
|
|
if ((ciptr = (XtransConnInfo) xcalloc (
|
|
|
1, sizeof(struct _XtransConnInfo))) == NULL)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketOpen: malloc failed\n", 0, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
|
|
|
Sockettrans2devtab[i].protocol)) < 0
|
|
|
) {
|
|
|
PRMSG (1, "[Xtranssock] SocketOpen: socket() failed for %s\n",
|
|
|
Sockettrans2devtab[i].transname, 0, 0);
|
|
|
|
|
|
xfree ((char *) ciptr);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
#ifdef TCP_NODELAY
|
|
|
if (Sockettrans2devtab[i].family == AF_INET)
|
|
|
{
|
|
|
/*
|
|
|
* turn off TCP coalescence for INET sockets
|
|
|
*/
|
|
|
|
|
|
int tmp = 1;
|
|
|
setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
|
|
|
(char *) &tmp, sizeof (int));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
|
|
|
#ifdef TRANS_REOPEN
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketReopen) (int i, int type, int fd, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
|
|
|
PRMSG (3,"[Xtranssock] SocketReopen(%d,%d,%s)\n", type, fd, port);
|
|
|
|
|
|
if ((ciptr = (XtransConnInfo) xcalloc (
|
|
|
1, sizeof(struct _XtransConnInfo))) == NULL)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketReopen: malloc failed\n", 0, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
ciptr->fd = fd;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_REOPEN */
|
|
|
|
|
|
|
|
|
/*
|
|
|
* These functions are the interface supplied in the Xtransport structure
|
|
|
*/
|
|
|
|
|
|
#ifdef TRANS_CLIENT
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
|
|
|
char *host, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2, "[Xtranssock] SocketOpenCOTSClient(%s,%s,%s)\n",
|
|
|
protocol, host, port);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketOpenCOTSClient: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketOpen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketOpenCOTSClient: Unable to open socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
|
|
|
|
|
|
#ifdef TRANS_SERVER
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
|
|
|
char *host, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketOpenCOTSServer: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketOpen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketOpenCOTSServer: Unable to open socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Using this prevents the bind() check for an existing server listening
|
|
|
* on the same port, but it is required for other reasons.
|
|
|
*/
|
|
|
#ifdef SO_REUSEADDR
|
|
|
|
|
|
/*
|
|
|
* SO_REUSEADDR only applied to AF_INET
|
|
|
*/
|
|
|
|
|
|
if (Sockettrans2devtab[i].family == AF_INET)
|
|
|
{
|
|
|
int one = 1;
|
|
|
setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
|
|
|
(char *) &one, sizeof (int));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_SERVER */
|
|
|
|
|
|
|
|
|
#ifdef TRANS_CLIENT
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
|
|
|
char *host, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketOpenCLTSClient: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketOpen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketOpenCLTSClient: Unable to open socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
|
|
|
|
|
|
#ifdef TRANS_SERVER
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
|
|
|
char *host, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketOpenCLTSServer: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketOpen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketOpenCLTSServer: Unable to open socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_SERVER */
|
|
|
|
|
|
|
|
|
#ifdef TRANS_REOPEN
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2,
|
|
|
"[Xtranssock] SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketReopenCOTSServer: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketReopen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketReopenCOTSServer: Unable to reopen socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo ciptr;
|
|
|
int i;
|
|
|
|
|
|
PRMSG (2,
|
|
|
"[Xtranssock] SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
|
|
|
|
|
|
SocketInitOnce();
|
|
|
|
|
|
if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketReopenCLTSServer: Unable to determine socket type for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((ciptr = TRANS(SocketReopen) (
|
|
|
i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketReopenCLTSServer: Unable to reopen socket for %s\n",
|
|
|
thistrans->TransName, 0, 0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/* Save the index for later use */
|
|
|
|
|
|
ciptr->index = i;
|
|
|
|
|
|
return ciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TRANS_REOPEN */
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
|
|
|
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
static int
|
|
|
set_sun_path(const char *port, const char *upath, char *path)
|
|
|
{
|
|
|
struct sockaddr_un s;
|
|
|
unsigned int maxlen = sizeof(s.sun_path) - 1;
|
|
|
|
|
|
if (!port || !*port || !path)
|
|
|
return -1;
|
|
|
|
|
|
if (*port == '/') { /* a full pathname */
|
|
|
if (strlen(port) > maxlen)
|
|
|
return -1;
|
|
|
sprintf(path, "%s", port);
|
|
|
} else {
|
|
|
if (strlen(port) + strlen(upath) > maxlen)
|
|
|
return -1;
|
|
|
sprintf(path, "%s%s", upath, port);
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
#ifdef TRANS_SERVER
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketCreateListener) (XtransConnInfo ciptr,
|
|
|
struct sockaddr *sockname, int socknamelen)
|
|
|
|
|
|
{
|
|
|
int namelen = socknamelen;
|
|
|
int fd = ciptr->fd;
|
|
|
int retry;
|
|
|
|
|
|
PRMSG (3, "[Xtranssock] SocketCreateListener(%x,%d)\n", ciptr, fd, 0);
|
|
|
|
|
|
if (Sockettrans2devtab[ciptr->index].family == AF_INET)
|
|
|
retry = 20;
|
|
|
else
|
|
|
retry = 0;
|
|
|
|
|
|
while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
|
|
|
{
|
|
|
if (errno == EADDRINUSE)
|
|
|
return TRANS_ADDR_IN_USE;
|
|
|
|
|
|
if (retry-- == 0) {
|
|
|
PRMSG (1, "[Xtranssock] SocketCreateListener: failed to bind listener\n",
|
|
|
0, 0, 0);
|
|
|
close (fd);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
#ifdef SO_REUSEADDR
|
|
|
sleep (1);
|
|
|
#else
|
|
|
sleep (10);
|
|
|
#endif /* SO_REUSEDADDR */
|
|
|
}
|
|
|
|
|
|
if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
|
|
|
#ifdef SO_DONTLINGER
|
|
|
setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
|
|
|
#else
|
|
|
#ifdef SO_LINGER
|
|
|
{
|
|
|
static int linger[2] = { 0, 0 };
|
|
|
setsockopt (fd, SOL_SOCKET, SO_LINGER,
|
|
|
(char *) linger, sizeof (linger));
|
|
|
}
|
|
|
#endif
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
if (listen (fd, BACKLOG) < 0)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketCreateListener: listen() failed\n", 0, 0, 0);
|
|
|
close (fd);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
|
|
|
/* Set a flag to indicate that this connection is a listener */
|
|
|
|
|
|
ciptr->flags = 1;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
#ifdef TCPCONN
|
|
|
static int
|
|
|
TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_in sockname;
|
|
|
int namelen = sizeof(sockname);
|
|
|
int status;
|
|
|
long tmpport;
|
|
|
struct servent *servp;
|
|
|
|
|
|
#ifdef X11_t
|
|
|
char portbuf[PORTBUFSIZE];
|
|
|
#endif
|
|
|
|
|
|
PRMSG (2, "[Xtranssock] SocketINETCreateListener(%s)\n", port, 0, 0);
|
|
|
|
|
|
#ifdef X11_t
|
|
|
/*
|
|
|
* X has a well known port, that is transport dependent. It is easier
|
|
|
* to handle it here, than try and come up with a transport independent
|
|
|
* representation that can be passed in and resolved the usual way.
|
|
|
*
|
|
|
* The port that is passed here is really a string containing the idisplay
|
|
|
* from ConnectDisplay().
|
|
|
*/
|
|
|
|
|
|
if (is_numeric (port))
|
|
|
{
|
|
|
/* fixup the server port address */
|
|
|
tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
|
|
|
sprintf (portbuf,"%lu", tmpport);
|
|
|
port = portbuf;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
if (port && *port)
|
|
|
{
|
|
|
/* Check to see if the port string is just a number (handles X11) */
|
|
|
|
|
|
if (!is_numeric (port))
|
|
|
{
|
|
|
if ((servp = getservbyname (port,"tcp")) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETCreateListener: Unable to get service for %s\n",
|
|
|
port, 0, 0);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
/* we trust getservbyname to return a valid number */
|
|
|
sockname.sin_port = htons (servp->s_port);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
tmpport = strtol (port, (char**)NULL, 10);
|
|
|
/*
|
|
|
* check that somehow the port address isn't negative or in
|
|
|
* the range of reserved port addresses. This can happen and
|
|
|
* be very bad if the server is suid-root and the user does
|
|
|
* something (dumb) like `X :60049`.
|
|
|
*/
|
|
|
if (tmpport < 1024 || tmpport > USHRT_MAX)
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
|
|
|
sockname.sin_port = htons (((unsigned short) tmpport));
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
sockname.sin_port = htons (0);
|
|
|
|
|
|
#ifdef BSD44SOCKETS
|
|
|
sockname.sin_len = sizeof (sockname);
|
|
|
#endif
|
|
|
sockname.sin_family = AF_INET;
|
|
|
sockname.sin_addr.s_addr = htonl (INADDR_ANY);
|
|
|
|
|
|
if ((status = TRANS(SocketCreateListener) (ciptr,
|
|
|
(struct sockaddr *) &sockname, namelen)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETCreateListener: ...SocketCreateListener() failed\n",
|
|
|
0, 0, 0);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
if (TRANS(SocketINETGetAddr) (ciptr) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
#endif /* SOCKCONN */
|
|
|
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_un sockname;
|
|
|
int namelen;
|
|
|
int oldUmask;
|
|
|
int status;
|
|
|
unsigned int mode;
|
|
|
|
|
|
PRMSG (2, "[Xtranssock] SocketUNIXCreateListener(%s)\n",
|
|
|
port ? port : "NULL", 0, 0);
|
|
|
|
|
|
/* Make sure the directory is created */
|
|
|
|
|
|
oldUmask = umask (0);
|
|
|
|
|
|
#ifdef UNIX_DIR
|
|
|
#ifdef HAS_STICKY_DIR_BIT
|
|
|
mode = 01777;
|
|
|
#else
|
|
|
mode = 0777;
|
|
|
#endif
|
|
|
if (trans_mkdir((char*)UNIX_DIR, mode) == -1) {
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
|
|
|
UNIX_DIR, errno, 0);
|
|
|
(void) umask (oldUmask);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
sockname.sun_family = AF_UNIX;
|
|
|
|
|
|
if (port && *port) {
|
|
|
if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXCreateListener: path too long\n", 0, 0, 0);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
} else {
|
|
|
sprintf (sockname.sun_path, "%s%d", UNIX_PATH, getpid());
|
|
|
}
|
|
|
|
|
|
namelen = sizeof( sockname ) - sizeof( sockname.sun_path ) + strlen( sockname.sun_path ) + 1;
|
|
|
#if defined(BSD44SOCKETS)
|
|
|
sockname.sun_len = namelen;
|
|
|
#endif
|
|
|
|
|
|
unlink (sockname.sun_path);
|
|
|
(void) umask (oldUmask);
|
|
|
|
|
|
if ((status = TRANS(SocketCreateListener) (ciptr,
|
|
|
(struct sockaddr *) &sockname, namelen)) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
|
|
|
0, 0, 0);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Now that the listener is esablished, create the addr info for
|
|
|
* this connection. getpeername() doesn't work for UNIX Domain Sockets
|
|
|
* on some systems (hpux at least), so we will just do it manually, instead
|
|
|
* of calling something like TRANS(SocketUNIXGetAddr).
|
|
|
*/
|
|
|
|
|
|
namelen = sizeof (sockname); /* this will always make it the same size */
|
|
|
|
|
|
if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXCreateListener: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CREATE_LISTENER_FAILED;
|
|
|
}
|
|
|
|
|
|
ciptr->family = sockname.sun_family;
|
|
|
ciptr->addrlen = namelen;
|
|
|
memcpy (ciptr->addr, &sockname, ciptr->addrlen);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
/*
|
|
|
* See if the unix domain socket has disappeared. If it has, recreate it.
|
|
|
*/
|
|
|
|
|
|
struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
|
|
|
struct stat statb;
|
|
|
int status = TRANS_RESET_NOOP;
|
|
|
unsigned int mode;
|
|
|
|
|
|
PRMSG (3, "[Xtranssock] SocketUNIXResetListener(%x,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
if (stat (unsock->sun_path, &statb) == -1 ||
|
|
|
((statb.st_mode & S_IFMT) !=
|
|
|
#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO) || defined(sco) || !defined(S_IFSOCK)
|
|
|
S_IFIFO))
|
|
|
#else
|
|
|
S_IFSOCK))
|
|
|
#endif
|
|
|
{
|
|
|
int oldUmask = umask (0);
|
|
|
|
|
|
#ifdef UNIX_DIR
|
|
|
#ifdef HAS_STICKY_DIR_BIT
|
|
|
mode = 01777;
|
|
|
#else
|
|
|
mode = 0777;
|
|
|
#endif
|
|
|
if (trans_mkdir((char*)UNIX_DIR, mode) == -1) {
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
|
|
|
UNIX_DIR, errno, 0);
|
|
|
(void) umask (oldUmask);
|
|
|
return TRANS_RESET_FAILURE;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
close (ciptr->fd);
|
|
|
unlink (unsock->sun_path);
|
|
|
|
|
|
if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
|
|
|
{
|
|
|
TRANS(FreeConnInfo) (ciptr);
|
|
|
(void) umask (oldUmask);
|
|
|
return TRANS_RESET_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
|
|
|
{
|
|
|
close (ciptr->fd);
|
|
|
TRANS(FreeConnInfo) (ciptr);
|
|
|
return TRANS_RESET_FAILURE;
|
|
|
}
|
|
|
|
|
|
if (listen (ciptr->fd, BACKLOG) < 0)
|
|
|
{
|
|
|
close (ciptr->fd);
|
|
|
TRANS(FreeConnInfo) (ciptr);
|
|
|
(void) umask (oldUmask);
|
|
|
return TRANS_RESET_FAILURE;
|
|
|
}
|
|
|
|
|
|
umask (oldUmask);
|
|
|
|
|
|
status = TRANS_RESET_NEW_FD;
|
|
|
}
|
|
|
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
#endif /* UNIXCONN */
|
|
|
|
|
|
|
|
|
#ifdef TCPCONN
|
|
|
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo newciptr;
|
|
|
struct sockaddr_in sockname;
|
|
|
#if defined(SVR4) || defined(SCO325)
|
|
|
size_t namelen = sizeof sockname;
|
|
|
#else
|
|
|
int namelen = sizeof(sockname);
|
|
|
#endif
|
|
|
|
|
|
PRMSG (2, "[Xtranssock] SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
if ((newciptr = (XtransConnInfo) xcalloc (
|
|
|
1, sizeof(struct _XtransConnInfo))) == NULL)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketINETAccept: malloc failed\n", 0, 0, 0);
|
|
|
*status = TRANS_ACCEPT_BAD_MALLOC;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((newciptr->fd = accept (ciptr->fd,
|
|
|
(struct sockaddr *) &sockname, &namelen)) < 0)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketINETAccept: accept() failed\n", 0, 0, 0);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_FAILED;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
#ifdef TCP_NODELAY
|
|
|
{
|
|
|
/*
|
|
|
* turn off TCP coalescence for INET sockets
|
|
|
*/
|
|
|
|
|
|
int tmp = 1;
|
|
|
setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
|
|
|
(char *) &tmp, sizeof (int));
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
* Get this address again because the transport may give a more
|
|
|
* specific address now that a connection is established.
|
|
|
*/
|
|
|
|
|
|
if (TRANS(SocketINETGetAddr) (newciptr) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETAccept: ...SocketINETGetAddr() failed:\n",
|
|
|
0, 0, 0);
|
|
|
close (newciptr->fd);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_MISC_ERROR;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
|
|
|
0, 0, 0);
|
|
|
close (newciptr->fd);
|
|
|
if (newciptr->addr) xfree (newciptr->addr);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_MISC_ERROR;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
*status = 0;
|
|
|
|
|
|
return newciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* TCPCONN */
|
|
|
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
static XtransConnInfo
|
|
|
TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
|
|
|
|
|
|
{
|
|
|
XtransConnInfo newciptr;
|
|
|
struct sockaddr_un sockname;
|
|
|
#if defined(SVR4) || defined(SCO325)
|
|
|
size_t namelen = sizeof sockname;
|
|
|
#else
|
|
|
int namelen = sizeof sockname;
|
|
|
#endif
|
|
|
|
|
|
PRMSG (2, "[Xtranssock] SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
if ((newciptr = (XtransConnInfo) xcalloc (
|
|
|
1, sizeof(struct _XtransConnInfo))) == NULL)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
|
|
|
*status = TRANS_ACCEPT_BAD_MALLOC;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
if ((newciptr->fd = accept (ciptr->fd,
|
|
|
(struct sockaddr *) &sockname, &namelen)) < 0)
|
|
|
{
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXAccept: accept() failed\n", 0, 0, 0);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_FAILED;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Get the socket name and the peer name from the listener socket,
|
|
|
* since this is unix domain.
|
|
|
*/
|
|
|
|
|
|
if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXAccept: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
close (newciptr->fd);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_BAD_MALLOC;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
|
|
|
newciptr->addrlen = ciptr->addrlen;
|
|
|
memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
|
|
|
|
|
|
if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXAccept: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
close (newciptr->fd);
|
|
|
if (newciptr->addr) xfree (newciptr->addr);
|
|
|
xfree (newciptr);
|
|
|
*status = TRANS_ACCEPT_BAD_MALLOC;
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
newciptr->peeraddrlen = ciptr->addrlen;
|
|
|
memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
|
|
|
|
|
|
newciptr->family = AF_UNIX;
|
|
|
|
|
|
*status = 0;
|
|
|
|
|
|
return newciptr;
|
|
|
}
|
|
|
|
|
|
#endif /* UNIXCONN */
|
|
|
|
|
|
#endif /* TRANS_SERVER */
|
|
|
|
|
|
|
|
|
#ifdef TRANS_CLIENT
|
|
|
|
|
|
#ifdef TCPCONN
|
|
|
static int
|
|
|
TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_in sockname;
|
|
|
#if defined(SVR4) || defined(SCO325)
|
|
|
size_t namelen = sizeof sockname;
|
|
|
#else
|
|
|
int namelen = sizeof sockname;
|
|
|
#endif
|
|
|
struct hostent *hostp;
|
|
|
struct servent *servp;
|
|
|
|
|
|
#ifdef X11_t
|
|
|
char portbuf[PORTBUFSIZE];
|
|
|
#endif
|
|
|
|
|
|
long tmpport;
|
|
|
unsigned long tmpaddr;
|
|
|
char hostnamebuf[256]; /* tmp space */
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
|
|
|
|
|
|
if (!host)
|
|
|
{
|
|
|
hostnamebuf[0] = '\0';
|
|
|
(void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
|
|
|
host = hostnamebuf;
|
|
|
}
|
|
|
|
|
|
#ifdef X11_t
|
|
|
/*
|
|
|
* X has a well known port, that is transport dependent. It is easier
|
|
|
* to handle it here, than try and come up with a transport independent
|
|
|
* representation that can be passed in and resolved the usual way.
|
|
|
*
|
|
|
* The port that is passed here is really a string containing the idisplay
|
|
|
* from ConnectDisplay().
|
|
|
*/
|
|
|
|
|
|
if (is_numeric (port))
|
|
|
{
|
|
|
tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
|
|
|
sprintf (portbuf, "%lu", tmpport);
|
|
|
port = portbuf;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
* Build the socket name.
|
|
|
*/
|
|
|
|
|
|
#ifdef BSD44SOCKETS
|
|
|
sockname.sin_len = sizeof (struct sockaddr_in);
|
|
|
#endif
|
|
|
sockname.sin_family = AF_INET;
|
|
|
|
|
|
/*
|
|
|
* fill in sin_addr
|
|
|
*/
|
|
|
|
|
|
/* check for ww.xx.yy.zz host string */
|
|
|
|
|
|
if (isascii (host[0]) && isdigit (host[0])) {
|
|
|
tmpaddr = inet_addr (host); /* returns network byte order */
|
|
|
} else {
|
|
|
tmpaddr = -1;
|
|
|
}
|
|
|
|
|
|
PRMSG (4,"[Xtranssock] SocketINETConnect: inet_addr(%s) = %x\n",
|
|
|
host, tmpaddr, 0);
|
|
|
|
|
|
if (tmpaddr == -1)
|
|
|
{
|
|
|
#ifdef _WIN32
|
|
|
if ((hostp = gethostbyname(host)) == NULL)
|
|
|
#else
|
|
|
if ((hostp = gethostbyname(host,hparams)) == NULL)
|
|
|
#endif
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketINETConnect: Can't get address for %s\n",
|
|
|
host, 0, 0);
|
|
|
ESET(EINVAL);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
if (hostp->h_addrtype != AF_INET) /* is IP host? */
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketINETConnect: not INET host%s\n",
|
|
|
host, 0, 0);
|
|
|
ESET(EPROTOTYPE);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
#if defined(CRAY) && defined(OLDTCP)
|
|
|
/* Only Cray UNICOS3 and UNICOS4 will define this */
|
|
|
{
|
|
|
long t;
|
|
|
memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
|
|
|
sockname.sin_addr = t;
|
|
|
}
|
|
|
#else
|
|
|
memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
|
|
|
sizeof (sockname.sin_addr));
|
|
|
#endif /* CRAY and OLDTCP */
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
#if defined(CRAY) && defined(OLDTCP)
|
|
|
/* Only Cray UNICOS3 and UNICOS4 will define this */
|
|
|
sockname.sin_addr = tmpaddr;
|
|
|
#else
|
|
|
sockname.sin_addr.s_addr = tmpaddr;
|
|
|
#endif /* CRAY and OLDTCP */
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* fill in sin_port
|
|
|
*/
|
|
|
|
|
|
/* Check for number in the port string */
|
|
|
|
|
|
if (!is_numeric (port))
|
|
|
{
|
|
|
if ((servp = getservbyname (port,"tcp")) == NULL)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketINETConnect: can't get service for %s\n",
|
|
|
port, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
sockname.sin_port = htons (servp->s_port);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
tmpport = strtol (port, (char**)NULL, 10);
|
|
|
if (tmpport < 1024 || tmpport > USHRT_MAX)
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
sockname.sin_port = htons (((unsigned short) tmpport));
|
|
|
}
|
|
|
|
|
|
PRMSG (4,"[Xtranssock] SocketINETConnect: sockname.sin_port = %d\n",
|
|
|
ntohs(sockname.sin_port), 0, 0);
|
|
|
|
|
|
/*
|
|
|
* Do the connect()
|
|
|
*/
|
|
|
|
|
|
if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
|
|
|
{
|
|
|
#ifdef _WIN32
|
|
|
int olderrno = WSAGetLastError();
|
|
|
#else
|
|
|
int olderrno = errno;
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
* If the error was ECONNREFUSED, the server may be overloaded
|
|
|
* and we should try again.
|
|
|
*
|
|
|
* If the error was EWOULDBLOCK or EINPROGRESS then the socket
|
|
|
* was non-blocking and we should poll using select
|
|
|
*
|
|
|
* If the error was EINTR, the connect was interrupted and we
|
|
|
* should try again.
|
|
|
*/
|
|
|
|
|
|
if (olderrno == ECONNREFUSED || olderrno == EINTR)
|
|
|
return TRANS_TRY_CONNECT_AGAIN;
|
|
|
else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
|
|
|
return TRANS_IN_PROGRESS;
|
|
|
else
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketINETConnect: Can't connect: errno = %d\n",
|
|
|
olderrno,0, 0);
|
|
|
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Sync up the address fields of ciptr.
|
|
|
*/
|
|
|
|
|
|
if (TRANS(SocketINETGetAddr) (ciptr) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETConnect: ...SocketINETGetAddr() failed:\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
#endif /* TCPCONN */
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
|
|
|
/*
|
|
|
* Make sure 'host' is really local.
|
|
|
*/
|
|
|
|
|
|
static int
|
|
|
UnixHostReallyLocal (char *host)
|
|
|
|
|
|
{
|
|
|
char hostnamebuf[256];
|
|
|
char* xauthlocalname = getenv("XAUTHLOCALHOSTNAME");
|
|
|
|
|
|
TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
|
|
|
|
|
|
if (strcmp (hostnamebuf, host) == 0)
|
|
|
{
|
|
|
return (1);
|
|
|
}
|
|
|
else if(xauthlocalname && strcmp (xauthlocalname, host) == 0)
|
|
|
{
|
|
|
return (1);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
/*
|
|
|
* A host may have more than one network address. If any of the
|
|
|
* network addresses of 'host' (specified to the connect call)
|
|
|
* match any of the network addresses of 'hostname' (determined
|
|
|
* by TRANS(GetHostname)), then the two hostnames are equivalent,
|
|
|
* and we know that 'host' is really a local host.
|
|
|
*/
|
|
|
char specified_local_addr_list[10][4];
|
|
|
int scount, equiv, i, j;
|
|
|
struct hostent *hostp;
|
|
|
|
|
|
if ((hostp = gethostbyname (host)) == NULL)
|
|
|
return (0);
|
|
|
|
|
|
scount = 0;
|
|
|
while (hostp->h_addr_list[scount] && scount <= 8)
|
|
|
{
|
|
|
/*
|
|
|
* The 2nd call to gethostname() overrides the data
|
|
|
* from the 1st call, so we must save the address list.
|
|
|
*/
|
|
|
|
|
|
specified_local_addr_list[scount][0] =
|
|
|
hostp->h_addr_list[scount][0];
|
|
|
specified_local_addr_list[scount][1] =
|
|
|
hostp->h_addr_list[scount][1];
|
|
|
specified_local_addr_list[scount][2] =
|
|
|
hostp->h_addr_list[scount][2];
|
|
|
specified_local_addr_list[scount][3] =
|
|
|
hostp->h_addr_list[scount][3];
|
|
|
scount++;
|
|
|
}
|
|
|
if ((hostp = gethostbyname (hostnamebuf)) == NULL)
|
|
|
return (0);
|
|
|
|
|
|
equiv = 0;
|
|
|
i = 0;
|
|
|
|
|
|
while (i < scount && !equiv)
|
|
|
{
|
|
|
j = 0;
|
|
|
|
|
|
while (hostp->h_addr_list[j])
|
|
|
{
|
|
|
if ((specified_local_addr_list[i][0] ==
|
|
|
hostp->h_addr_list[j][0]) &&
|
|
|
(specified_local_addr_list[i][1] ==
|
|
|
hostp->h_addr_list[j][1]) &&
|
|
|
(specified_local_addr_list[i][2] ==
|
|
|
hostp->h_addr_list[j][2]) &&
|
|
|
(specified_local_addr_list[i][3] ==
|
|
|
hostp->h_addr_list[j][3]))
|
|
|
{
|
|
|
/* They're equal, so we're done */
|
|
|
|
|
|
equiv = 1;
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
j++;
|
|
|
}
|
|
|
|
|
|
i++;
|
|
|
}
|
|
|
|
|
|
return (equiv);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
|
|
|
|
|
|
{
|
|
|
struct sockaddr_un sockname;
|
|
|
int namelen;
|
|
|
|
|
|
#if defined(hpux) && defined(X11_t)
|
|
|
struct sockaddr_un old_sockname;
|
|
|
int old_namelen;
|
|
|
#endif
|
|
|
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
|
|
|
|
|
|
/*
|
|
|
* Make sure 'host' is really local. If not, we return failure.
|
|
|
* The reason we make this check is because a process may advertise
|
|
|
* a "local" network ID for which it can accept connections, but if
|
|
|
* a process on a remote machine tries to connect to this network ID,
|
|
|
* we know for sure it will fail.
|
|
|
*/
|
|
|
|
|
|
if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXConnect: Cannot connect to non-local host %s\n",
|
|
|
host, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Check the port.
|
|
|
*/
|
|
|
|
|
|
if (!port || !*port)
|
|
|
{
|
|
|
PRMSG (1,"[Xtranssock] SocketUNIXConnect: Missing port specification\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Build the socket name.
|
|
|
*/
|
|
|
|
|
|
sockname.sun_family = AF_UNIX;
|
|
|
|
|
|
if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXConnect: path too long\n", 0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
namelen = sizeof( sockname ) - sizeof( sockname.sun_path ) + strlen( sockname.sun_path ) + 1;
|
|
|
#if defined(BSD44SOCKETS)
|
|
|
sockname.sun_len = namelen;
|
|
|
#endif
|
|
|
|
|
|
#if defined(hpux) && defined(X11_t)
|
|
|
/*
|
|
|
* This is gross, but it was in Xlib
|
|
|
*/
|
|
|
old_sockname.sun_family = AF_UNIX;
|
|
|
if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
|
|
|
PRMSG (1, "[Xtranssock] SocketUNIXConnect: path too long\n", 0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
old_namelen = strlen (old_sockname.sun_path) +
|
|
|
sizeof (old_sockname.sun_family);
|
|
|
#endif
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Do the connect()
|
|
|
*/
|
|
|
|
|
|
if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
|
|
|
{
|
|
|
int olderrno = errno;
|
|
|
int connected = 0;
|
|
|
|
|
|
#if defined(hpux) && defined(X11_t)
|
|
|
if (olderrno == ENOENT)
|
|
|
{
|
|
|
if (connect (ciptr->fd,
|
|
|
(struct sockaddr *) &old_sockname, old_namelen) >= 0)
|
|
|
{
|
|
|
connected = 1;
|
|
|
}
|
|
|
else
|
|
|
olderrno = errno;
|
|
|
}
|
|
|
#endif
|
|
|
if (!connected)
|
|
|
{
|
|
|
errno = olderrno;
|
|
|
|
|
|
/*
|
|
|
* If the error was ENOENT, the server may be starting up
|
|
|
* and we should try again.
|
|
|
*
|
|
|
* If the error was EWOULDBLOCK or EINPROGRESS then the socket
|
|
|
* was non-blocking and we should poll using select
|
|
|
*
|
|
|
* If the error was EINTR, the connect was interrupted and we
|
|
|
* should try again.
|
|
|
*/
|
|
|
|
|
|
if (olderrno == ENOENT || olderrno == EINTR)
|
|
|
return TRANS_TRY_CONNECT_AGAIN;
|
|
|
else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
|
|
|
return TRANS_IN_PROGRESS;
|
|
|
else
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketUNIXConnect: Can't connect: errno = %d\n",
|
|
|
EGET(),0, 0);
|
|
|
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Get the socket name and the peer name from the connect socket,
|
|
|
* since this is unix domain.
|
|
|
*/
|
|
|
|
|
|
if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
|
|
|
(ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
|
|
|
{
|
|
|
PRMSG (1,
|
|
|
"[Xtranssock] SocketUNIXCreateListener: Can't allocate space for the addr\n",
|
|
|
0, 0, 0);
|
|
|
return TRANS_CONNECT_FAILED;
|
|
|
}
|
|
|
|
|
|
ciptr->family = AF_UNIX;
|
|
|
ciptr->addrlen = namelen;
|
|
|
ciptr->peeraddrlen = namelen;
|
|
|
memcpy (ciptr->addr, &sockname, ciptr->addrlen);
|
|
|
memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
#endif /* UNIXCONN */
|
|
|
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketBytesReadable(%x,%d,%x)\n",
|
|
|
ciptr, ciptr->fd, pend);
|
|
|
#if defined(QNX4)
|
|
|
*pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
|
|
|
#endif
|
|
|
#ifdef _WIN32
|
|
|
return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
|
|
|
#else
|
|
|
#if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_)
|
|
|
return ioctl (ciptr->fd, I_NREAD, (char *) pend);
|
|
|
#else
|
|
|
#if defined(__EMX__)
|
|
|
return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
|
|
|
#else
|
|
|
return ioctl (ciptr->fd, FIONREAD, (char *) pend);
|
|
|
#endif /* __EMX__ */
|
|
|
#endif /* i386 && SYSV && !SCO || _SEQUENT_ */
|
|
|
#endif /* _WIN32 */
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size);
|
|
|
|
|
|
#if defined(_WIN32) || defined(__EMX__)
|
|
|
return recv ((SOCKET)ciptr->fd, buf, size, 0);
|
|
|
#else
|
|
|
return read (ciptr->fd, buf, size);
|
|
|
#endif /* _WIN32 */
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
|
|
|
|
|
|
#if defined(_WIN32) || defined(__EMX__)
|
|
|
return send ((SOCKET)ciptr->fd, buf, size, 0);
|
|
|
#else
|
|
|
return write (ciptr->fd, buf, size);
|
|
|
#endif /* _WIN32 */
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
|
|
|
|
|
|
return READV (ciptr, buf, size);
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
|
|
|
|
|
|
return WRITEV (ciptr, buf, size);
|
|
|
}
|
|
|
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketDisconnect) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
|
|
|
}
|
|
|
|
|
|
|
|
|
#ifdef TCPCONN
|
|
|
static int
|
|
|
TRANS(SocketINETClose) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
PRMSG (2,"[Xtranssock] SocketINETClose(%x,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
return close (ciptr->fd);
|
|
|
}
|
|
|
|
|
|
#endif /* TCPCONN */
|
|
|
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
static int
|
|
|
TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
/*
|
|
|
* If this is the server side, then once the socket is closed,
|
|
|
* it must be unlinked to completely close it
|
|
|
*/
|
|
|
|
|
|
struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
|
|
|
char path[200]; /* > sizeof sun_path +1 */
|
|
|
int ret;
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
|
|
|
|
|
|
ret = close(ciptr->fd);
|
|
|
|
|
|
if (ciptr->flags
|
|
|
&& sockname
|
|
|
&& sockname->sun_family == AF_UNIX
|
|
|
&& sockname->sun_path[0])
|
|
|
{
|
|
|
strncpy (path, sockname->sun_path,
|
|
|
ciptr->addrlen - sizeof (sockname->sun_family));
|
|
|
unlink (path);
|
|
|
}
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
|
|
|
|
|
|
{
|
|
|
/*
|
|
|
* Don't unlink path.
|
|
|
*/
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
PRMSG (2,"[Xtranssock] SocketUNIXCloseForCloning(%x,%d)\n",
|
|
|
ciptr, ciptr->fd, 0);
|
|
|
|
|
|
ret = close(ciptr->fd);
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
#endif /* UNIXCONN */
|
|
|
|
|
|
|
|
|
#ifdef TCPCONN
|
|
|
Xtransport TRANS(SocketTCPFuncs) = {
|
|
|
/* Socket Interface */
|
|
|
"tcp",
|
|
|
0,
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCOTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCOTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCLTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCLTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_REOPEN
|
|
|
TRANS(SocketReopenCOTSServer),
|
|
|
TRANS(SocketReopenCLTSServer),
|
|
|
#endif
|
|
|
TRANS(SocketSetOption),
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketINETCreateListener),
|
|
|
NULL, /* ResetListener */
|
|
|
TRANS(SocketINETAccept),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketINETConnect),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
TRANS(SocketBytesReadable),
|
|
|
TRANS(SocketRead),
|
|
|
TRANS(SocketWrite),
|
|
|
TRANS(SocketReadv),
|
|
|
TRANS(SocketWritev),
|
|
|
TRANS(SocketDisconnect),
|
|
|
TRANS(SocketINETClose),
|
|
|
TRANS(SocketINETClose),
|
|
|
};
|
|
|
|
|
|
Xtransport TRANS(SocketINETFuncs) = {
|
|
|
/* Socket Interface */
|
|
|
"inet",
|
|
|
TRANS_ALIAS,
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCOTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCOTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCLTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCLTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_REOPEN
|
|
|
TRANS(SocketReopenCOTSServer),
|
|
|
TRANS(SocketReopenCLTSServer),
|
|
|
#endif
|
|
|
TRANS(SocketSetOption),
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketINETCreateListener),
|
|
|
NULL, /* ResetListener */
|
|
|
TRANS(SocketINETAccept),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketINETConnect),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
TRANS(SocketBytesReadable),
|
|
|
TRANS(SocketRead),
|
|
|
TRANS(SocketWrite),
|
|
|
TRANS(SocketReadv),
|
|
|
TRANS(SocketWritev),
|
|
|
TRANS(SocketDisconnect),
|
|
|
TRANS(SocketINETClose),
|
|
|
TRANS(SocketINETClose),
|
|
|
};
|
|
|
|
|
|
#endif /* TCPCONN */
|
|
|
|
|
|
#ifdef UNIXCONN
|
|
|
#if !defined(LOCALCONN)
|
|
|
Xtransport TRANS(SocketLocalFuncs) = {
|
|
|
/* Socket Interface */
|
|
|
(char*)"local",
|
|
|
0,
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCOTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCOTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCLTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCLTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_REOPEN
|
|
|
TRANS(SocketReopenCOTSServer),
|
|
|
TRANS(SocketReopenCLTSServer),
|
|
|
#endif
|
|
|
TRANS(SocketSetOption),
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketUNIXCreateListener),
|
|
|
TRANS(SocketUNIXResetListener),
|
|
|
TRANS(SocketUNIXAccept),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketUNIXConnect),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
TRANS(SocketBytesReadable),
|
|
|
TRANS(SocketRead),
|
|
|
TRANS(SocketWrite),
|
|
|
TRANS(SocketReadv),
|
|
|
TRANS(SocketWritev),
|
|
|
TRANS(SocketDisconnect),
|
|
|
TRANS(SocketUNIXClose),
|
|
|
TRANS(SocketUNIXCloseForCloning),
|
|
|
};
|
|
|
#endif /* !LOCALCONN */
|
|
|
|
|
|
Xtransport TRANS(SocketUNIXFuncs) = {
|
|
|
/* Socket Interface */
|
|
|
(char*)"unix",
|
|
|
#if !defined(LOCALCONN)
|
|
|
TRANS_ALIAS,
|
|
|
#else
|
|
|
0,
|
|
|
#endif
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCOTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCOTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketOpenCLTSClient),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketOpenCLTSServer),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_REOPEN
|
|
|
TRANS(SocketReopenCOTSServer),
|
|
|
TRANS(SocketReopenCLTSServer),
|
|
|
#endif
|
|
|
TRANS(SocketSetOption),
|
|
|
#ifdef TRANS_SERVER
|
|
|
TRANS(SocketUNIXCreateListener),
|
|
|
TRANS(SocketUNIXResetListener),
|
|
|
TRANS(SocketUNIXAccept),
|
|
|
#endif /* TRANS_SERVER */
|
|
|
#ifdef TRANS_CLIENT
|
|
|
TRANS(SocketUNIXConnect),
|
|
|
#endif /* TRANS_CLIENT */
|
|
|
TRANS(SocketBytesReadable),
|
|
|
TRANS(SocketRead),
|
|
|
TRANS(SocketWrite),
|
|
|
TRANS(SocketReadv),
|
|
|
TRANS(SocketWritev),
|
|
|
TRANS(SocketDisconnect),
|
|
|
TRANS(SocketUNIXClose),
|
|
|
TRANS(SocketUNIXCloseForCloning),
|
|
|
};
|
|
|
|
|
|
#endif /* UNIXCONN */
|