#include <ctype.h>
#ifdef XTHREADS
#include <X11/Xthreads.h>
#endif
#ifndef WIN32
#if defined(TCPCONN) || defined(UNIXCONN)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#if defined(TCPCONN) || defined(UNIXCONN)
#define X_INCLUDE_NETDB_H
#define XOS_USE_NO_LOCKING
#include <X11/Xos_r.h>
#endif
#ifdef UNIXCONN
#ifndef X_NO_SYS_UN
#include <sys/un.h>
#endif
#include <sys/stat.h>
#endif
#ifndef NO_TCP_H
#if defined(linux) || defined(__GLIBC__)
#include <sys/param.h>
#endif
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/param.h>
#include <machine/endian.h>
#endif
#include <netinet/tcp.h>
#endif
#include <sys/ioctl.h>
#if defined(SVR4) || defined(__SVR4)
#include <sys/filio.h>
#endif
#if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
#include <net/errno.h>
#endif
#if defined(__i386__) && defined(SYSV)
#include <sys/stropts.h>
#endif
#include <unistd.h>
#else
#include <X11/Xwinsock.h>
#include <X11/Xwindows.h>
#include <X11/Xw32defs.h>
#undef close
#define close closesocket
#define ECONNREFUSED WSAECONNREFUSED
#define EADDRINUSE WSAEADDRINUSE
#define EPROTOTYPE WSAEPROTOTYPE
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#define EINPROGRESS WSAEINPROGRESS
#undef EINTR
#define EINTR WSAEINTR
#define X_INCLUDE_NETDB_H
#define XOS_USE_MTSAFE_NETDBAPI
#include <X11/Xos_r.h>
#endif
#if defined(SO_DONTLINGER) && defined(SO_LINGER)
#undef SO_DONTLINGER
#endif
#define SocketInitOnce()
#ifdef linux
#define HAVE_ABSTRACT_SOCKETS
#endif
#define MIN_BACKLOG 128
#ifdef SOMAXCONN
#if SOMAXCONN > MIN_BACKLOG
#define BACKLOG SOMAXCONN
#endif
#endif
#ifndef BACKLOG
#define BACKLOG MIN_BACKLOG
#endif
typedef struct _Sockettrans2dev {
char *transname;
int family;
int devcotsname;
int devcltsname;
int protocol;
} Sockettrans2dev;
static Sockettrans2dev Sockettrans2devtab[] = {
#ifdef TCPCONN
{"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
#if !defined(IPv6) || !defined(AF_INET6)
{"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
#else
{"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
{"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
{"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
#endif
#endif
#ifdef UNIXCONN
{"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
#if !defined(LOCALCONN)
{"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
#endif
#endif
};
#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
#ifdef TCPCONN
static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
#endif
#ifdef UNIXCONN
#if defined(X11_t)
#define UNIX_PATH "/tmp/.X11-unix/X"
#define UNIX_DIR "/tmp/.X11-unix"
#endif
#if defined(XIM_t)
#define UNIX_PATH "/tmp/.XIM-unix/XIM"
#define UNIX_DIR "/tmp/.XIM-unix"
#endif
#if defined(FS_t) || defined(FONT_t)
#define UNIX_PATH "/tmp/.font-unix/fs"
#define UNIX_DIR "/tmp/.font-unix"
#endif
#if defined(ICE_t)
#define UNIX_PATH "/tmp/.ICE-unix/"
#define UNIX_DIR "/tmp/.ICE-unix"
#endif
#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
#define PORTBUFSIZE 32
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 255
#endif
#if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6))
# define SOCKLEN_T socklen_t
#elif defined(SVR4) || defined(__SVR4) || defined(__SCO__)
# define SOCKLEN_T size_t
#else
# define SOCKLEN_T int
#endif
static int
TRANS(SocketSelectFamily) (int first, char *family)
{
int i;
PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
{
if (!strcmp (family, Sockettrans2devtab[i].transname))
return i;
}
return (first == -1 ? -2 : -1);
}
static int
TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
{
#if defined(IPv6) && defined(AF_INET6)
struct sockaddr_storage socknamev6;
#else
struct sockaddr_in socknamev4;
#endif
void *socknamePtr;
SOCKLEN_T namelen;
PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
#if defined(IPv6) && defined(AF_INET6)
namelen = sizeof(socknamev6);
socknamePtr = &socknamev6;
#else
namelen = sizeof(socknamev4);
socknamePtr = &socknamev4;
#endif
bzero(socknamePtr, namelen);
if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
(void *)&namelen) < 0)
{
#ifdef WIN32
errno = WSAGetLastError();
#endif
PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
EGET(),0, 0);
return -1;
}
if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
{
PRMSG (1,
"SocketINETGetAddr: Can't allocate space for the addr\n",
0, 0, 0);
return -1;
}
#if defined(IPv6) && defined(AF_INET6)
ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
#else
ciptr->family = socknamev4.sin_family;
#endif
ciptr->addrlen = namelen;
memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
return 0;
}
static int
TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
{
#if defined(IPv6) && defined(AF_INET6)
struct sockaddr_storage socknamev6;
#endif
struct sockaddr_in socknamev4;
void *socknamePtr;
SOCKLEN_T namelen;
#if defined(IPv6) && defined(AF_INET6)
if (ciptr->family == AF_INET6)
{
namelen = sizeof(socknamev6);
socknamePtr = &socknamev6;
}
else
#endif
{
namelen = sizeof(socknamev4);
socknamePtr = &socknamev4;
}
bzero(socknamePtr, namelen);
PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
(void *)&namelen) < 0)
{
#ifdef WIN32
errno = WSAGetLastError();
#endif
PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
EGET(), 0, 0);
return -1;
}
if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
{
PRMSG (1,
"SocketINETGetPeerAddr: Can't allocate space for the addr\n",
0, 0, 0);
return -1;
}
ciptr->peeraddrlen = namelen;
memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
return 0;
}
static XtransConnInfo
TRANS(SocketOpen) (int i, int type)
{
XtransConnInfo ciptr;
PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
if ((ciptr = (XtransConnInfo) xcalloc (
1, sizeof(struct _XtransConnInfo))) == NULL)
{
PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
return NULL;
}
if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
Sockettrans2devtab[i].protocol)) < 0
#ifndef WIN32
#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
|| ciptr->fd >= sysconf(_SC_OPEN_MAX)
#endif
#endif
) {
#ifdef WIN32
errno = WSAGetLastError();
#endif
PRMSG (2, "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
#if defined(IPv6) && defined(AF_INET6)
|| Sockettrans2devtab[i].family == AF_INET6
#endif
)
{
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;
int portlen;
struct sockaddr *addr;
PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
if (port == NULL) {
PRMSG (1, "SocketReopen: port was null!\n", 0, 0, 0);
return NULL;
}
portlen = strlen(port) + 1; #ifdef SOCK_MAXADDRLEN
if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0);
return NULL;
}
if (portlen < 14) portlen = 14;
#else
if (portlen < 0 || portlen > 14) {
PRMSG (1, "SocketReopen: invalid portlen %d\n", portlen, 0, 0);
return NULL;
}
#endif
if ((ciptr = (XtransConnInfo) xcalloc (
1, sizeof(struct _XtransConnInfo))) == NULL)
{
PRMSG (1, "SocketReopen: malloc(ciptr) failed\n", 0, 0, 0);
return NULL;
}
ciptr->fd = fd;
if ((addr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) {
PRMSG (1, "SocketReopen: malloc(addr) failed\n", 0, 0, 0);
return NULL;
}
ciptr->addr = (char *) addr;
ciptr->addrlen = portlen + 2;
if ((ciptr->peeraddr = (char *) xcalloc (1, portlen + 2)) == NULL) {
PRMSG (1, "SocketReopen: malloc(portaddr) failed\n", 0, 0, 0);
return NULL;
}
ciptr->peeraddrlen = portlen + 2;
ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
#ifdef BSD44SOCKETS
addr->sa_len = portlen + 1;
#endif
addr->sa_family = AF_UNIX;
#ifdef HAS_STRLCPY
strlcpy(addr->sa_data, port, portlen);
#else
strncpy(addr->sa_data, port, portlen);
#endif
ciptr->family = AF_UNIX;
memcpy(ciptr->peeraddr, ciptr->addr, sizeof(struct sockaddr));
ciptr->port = rindex(addr->sa_data, ':');
if (ciptr->port == NULL) {
if (is_numeric(addr->sa_data)) {
ciptr->port = addr->sa_data;
}
} else if (ciptr->port[0] == ':') {
ciptr->port++;
}
return ciptr;
}
#endif
#ifdef TRANS_CLIENT
static XtransConnInfo
TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
char *host, char *port, int previndex)
{
XtransConnInfo ciptr;
int i = previndex;
PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
protocol, host, port);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
if ((ciptr = TRANS(SocketOpen) (
i, Sockettrans2devtab[i].devcotsname)) != NULL) {
ciptr->index = i;
break;
}
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
transname, 0, 0);
else
PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
transname, 0, 0);
return NULL;
}
return ciptr;
}
static XtransConnInfo
TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
char *host, char *port)
{
return TRANS(SocketOpenCOTSClientBase)(
thistrans->TransName, protocol, host, port, -1);
}
#endif
#ifdef TRANS_SERVER
static XtransConnInfo
TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
char *host, char *port)
{
XtransConnInfo ciptr;
int i = -1;
PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
if ((ciptr = TRANS(SocketOpen) (
i, Sockettrans2devtab[i].devcotsname)) != NULL)
break;
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
thistrans->TransName, 0, 0);
else
PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
thistrans->TransName, 0, 0);
return NULL;
}
#ifdef SO_REUSEADDR
if (Sockettrans2devtab[i].family == AF_INET
#if defined(IPv6) && defined(AF_INET6)
|| Sockettrans2devtab[i].family == AF_INET6
#endif
)
{
int one = 1;
setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &one, sizeof (int));
}
#endif
#ifdef IPV6_V6ONLY
if (Sockettrans2devtab[i].family == AF_INET6)
{
int one = 1;
setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
}
#endif
ciptr->index = i;
return ciptr;
}
#endif
#ifdef TRANS_CLIENT
static XtransConnInfo
TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
char *host, char *port)
{
XtransConnInfo ciptr;
int i = -1;
PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
if ((ciptr = TRANS(SocketOpen) (
i, Sockettrans2devtab[i].devcotsname)) != NULL)
break;
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
thistrans->TransName, 0, 0);
else
PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
thistrans->TransName, 0, 0);
return NULL;
}
ciptr->index = i;
return ciptr;
}
#endif
#ifdef TRANS_SERVER
static XtransConnInfo
TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
char *host, char *port)
{
XtransConnInfo ciptr;
int i = -1;
PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
if ((ciptr = TRANS(SocketOpen) (
i, Sockettrans2devtab[i].devcotsname)) != NULL)
break;
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
thistrans->TransName, 0, 0);
else
PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
thistrans->TransName, 0, 0);
return NULL;
}
#ifdef IPV6_V6ONLY
if (Sockettrans2devtab[i].family == AF_INET6)
{
int one = 1;
setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
}
#endif
ciptr->index = i;
return ciptr;
}
#endif
#ifdef TRANS_REOPEN
static XtransConnInfo
TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
{
XtransConnInfo ciptr;
int i = -1;
PRMSG (2,
"SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
if ((ciptr = TRANS(SocketReopen) (
i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
break;
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
thistrans->TransName, 0, 0);
else
PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
thistrans->TransName, 0, 0);
return NULL;
}
ciptr->index = i;
return ciptr;
}
static XtransConnInfo
TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
{
XtransConnInfo ciptr;
int i = -1;
PRMSG (2,
"SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
SocketInitOnce();
while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
if ((ciptr = TRANS(SocketReopen) (
i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
break;
}
if (i < 0) {
if (i == -1)
PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
thistrans->TransName, 0, 0);
else
PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
thistrans->TransName, 0, 0);
return NULL;
}
ciptr->index = i;
return ciptr;
}
#endif
static int
TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
{
PRMSG (2,"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, int abstract)
{
struct sockaddr_un s;
int maxlen = sizeof(s.sun_path) - 1;
const char *at = "";
if (!port || !*port || !path)
return -1;
#ifdef HAVE_ABSTRACT_SOCKETS
if (port[0] == '@')
upath = "";
else if (abstract)
at = "@";
#endif
if (*port == '/')
upath = "";
if (strlen(port) + strlen(upath) > maxlen)
return -1;
sprintf(path, "%s%s%s", at, upath, port);
return 0;
}
#endif
#ifdef TRANS_SERVER
static int
TRANS(SocketCreateListener) (XtransConnInfo ciptr,
struct sockaddr *sockname,
int socknamelen, unsigned int flags)
{
SOCKLEN_T namelen = socknamelen;
int fd = ciptr->fd;
int retry;
PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
if (Sockettrans2devtab[ciptr->index].family == AF_INET
#if defined(IPv6) && defined(AF_INET6)
|| Sockettrans2devtab[ciptr->index].family == AF_INET6
#endif
)
retry = 20;
else
retry = 0;
while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
{
if (errno == EADDRINUSE) {
if (flags & ADDR_IN_USE_ALLOWED)
break;
else
return TRANS_ADDR_IN_USE;
}
if (retry-- == 0) {
PRMSG (1, "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
}
if (Sockettrans2devtab[ciptr->index].family == AF_INET
#if defined(IPv6) && defined(AF_INET6)
|| Sockettrans2devtab[ciptr->index].family == AF_INET6
#endif
) {
#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, "SocketCreateListener: listen() failed\n", 0, 0, 0);
close (fd);
return TRANS_CREATE_LISTENER_FAILED;
}
ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
return 0;
}
#ifdef TCPCONN
static int
TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
{
#if defined(IPv6) && defined(AF_INET6)
struct sockaddr_storage sockname;
#else
struct sockaddr_in sockname;
#endif
unsigned short sport;
SOCKLEN_T namelen = sizeof(sockname);
int status;
long tmpport;
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgetservbynameparams sparams;
#endif
struct servent *servp;
#ifdef X11_t
char portbuf[PORTBUFSIZE];
#endif
PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
#ifdef X11_t
if (is_numeric (port))
{
tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
sprintf (portbuf,"%lu", tmpport);
port = portbuf;
}
#endif
if (port && *port)
{
if (!is_numeric (port))
{
if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
{
PRMSG (1,
"SocketINETCreateListener: Unable to get service for %s\n",
port, 0, 0);
return TRANS_CREATE_LISTENER_FAILED;
}
sport = servp->s_port;
}
else
{
tmpport = strtol (port, (char**)NULL, 10);
if (tmpport < 1024 || tmpport > USHRT_MAX)
return TRANS_CREATE_LISTENER_FAILED;
sport = (unsigned short) tmpport;
}
}
else
sport = 0;
bzero(&sockname, sizeof(sockname));
#if defined(IPv6) && defined(AF_INET6)
if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
namelen = sizeof (struct sockaddr_in);
#ifdef BSD44SOCKETS
((struct sockaddr_in *)&sockname)->sin_len = namelen;
#endif
((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
} else {
namelen = sizeof (struct sockaddr_in6);
#ifdef SIN6_LEN
((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
#endif
((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
}
#else
#ifdef BSD44SOCKETS
sockname.sin_len = sizeof (sockname);
#endif
sockname.sin_family = AF_INET;
sockname.sin_port = htons (sport);
sockname.sin_addr.s_addr = htonl (INADDR_ANY);
#endif
if ((status = TRANS(SocketCreateListener) (ciptr,
(struct sockaddr *) &sockname, namelen, flags)) < 0)
{
PRMSG (1,
"SocketINETCreateListener: ...SocketCreateListener() failed\n",
0, 0, 0);
return status;
}
if (TRANS(SocketINETGetAddr) (ciptr) < 0)
{
PRMSG (1,
"SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
0, 0, 0);
return TRANS_CREATE_LISTENER_FAILED;
}
return 0;
}
#endif
#ifdef UNIXCONN
static int
TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
unsigned int flags)
{
struct sockaddr_un sockname;
int namelen;
int oldUmask;
int status;
unsigned int mode;
char tmpport[108];
int abstract = 0;
#ifdef HAVE_ABSTRACT_SOCKETS
abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
#endif
PRMSG (2, "SocketUNIXCreateListener(%s)\n",
port ? port : "NULL", 0, 0);
oldUmask = umask (0);
#ifdef UNIX_DIR
#ifdef HAS_STICKY_DIR_BIT
mode = 01777;
#else
mode = 0777;
#endif
if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
UNIX_DIR, errno, 0);
(void) umask (oldUmask);
return TRANS_CREATE_LISTENER_FAILED;
}
#endif
memset(&sockname, 0, sizeof(sockname));
sockname.sun_family = AF_UNIX;
if (!(port && *port)) {
snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
port = tmpport;
}
if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
return TRANS_CREATE_LISTENER_FAILED;
}
#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
sockname.sun_len = strlen(sockname.sun_path);
#endif
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
namelen = SUN_LEN(&sockname);
#else
namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
#endif
if (abstract) {
sockname.sun_path[0] = '\0';
namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
}
else
unlink (sockname.sun_path);
if ((status = TRANS(SocketCreateListener) (ciptr,
(struct sockaddr *) &sockname, namelen, flags)) < 0)
{
PRMSG (1,
"SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
0, 0, 0);
(void) umask (oldUmask);
return status;
}
namelen = sizeof (sockname);
if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
{
PRMSG (1,
"SocketUNIXCreateListener: Can't allocate space for the addr\n",
0, 0, 0);
(void) umask (oldUmask);
return TRANS_CREATE_LISTENER_FAILED;
}
if (abstract)
sockname.sun_path[0] = '@';
ciptr->family = sockname.sun_family;
ciptr->addrlen = namelen;
memcpy (ciptr->addr, &sockname, ciptr->addrlen);
(void) umask (oldUmask);
return 0;
}
static int
TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
{
struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
struct stat statb;
int status = TRANS_RESET_NOOP;
unsigned int mode;
int abstract = 0;
#ifdef HAVE_ABSTRACT_SOCKETS
abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
#endif
PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
if (!abstract && (
stat (unsock->sun_path, &statb) == -1 ||
((statb.st_mode & S_IFMT) !=
#if defined(NCR) || defined(SCO325) || !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(UNIX_DIR, mode) == -1) {
PRMSG (1, "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
#ifdef TCPCONN
static XtransConnInfo
TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
{
XtransConnInfo newciptr;
struct sockaddr_in sockname;
SOCKLEN_T namelen = sizeof(sockname);
PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
if ((newciptr = (XtransConnInfo) xcalloc (
1, sizeof(struct _XtransConnInfo))) == NULL)
{
PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
*status = TRANS_ACCEPT_BAD_MALLOC;
return NULL;
}
if ((newciptr->fd = accept (ciptr->fd,
(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
{
#ifdef WIN32
errno = WSAGetLastError();
#endif
PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
xfree (newciptr);
*status = TRANS_ACCEPT_FAILED;
return NULL;
}
#ifdef TCP_NODELAY
{
int tmp = 1;
setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
(char *) &tmp, sizeof (int));
}
#endif
if (TRANS(SocketINETGetAddr) (newciptr) < 0)
{
PRMSG (1,
"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,
"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
#ifdef UNIXCONN
static XtransConnInfo
TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
{
XtransConnInfo newciptr;
struct sockaddr_un sockname;
SOCKLEN_T namelen = sizeof sockname;
PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
if ((newciptr = (XtransConnInfo) xcalloc (
1, sizeof(struct _XtransConnInfo))) == NULL)
{
PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
*status = TRANS_ACCEPT_BAD_MALLOC;
return NULL;
}
if ((newciptr->fd = accept (ciptr->fd,
(struct sockaddr *) &sockname, (void *)&namelen)) < 0)
{
PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
xfree (newciptr);
*status = TRANS_ACCEPT_FAILED;
return NULL;
}
ciptr->addrlen = namelen;
if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
{
PRMSG (1,
"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,
"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
#endif
#ifdef TRANS_CLIENT
#ifdef TCPCONN
#if defined(IPv6) && defined(AF_INET6)
struct addrlist {
struct addrinfo * addr;
struct addrinfo * firstaddr;
char port[PORTBUFSIZE];
char host[MAXHOSTNAMELEN];
};
static struct addrlist *addrlist = NULL;
#endif
static int
TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
{
struct sockaddr * socketaddr = NULL;
int socketaddrlen = 0;
int res;
#if defined(IPv6) && defined(AF_INET6)
struct addrinfo hints;
char ntopbuf[INET6_ADDRSTRLEN];
int resetonce = 0;
#endif
struct sockaddr_in sockname;
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgethostbynameparams hparams;
_Xgetservbynameparams sparams;
#endif
struct hostent *hostp;
struct servent *servp;
unsigned long tmpaddr;
#ifdef X11_t
char portbuf[PORTBUFSIZE];
#endif
long tmpport;
char hostnamebuf[256];
PRMSG (2,"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
if (is_numeric (port))
{
tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
sprintf (portbuf, "%lu", tmpport);
port = portbuf;
}
#endif
#if defined(IPv6) && defined(AF_INET6)
{
if (addrlist != NULL) {
if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
if (addrlist->firstaddr)
freeaddrinfo(addrlist->firstaddr);
addrlist->firstaddr = NULL;
}
} else {
addrlist = malloc(sizeof(struct addrlist));
addrlist->firstaddr = NULL;
}
if (addrlist->firstaddr == NULL) {
strncpy(addrlist->port, port, sizeof(addrlist->port));
addrlist->port[sizeof(addrlist->port) - 1] = '\0';
strncpy(addrlist->host, host, sizeof(addrlist->host));
addrlist->host[sizeof(addrlist->host) - 1] = '\0';
bzero(&hints,sizeof(hints));
hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
if (res != 0) {
PRMSG (1, "SocketINETConnect() can't get address "
"for %s:%s: %s\n", host, port, gai_strerror(res));
ESET(EINVAL);
return TRANS_CONNECT_FAILED;
}
for (res = 0, addrlist->addr = addrlist->firstaddr;
addrlist->addr ; res++) {
addrlist->addr = addrlist->addr->ai_next;
}
PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
res = 0;
addrlist->addr = NULL;
}
while (socketaddr == NULL) {
if (addrlist->addr == NULL) {
if (resetonce) {
PRMSG (1, "SocketINETConnect() no usable address "
"for %s:%s\n", host, port, 0);
return TRANS_CONNECT_FAILED;
} else {
resetonce = 1;
addrlist->addr = addrlist->firstaddr;
}
}
socketaddr = addrlist->addr->ai_addr;
socketaddrlen = addrlist->addr->ai_addrlen;
if (addrlist->addr->ai_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
ntopbuf,sizeof(ntopbuf)), 0, 0);
PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
ntohs(sin->sin_port), 0, 0);
if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
if (strcmp(Sockettrans2devtab[ciptr->index].transname,
"tcp") == 0) {
XtransConnInfo newciptr;
TRANS(SocketINETClose)(ciptr);
newciptr = TRANS(SocketOpenCOTSClientBase)(
"tcp", "tcp", host, port, ciptr->index);
if (newciptr)
ciptr->fd = newciptr->fd;
if (!newciptr ||
Sockettrans2devtab[newciptr->index].family !=
AF_INET) {
socketaddr = NULL;
PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
" socketfor IPv4 address\n", 0,0,0);
}
if (newciptr)
xfree(newciptr);
} else {
socketaddr = NULL;
PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
0,0,0);
}
}
} else if (addrlist->addr->ai_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
inet_ntop(addrlist->addr->ai_family,
&sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
0, 0);
PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
ntohs(sin6->sin6_port), 0, 0);
if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
if (strcmp(Sockettrans2devtab[ciptr->index].transname,
"tcp") == 0) {
XtransConnInfo newciptr;
TRANS(SocketINETClose)(ciptr);
newciptr = TRANS(SocketOpenCOTSClientBase)(
"tcp", "tcp", host, port, -1);
if (newciptr)
ciptr->fd = newciptr->fd;
if (!newciptr ||
Sockettrans2devtab[newciptr->index].family !=
AF_INET6) {
socketaddr = NULL;
PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
"socket for IPv6 address\n", 0,0,0);
}
if (newciptr)
xfree(newciptr);
}
else
{
socketaddr = NULL;
PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
0,0,0);
}
}
} else {
socketaddr = NULL;
}
if (socketaddr == NULL) {
addrlist->addr = addrlist->addr->ai_next;
}
}
}
#else
{
#ifdef BSD44SOCKETS
sockname.sin_len = sizeof (struct sockaddr_in);
#endif
sockname.sin_family = AF_INET;
#ifndef INADDR_NONE
#define INADDR_NONE ((in_addr_t) 0xffffffff)
#endif
if (isascii (host[0]) && isdigit (host[0])) {
tmpaddr = inet_addr (host);
} else {
tmpaddr = INADDR_NONE;
}
PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
if (tmpaddr == INADDR_NONE) {
if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
host, 0, 0);
ESET(EINVAL);
return TRANS_CONNECT_FAILED;
}
if (hostp->h_addrtype != AF_INET) {
PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
ESET(EPROTOTYPE);
return TRANS_CONNECT_FAILED;
}
memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
sizeof (sockname.sin_addr));
} else {
sockname.sin_addr.s_addr = tmpaddr;
}
if (!is_numeric (port)) {
if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
PRMSG (1,"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,"SocketINETConnect: sockname.sin_port = %d\n",
ntohs(sockname.sin_port), 0, 0);
socketaddr = (struct sockaddr *) &sockname;
socketaddrlen = sizeof(sockname);
}
#endif
{
int tmp = 1;
setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
(char *) &tmp, sizeof (int));
}
if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
{
#ifdef WIN32
int olderrno = WSAGetLastError();
#else
int olderrno = errno;
#endif
if (olderrno == ECONNREFUSED || olderrno == EINTR
#if defined(IPv6) && defined(AF_INET6)
|| (((addrlist->addr->ai_next != NULL) ||
(addrlist->addr != addrlist->firstaddr)) &&
(olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
#if defined(EHOSTDOWN)
|| olderrno == EHOSTDOWN
#endif
))
#endif
)
res = TRANS_TRY_CONNECT_AGAIN;
else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
res = TRANS_IN_PROGRESS;
else
{
PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
olderrno,0, 0);
res = TRANS_CONNECT_FAILED;
}
} else {
res = 0;
if (TRANS(SocketINETGetAddr) (ciptr) < 0)
{
PRMSG (1,
"SocketINETConnect: ...SocketINETGetAddr() failed:\n",
0, 0, 0);
res = TRANS_CONNECT_FAILED;
}
else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
{
PRMSG (1,
"SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
0, 0, 0);
res = TRANS_CONNECT_FAILED;
}
}
#if defined(IPv6) && defined(AF_INET6)
if (res != 0) {
addrlist->addr = addrlist->addr->ai_next;
}
#endif
return res;
}
#endif
#ifdef UNIXCONN
static int
UnixHostReallyLocal (char *host)
{
char hostnamebuf[256];
TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
if (strcmp (hostnamebuf, host) == 0)
{
return (1);
} else {
#if defined(IPv6) && defined(AF_INET6)
struct addrinfo *localhostaddr;
struct addrinfo *otherhostaddr;
struct addrinfo *i, *j;
int equiv = 0;
if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
return 0;
if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
freeaddrinfo(localhostaddr);
return 0;
}
for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
if (i->ai_family == j->ai_family) {
if (i->ai_family == AF_INET) {
struct sockaddr_in *sinA
= (struct sockaddr_in *) i->ai_addr;
struct sockaddr_in *sinB
= (struct sockaddr_in *) j->ai_addr;
struct in_addr *A = &sinA->sin_addr;
struct in_addr *B = &sinB->sin_addr;
if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
equiv = 1;
}
} else if (i->ai_family == AF_INET6) {
struct sockaddr_in6 *sinA
= (struct sockaddr_in6 *) i->ai_addr;
struct sockaddr_in6 *sinB
= (struct sockaddr_in6 *) j->ai_addr;
struct in6_addr *A = &sinA->sin6_addr;
struct in6_addr *B = &sinB->sin6_addr;
if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
equiv = 1;
}
}
}
}
}
freeaddrinfo(localhostaddr);
freeaddrinfo(otherhostaddr);
return equiv;
#else
char specified_local_addr_list[10][4];
int scount, equiv, i, j;
#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
_Xgethostbynameparams hparams;
#endif
struct hostent *hostp;
if ((hostp = _XGethostbyname (host,hparams)) == NULL)
return (0);
scount = 0;
while (hostp->h_addr_list[scount] && scount <= 8)
{
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 = _XGethostbyname (hostnamebuf,hparams)) == 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]))
{
equiv = 1;
break;
}
j++;
}
i++;
}
return (equiv);
#endif
}
}
static int
TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
{
struct sockaddr_un sockname;
SOCKLEN_T namelen;
int abstract = 0;
#ifdef HAVE_ABSTRACT_SOCKETS
abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
#endif
PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
{
PRMSG (1,
"SocketUNIXConnect: Cannot connect to non-local host %s\n",
host, 0, 0);
return TRANS_CONNECT_FAILED;
}
if (!port || !*port)
{
PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
0, 0, 0);
return TRANS_CONNECT_FAILED;
}
sockname.sun_family = AF_UNIX;
if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
return TRANS_CONNECT_FAILED;
}
#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__))
sockname.sun_len = strlen (sockname.sun_path);
#endif
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
namelen = SUN_LEN (&sockname);
#else
namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
#endif
if (abstract) {
sockname.sun_path[0] = '\0';
}
if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
{
int olderrno = errno;
int connected = 0;
if (!connected)
{
errno = olderrno;
if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
return TRANS_IN_PROGRESS;
else if (olderrno == EINTR)
return TRANS_TRY_CONNECT_AGAIN;
else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
if (abstract) {
ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
return TRANS_TRY_CONNECT_AGAIN;
} else {
return TRANS_CONNECT_FAILED;
}
} else {
PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
EGET(),0, 0);
return TRANS_CONNECT_FAILED;
}
}
}
if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
(ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
{
PRMSG (1,
"SocketUNIXCreateListener: Can't allocate space for the addr\n",
0, 0, 0);
return TRANS_CONNECT_FAILED;
}
if (abstract)
sockname.sun_path[0] = '@';
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
#endif
static int
TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
{
PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
ciptr, ciptr->fd, pend);
#ifdef WIN32
{
int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
return ret;
}
#else
#if defined(__i386__) && defined(SYSV) && !defined(SCO325)
return ioctl (ciptr->fd, I_NREAD, (char *) pend);
#else
return ioctl (ciptr->fd, FIONREAD, (char *) pend);
#endif
#endif
}
static int
TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
{
PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
#if defined(WIN32)
{
int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
#ifdef WIN32
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
#endif
return ret;
}
#else
return read (ciptr->fd, buf, size);
#endif
}
static int
TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
{
PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
#if defined(WIN32)
{
int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
#ifdef WIN32
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
#endif
return ret;
}
#else
return write (ciptr->fd, buf, size);
#endif
}
static int
TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
return READV (ciptr, buf, size);
}
static int
TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
return WRITEV (ciptr, buf, size);
}
static int
TRANS(SocketDisconnect) (XtransConnInfo ciptr)
{
PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
#ifdef WIN32
{
int ret = shutdown (ciptr->fd, 2);
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
return ret;
}
#else
return shutdown (ciptr->fd, 2);
#endif
}
#ifdef TCPCONN
static int
TRANS(SocketINETClose) (XtransConnInfo ciptr)
{
PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
#ifdef WIN32
{
int ret = close (ciptr->fd);
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
return ret;
}
#else
return close (ciptr->fd);
#endif
}
#endif
#ifdef UNIXCONN
static int
TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
{
struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
int ret;
PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
ret = close(ciptr->fd);
if (ciptr->flags
&& sockname
&& sockname->sun_family == AF_UNIX
&& sockname->sun_path[0])
{
if (!(ciptr->flags & TRANS_NOUNLINK
|| ciptr->transptr->flags & TRANS_ABSTRACT))
unlink (sockname->sun_path);
}
return ret;
}
static int
TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
{
int ret;
PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
ciptr, ciptr->fd, 0);
ret = close(ciptr->fd);
return ret;
}
#endif
#ifdef TCPCONN
# ifdef TRANS_SERVER
static char* tcp_nolisten[] = {
"inet",
#if defined(IPv6) && defined(AF_INET6)
"inet6",
#endif
NULL
};
# endif
Xtransport TRANS(SocketTCPFuncs) = {
"tcp",
TRANS_ALIAS,
#ifdef TRANS_CLIENT
TRANS(SocketOpenCOTSClient),
#endif
#ifdef TRANS_SERVER
tcp_nolisten,
TRANS(SocketOpenCOTSServer),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCLTSClient),
#endif
#ifdef TRANS_SERVER
TRANS(SocketOpenCLTSServer),
#endif
#ifdef TRANS_REOPEN
TRANS(SocketReopenCOTSServer),
TRANS(SocketReopenCLTSServer),
#endif
TRANS(SocketSetOption),
#ifdef TRANS_SERVER
TRANS(SocketINETCreateListener),
NULL,
TRANS(SocketINETAccept),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketINETConnect),
#endif
TRANS(SocketBytesReadable),
TRANS(SocketRead),
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
};
Xtransport TRANS(SocketINETFuncs) = {
"inet",
0,
#ifdef TRANS_CLIENT
TRANS(SocketOpenCOTSClient),
#endif
#ifdef TRANS_SERVER
NULL,
TRANS(SocketOpenCOTSServer),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCLTSClient),
#endif
#ifdef TRANS_SERVER
TRANS(SocketOpenCLTSServer),
#endif
#ifdef TRANS_REOPEN
TRANS(SocketReopenCOTSServer),
TRANS(SocketReopenCLTSServer),
#endif
TRANS(SocketSetOption),
#ifdef TRANS_SERVER
TRANS(SocketINETCreateListener),
NULL,
TRANS(SocketINETAccept),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketINETConnect),
#endif
TRANS(SocketBytesReadable),
TRANS(SocketRead),
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
};
#if defined(IPv6) && defined(AF_INET6)
Xtransport TRANS(SocketINET6Funcs) = {
"inet6",
0,
#ifdef TRANS_CLIENT
TRANS(SocketOpenCOTSClient),
#endif
#ifdef TRANS_SERVER
NULL,
TRANS(SocketOpenCOTSServer),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCLTSClient),
#endif
#ifdef TRANS_SERVER
TRANS(SocketOpenCLTSServer),
#endif
#ifdef TRANS_REOPEN
TRANS(SocketReopenCOTSServer),
TRANS(SocketReopenCLTSServer),
#endif
TRANS(SocketSetOption),
#ifdef TRANS_SERVER
TRANS(SocketINETCreateListener),
NULL,
TRANS(SocketINETAccept),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketINETConnect),
#endif
TRANS(SocketBytesReadable),
TRANS(SocketRead),
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
};
#endif
#endif
#ifdef UNIXCONN
#if !defined(LOCALCONN)
Xtransport TRANS(SocketLocalFuncs) = {
"local",
#ifdef HAVE_ABSTRACT_SOCKETS
TRANS_ABSTRACT,
#else
0,
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCOTSClient),
#endif
#ifdef TRANS_SERVER
NULL,
TRANS(SocketOpenCOTSServer),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCLTSClient),
#endif
#ifdef TRANS_SERVER
TRANS(SocketOpenCLTSServer),
#endif
#ifdef TRANS_REOPEN
TRANS(SocketReopenCOTSServer),
TRANS(SocketReopenCLTSServer),
#endif
TRANS(SocketSetOption),
#ifdef TRANS_SERVER
TRANS(SocketUNIXCreateListener),
TRANS(SocketUNIXResetListener),
TRANS(SocketUNIXAccept),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketUNIXConnect),
#endif
TRANS(SocketBytesReadable),
TRANS(SocketRead),
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
};
#endif
# ifdef TRANS_SERVER
# if !defined(LOCALCONN)
static char* unix_nolisten[] = { "local" , NULL };
# endif
# endif
Xtransport TRANS(SocketUNIXFuncs) = {
"unix",
#if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
TRANS_ALIAS,
#else
0,
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCOTSClient),
#endif
#ifdef TRANS_SERVER
#if !defined(LOCALCONN)
unix_nolisten,
#else
NULL,
#endif
TRANS(SocketOpenCOTSServer),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketOpenCLTSClient),
#endif
#ifdef TRANS_SERVER
TRANS(SocketOpenCLTSServer),
#endif
#ifdef TRANS_REOPEN
TRANS(SocketReopenCOTSServer),
TRANS(SocketReopenCLTSServer),
#endif
TRANS(SocketSetOption),
#ifdef TRANS_SERVER
TRANS(SocketUNIXCreateListener),
TRANS(SocketUNIXResetListener),
TRANS(SocketUNIXAccept),
#endif
#ifdef TRANS_CLIENT
TRANS(SocketUNIXConnect),
#endif
TRANS(SocketBytesReadable),
TRANS(SocketRead),
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
};
#endif