diff options
author | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-26 22:48:40 +0000 |
---|---|---|
committer | Kaleb Keithley <kaleb@freedesktop.org> | 2003-11-26 22:48:40 +0000 |
commit | acb541bcf33fc15b75adf872605734fd730f9168 (patch) | |
tree | 5a5fad5f038ddf02d4b343adb219848ae68f7b1f | |
parent | d93c194ca393697cd053d63ed7546d48735a6990 (diff) |
merge latest (4.3.99.16) from XFree86 (vendor) branch
-rw-r--r-- | Xtrans.c | 119 | ||||
-rw-r--r-- | Xtrans.h | 20 | ||||
-rw-r--r-- | Xtransdnet.c | 4 | ||||
-rw-r--r-- | Xtransint.h | 160 | ||||
-rw-r--r-- | Xtranslcl.c | 24 | ||||
-rw-r--r-- | Xtransos2.c | 887 | ||||
-rw-r--r-- | Xtranssock.c | 647 | ||||
-rw-r--r-- | Xtranstli.c | 12 | ||||
-rw-r--r-- | Xtransutil.c | 108 | ||||
-rw-r--r-- | transport.c | 9 |
10 files changed, 1704 insertions, 286 deletions
@@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.28 2002/11/20 23:00:36 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.33 2003/08/11 17:41:29 eich Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -78,6 +78,7 @@ from The Open Group. #define TRANS_LOCAL_NAMED_INDEX 11 #define TRANS_LOCAL_ISC_INDEX 12 #define TRANS_LOCAL_SCO_INDEX 13 +#define TRANS_SOCKET_INET6_INDEX 14 static @@ -89,6 +90,9 @@ Xtransport_table Xtransports[] = { #endif /* STREAMSCONN */ #if defined(TCPCONN) { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, +#if defined(IPv6) && defined(AF_INET6) + { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, +#endif /* IPv6 */ { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, #endif /* TCPCONN */ #if defined(DNETCONN) @@ -100,6 +104,9 @@ Xtransport_table Xtransports[] = { #endif /* !LOCALCONN */ { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, #endif /* UNIXCONN */ +#if defined(OS2PIPECONN) + { &TRANS(OS2LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, +#endif /* OS2PIPECONN */ #if defined(LOCALCONN) { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, #ifndef sun @@ -134,7 +141,7 @@ void TRANS(FreeConnInfo) (XtransConnInfo ciptr) { - PRMSG (3,"FreeConnInfo(%x)\n", ciptr, 0, 0); + PRMSG (3,"FreeConnInfo(%p)\n", ciptr, 0, 0); if (ciptr->addr) xfree (ciptr->addr); @@ -166,6 +173,7 @@ TRANS(SelectTransport) (char *protocol) */ strncpy (protobuf, protocol, PROTOBUFSIZE - 1); + protobuf[PROTOBUFSIZE-1] = '\0'; for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) if (isupper (protobuf[i])) @@ -198,7 +206,7 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) * Other than fontlib, the address is a string formatted * as "protocol/host:port". * - * If the protocol part is missing, then assume INET. + * If the protocol part is missing, then assume TCP. * If the protocol part and host part are missing, then assume local. * If a "::" is found then assume DNET. */ @@ -206,6 +214,7 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) char *mybuf, *tmpptr; char *_protocol, *_host, *_port; char hostnamebuf[256]; + int _host_len; PRMSG (3,"ParseAddress(%s)\n", address, 0, 0); @@ -220,9 +229,11 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) _protocol = mybuf; - if ((mybuf = strpbrk (mybuf,"/:")) == NULL) - { - /* adress is in a bad format */ + + if ( ((mybuf = strchr (mybuf,'/')) == NULL) && + ((mybuf = strrchr (tmpptr,':')) == NULL) ) + { + /* address is in a bad format */ *protocol = NULL; *host = NULL; *port = NULL; @@ -233,7 +244,7 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) if (*mybuf == ':') { /* - * If there is a hostname, then assume inet, otherwise + * If there is a hostname, then assume tcp, otherwise * it must be local. */ if (mybuf == tmpptr) @@ -243,8 +254,8 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) } else { - /* Ther is a hostname specified */ - _protocol = "inet"; + /* There is a hostname specified */ + _protocol = "tcp"; mybuf = tmpptr; /* reset to the begining of the host ptr */ } } @@ -257,11 +268,11 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) if (strlen(_protocol) == 0) { /* - * If there is a hostname, then assume inet, otherwise + * If there is a hostname, then assume tcp, otherwise * it must be local. */ if (*mybuf != ':') - _protocol = "inet"; + _protocol = "tcp"; else _protocol = "local"; } @@ -271,7 +282,7 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) _host = mybuf; - if ((mybuf = strchr (mybuf,':')) == NULL) + if ((mybuf = strrchr (mybuf,':')) == NULL) { *protocol = NULL; *host = NULL; @@ -280,21 +291,51 @@ TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port) return 0; } - *mybuf ++= '\0'; + /* Check for DECnet */ - if (strlen(_host) == 0) + if ((mybuf != _host) && (*(mybuf - 1) == ':') +#if defined(IPv6) && defined(AF_INET6) + /* An IPv6 address can end in :: so three : in a row is assumed to be + an IPv6 host and not a DECnet node with a : in it's name, unless + DECnet is specifically requested */ + && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') || + ((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) ) +#endif + ) { - TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); - _host = hostnamebuf; + _protocol = "dnet"; + *(mybuf - 1) = '\0'; } - /* Check for DECnet */ + *mybuf ++= '\0'; - if (*mybuf == ':') + _host_len = strlen(_host); + if (_host_len == 0) { - _protocol = "dnet"; - mybuf++; + TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); + _host = hostnamebuf; + } +#if defined(IPv6) && defined(AF_INET6) + /* hostname in IPv6 [numeric_addr]:0 form? */ + else if ( (_host_len > 3) && + ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) + && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { + struct sockaddr_in6 sin6; + + *(_host + _host_len - 1) = '\0'; + + /* Verify address is valid IPv6 numeric form */ + if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { + /* It is. Use it as such. */ + _host++; + _protocol = "inet6"; + } else { + /* It's not, restore it just in case some other code can use it. */ + *(_host + _host_len - 1) = ']'; + } } +#endif + /* Get the port */ @@ -727,10 +768,10 @@ TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) #ifdef TRANS_SERVER int -TRANS(CreateListener) (XtransConnInfo ciptr, char *port) +TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) { - return ciptr->transptr->CreateListener (ciptr, port); + return ciptr->transptr->CreateListener (ciptr, port, flags); } int @@ -738,6 +779,7 @@ TRANS(NoListen) (char * protocol) { Xtransport *trans; + int i = 0, ret = 0; if ((trans = TRANS(SelectTransport)(protocol)) == NULL) { @@ -746,9 +788,16 @@ TRANS(NoListen) (char * protocol) return -1; } - + if (trans->flags & TRANS_ALIAS) { + if (trans->nolisten) + while (trans->nolisten[i]) { + ret |= TRANS(NoListen)(trans->nolisten[i]); + i++; + } + } + trans->flags |= TRANS_NOLISTEN; - return 0; + return ret; } int @@ -996,8 +1045,11 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, char buffer[256]; /* ??? What size ?? */ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; int status, i, j; +#if defined(IPv6) && defined(AF_INET6) + int ipv6_succ = 0; +#endif - PRMSG (2,"MakeAllCOTSServerListeners(%s,%x)\n", + PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n", port ? port : "NULL", ciptrs_ret, 0); *count_ret = 0; @@ -1005,6 +1057,7 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, for (i = 0; i < NUMTRANS; i++) { Xtransport *trans = Xtransports[i].transport; + unsigned int flags = 0; if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN) continue; @@ -1024,8 +1077,13 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, trans->TransName, 0, 0); continue; } +#if defined(IPv6) && defined(AF_INET6) + if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX + && ipv6_succ)) + flags |= ADDR_IN_USE_ALLOWED; +#endif - if ((status = TRANS(CreateListener (ciptr, port))) < 0) + if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) { if (status == TRANS_ADDR_IN_USE) { @@ -1057,6 +1115,11 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, } } +#if defined(IPv6) && defined(AF_INET6) + if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) + ipv6_succ = 1; +#endif + PRMSG (5, "MakeAllCOTSServerListeners: opened listener for %s, %d\n", trans->TransName, ciptr->fd, 0); @@ -1099,7 +1162,7 @@ TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; int status, i, j; - PRMSG (2,"MakeAllCLTSServerListeners(%s,%x)\n", + PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)\n", port ? port : "NULL", ciptrs_ret, 0); *count_ret = 0; @@ -1124,7 +1187,7 @@ TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, continue; } - if ((status = TRANS(CreateListener (ciptr, port))) < 0) + if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0) { if (status == TRANS_ADDR_IN_USE) { @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtrans.h,v 3.18 2001/12/14 19:57:04 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtrans.h,v 3.22 2003/07/24 13:50:19 eich Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -57,6 +57,14 @@ from The Open Group. #include <X11/Xfuncproto.h> #include <X11/Xos.h> +#ifndef WIN32 +#ifndef Lynx +#include <sys/socket.h> +#else +#include <socket.h> +#endif +#endif + /* * Set the functions names according to where this code is being compiled. @@ -83,7 +91,7 @@ static char* __xtransname = "_X11Trans"; static char* __xtransname = "_XSERVTrans"; #endif #define X11_t -#endif /* X11_t */ +#endif /* XSERV_t */ #ifdef XIM_t #if !defined(UNIXCPP) || defined(ANSICPP) @@ -173,12 +181,15 @@ static char* __xtransname = "_XTrans"; * This structure needs to be independent of the socket/TLI interface used. */ +#if defined(IPv6) && defined(AF_INET6) +typedef struct sockaddr_storage Xtransaddr; +#else #define XTRANS_MAX_ADDR_LEN 128 /* large enough to hold sun_path */ typedef struct { unsigned char addr[XTRANS_MAX_ADDR_LEN]; } Xtransaddr; - +#endif #ifdef LONG64 typedef int BytesReadable_t; @@ -328,7 +339,8 @@ int TRANS(SetOption)( int TRANS(CreateListener)( XtransConnInfo, /* ciptr */ - char * /* port */ + char *, /* port */ + unsigned int /* flags */ ); int TRANS(NoListen) ( diff --git a/Xtransdnet.c b/Xtransdnet.c index fcdede0..40b08b3 100644 --- a/Xtransdnet.c +++ b/Xtransdnet.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtransdnet.c,v 3.7 2002/11/26 01:12:30 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtransdnet.c,v 3.8 2003/08/26 15:38:39 tsi Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -340,7 +340,7 @@ TRANS(DNETSetOption) (XtransConnInfo ciptr, int option, int arg) #ifdef TRANS_SERVER static int -TRANS(DNETCreateListener) (XtransConnInfo ciptr, char *port) +TRANS(DNETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) { struct sockaddr_dn dnsock; diff --git a/Xtransint.h b/Xtransint.h index a9d7d91..9b73f5e 100644 --- a/Xtransint.h +++ b/Xtransint.h @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.35 2002/11/26 01:12:30 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.41 2003/08/28 00:35:23 tsi Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -81,106 +81,107 @@ from The Open Group. #endif #ifdef WIN32 -#define _WILLWINSOCK_ +# define _WILLWINSOCK_ #endif #include "Xtrans.h" #ifdef XTRANSDEBUG -#include <stdio.h> +# include <stdio.h> #endif /* XTRANSDEBUG */ #include <errno.h> #ifndef WIN32 -#ifndef Lynx -#include <sys/socket.h> -#else -#include <socket.h> -#endif -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef __UNIXOS2__ -#include <sys/ioctl.h> -#endif +# ifndef Lynx +# include <sys/socket.h> +# else +# include <socket.h> +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# ifdef __UNIXOS2__ +# include <sys/ioctl.h> +# endif /* * Moved the setting of NEED_UTSNAME to this header file from Xtrans.c, * to avoid a race condition. JKJ (6/5/97) */ -#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(SCO) -#ifndef NEED_UTSNAME -#define NEED_UTSNAME -#endif -#include <sys/utsname.h> -#endif +# if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(SCO) +# ifndef NEED_UTSNAME +# define NEED_UTSNAME +# endif +# include <sys/utsname.h> +# endif /* * makedepend screws up on #undef OPEN_MAX, so we define a new symbol */ -#ifndef TRANS_OPEN_MAX - -#ifndef X_NOT_POSIX -#ifdef _POSIX_SOURCE -#include <limits.h> -#else -#define _POSIX_SOURCE -#include <limits.h> -#undef _POSIX_SOURCE -#endif -#endif -#ifndef OPEN_MAX -#ifdef __GNU__ -#define OPEN_MAX (sysconf(_SC_OPEN_MAX)) -#endif -#ifdef SVR4 -#define OPEN_MAX 256 -#else -#include <sys/param.h> -#ifndef OPEN_MAX -#ifdef __OSF1__ -#define OPEN_MAX 256 -#else -#ifdef NOFILE -#define OPEN_MAX NOFILE -#else -#if !defined(__UNIXOS2__) && !defined(__QNX__) -#define OPEN_MAX NOFILES_MAX -#else -#define OPEN_MAX 256 -#endif -#endif -#endif -#endif -#endif -#endif -#ifdef __GNU__ -#define TRANS_OPEN_MAX OPEN_MAX -#else /* !__GNU__ */ -#if OPEN_MAX > 256 -#define TRANS_OPEN_MAX 256 -#else -#define TRANS_OPEN_MAX OPEN_MAX -#endif -#endif /*__GNU__*/ - -#endif /* TRANS_OPEN_MAX */ - -#ifdef __UNIXOS2__ -#define ESET(val) -#else -#define ESET(val) errno = val -#endif -#define EGET() errno +# ifndef TRANS_OPEN_MAX + +# ifndef X_NOT_POSIX +# ifdef _POSIX_SOURCE +# include <limits.h> +# else +# define _POSIX_SOURCE +# include <limits.h> +# undef _POSIX_SOURCE +# endif +# endif +# ifndef OPEN_MAX +# if defined(_SC_OPEN_MAX) +# define OPEN_MAX (sysconf(_SC_OPEN_MAX)) +# else +# ifdef SVR4 +# define OPEN_MAX 256 +# else +# include <sys/param.h> +# ifndef OPEN_MAX +# ifdef __OSF1__ +# define OPEN_MAX 256 +# else +# ifdef NOFILE +# define OPEN_MAX NOFILE +# else +# if !defined(__UNIXOS2__) && !defined(__QNX__) +# define OPEN_MAX NOFILES_MAX +# else +# define OPEN_MAX 256 +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# if defined(_SC_OPEN_MAX) +# define TRANS_OPEN_MAX OPEN_MAX +# else /* !__GNU__ */ +# if OPEN_MAX > 256 +# define TRANS_OPEN_MAX 256 +# else +# define TRANS_OPEN_MAX OPEN_MAX +# endif +# endif /*__GNU__*/ + +# endif /* TRANS_OPEN_MAX */ + +# ifdef __UNIXOS2__ +# define ESET(val) +# else +# define ESET(val) errno = val +# endif +# define EGET() errno #else /* WIN32 */ -#include <limits.h> /* for USHRT_MAX */ +# include <limits.h> /* for USHRT_MAX */ -#define ESET(val) WSASetLastError(val) -#define EGET() WSAGetLastError() +# define ESET(val) WSASetLastError(val) +# define EGET() WSAGetLastError() #endif /* WIN32 */ @@ -226,7 +227,7 @@ typedef struct _Xtransport { #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER - + char ** nolisten; XtransConnInfo (*OpenCOTSServer)( struct _Xtransport *, /* transport */ char *, /* protocol */ @@ -283,10 +284,13 @@ typedef struct _Xtransport { ); #ifdef TRANS_SERVER +/* Flags */ +# define ADDR_IN_USE_ALLOWED 1 int (*CreateListener)( XtransConnInfo, /* connection */ - char * /* port */ + char *, /* port */ + unsigned int /* flags */ ); int (*ResetListener)( diff --git a/Xtranslcl.c b/Xtranslcl.c index f92d6f8..352f360 100644 --- a/Xtranslcl.c +++ b/Xtranslcl.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtranslcl.c,v 3.39 2002/11/26 01:12:30 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtranslcl.c,v 3.41 2003/08/26 15:38:39 tsi Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -2325,7 +2325,7 @@ TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg) #ifdef TRANS_SERVER static int -TRANS(LocalCreateListener)(XtransConnInfo ciptr, char *port) +TRANS(LocalCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags) { PRMSG(2,"LocalCreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port); @@ -2495,6 +2495,21 @@ TRANS(LocalCloseForCloning)(XtransConnInfo ciptr) * call to SelectTransport() in Xtrans.c. */ +#ifdef TRANS_SERVER +static char * local_aliases[] = { +# ifndef sun + "pts", +# endif + "named", +# ifndef sun +# ifndef SCO325 + "isc", +# endif + "sco", +# endif + NULL }; +#endif + Xtransport TRANS(LocalFuncs) = { /* Local Interface */ "local", @@ -2503,6 +2518,7 @@ Xtransport TRANS(LocalFuncs) = { TRANS(LocalOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + local_aliases, TRANS(LocalOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -2544,6 +2560,7 @@ Xtransport TRANS(PTSFuncs) = { TRANS(LocalOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(LocalOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -2585,6 +2602,7 @@ Xtransport TRANS(NAMEDFuncs) = { TRANS(LocalOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(LocalOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -2626,6 +2644,7 @@ Xtransport TRANS(ISCFuncs) = { TRANS(LocalOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(LocalOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -2665,6 +2684,7 @@ Xtransport TRANS(SCOFuncs) = { TRANS(LocalOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(LocalOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT diff --git a/Xtransos2.c b/Xtransos2.c new file mode 100644 index 0000000..f61617e --- /dev/null +++ b/Xtransos2.c @@ -0,0 +1,887 @@ +/* $XFree86: xc/lib/xtrans/Xtransos2.c,v 3.10 2003/08/26 15:38:39 tsi Exp $ */ + +/* + * (c) Copyright 1996 by Sebastien Marineau and Holger Veit + * <marineau@genie.uottawa.ca> + * <Holger.Veit@gmd.de> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * 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 + * HOLGER VEIT 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 Sebastien Marineau or Holger Veit shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Holger Veit or Sebastien Marineau. + * + */ + +/* Implementation of the OS/2 local pipe transport layer */ + +#define INCL_DOSNMPIPES +#define INCL_DOSPROCESS +#define INCL_DOSERRORS +#define INCL_DOSFILEMGR +#undef BYTE +#undef BOOL +#include <os2.h> + +#ifdef XSERV_t +extern HEV hPipeSem; +BOOL init_server_pipes(); +#endif + +/************************************************************************* + * Independent Layer + *************************************************************************/ +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(Os2OpenClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + APIRET rc; + HFILE hfd,hServer; + ULONG action,byteWritten,State; + char pipename[256],clientname[256]; + char server_string[256]; + struct sockaddr *addr_name; + unsigned char pipe_len; + XtransConnInfo ciptr; + static int unique_id=0; + int i,namelen,try; + + PRMSG(2,"Os2OpenClient(%s,%s,%s)\n",protocol,host,port); + + /* test, whether the host is really local, i.e. either + * "os2" or "local" + */ + if (strcmp(protocol,"os2") && strcmp(protocol,"local")) { + PRMSG (1, + "Os2OpenClient: Cannot connect to non-local host %s\n", + host, 0, 0); + return NULL; + } + + /* make the pipename */ + + if (port && *port ) { + if( *port == '/' ) { /* A full pathname */ + (void) sprintf(pipename, "\\PIPE\\X\\%s,", port); + } else { + (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port); + } + } else { + (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); } + + PRMSG(5, "Os2OpenClient: Creating pipe %s\n",pipename, 0,0 ); + + /* make a connection entry */ + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) { + PRMSG(1,"Os2OpenClient: calloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + /* open the pipe. Try ten times before giving up at 500ms intervals*/ + try = 0; + do { + rc = DosOpen(pipename,&hServer, &action, 0, + FILE_NORMAL, FILE_OPEN, + OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE, + (PEAOP2)NULL); + if(rc == 0) break; + if (try >=10) { + PRMSG(1,"Os2OpenClient: Open server pipe %s failed, rc=%d\n", + pipename,rc,0 ); + PRMSG(1,"\tProbable causes: either the XServer is not running, or has not started properly,\n", + 0,0,0 ); + PRMSG(1,"\tor the DISPLAY variable is set incorrectly.\n", + 0,0,0 ); + xfree(ciptr); + return NULL; + } + try ++; + DosSleep(500); + } while (rc != 0); + +/* OK, now we are talking to the server. Generate a unique pipe name and pass it to + * the server. Make the pipe and wait for server to connect */ + + sprintf(clientname,"\\PIPE\\X\\%d.%d",getpid(),unique_id++); + + rc = DosCreateNPipe (clientname, &hfd, + NP_NOINHERIT | NP_ACCESS_DUPLEX, + 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, + 16384, 16384, 0); + if (rc != 0){ + PRMSG(1, "Os2OpenClient: Unable to create pipe %s\n", pipename,0,0 ); + DosClose(hfd); + pipe_len=0; + DosWrite(hServer,&pipe_len,1,&byteWritten); + DosClose(hServer); + xfree(ciptr); + return(NULL); + } + + /* Connect to the pipe. */ + + rc = DosConnectNPipe (hfd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2OpenClient: Unable to connect to pipe %s\n", pipename,0,0 ); + DosClose (hfd); + DosClose(hServer); + xfree(ciptr); + return (NULL); + } + +/* Now write name to server on hServer */ + server_string[0]=(char) strlen(clientname)+1; + strcpy(&server_string[1],clientname); + rc = DosWrite(hServer,server_string,(ULONG)server_string[0]+1,&byteWritten); + if(rc != 0){ /* Could not write to server pipe? */ + PRMSG(1, "Os2OpenClient: Error writing to server pipe, handle=%d, rc=%d, w=%d\n", + hServer,rc,byteWritten ); + DosClose(hServer); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + PRMSG (5, "Os2OpenCLient: Wrote pipename %s to server; len %d written %d \n", + &server_string[1],server_string[0]+1,byteWritten); + + +/* The server will respond by opening the pipe. Wait for that for 30 secs */ + + i=0; + DosSleep(50); /* Give it time to catch up but minimize race condition*/ + rc = DosConnectNPipe(hfd); + while((rc == ERROR_PIPE_NOT_CONNECTED)&&(i++<60)) { + DosSleep(500); + rc = DosConnectNPipe(hfd); + } + + if(rc != 0){ /* Server has not responded! */ + PRMSG(1, "Os2OpenClient: Timeout on wait for server response, handle=%d, rc=%d\n",hServer,rc,0 ); + PRMSG(1, "\tProbable cause: the XServer has exited or crashed while the connection was being established\n",0,0,0 ); + PRMSG(1, "\tor the XServer is too busy to respond.\n",0,0,0 ); + DosClose(hServer); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + +/* OK, the server has connected! Fill-in the info and return */ + + DosClose(hServer); + +/* Last check: make sure client is connected! */ + + rc = DosQueryNPHState(hfd,&State); + if(rc != 0){ /* Client is not connected! */ + PRMSG(1, "Os2OpenClient: Client pipe does not appear connected. rc=%d, h=%d\n",rc,hfd,0 ); + PRMSG(1, "\tProbable cause: the XServer has just exited.\n",0,0,0 ); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + namelen=sizeof(struct sockaddr); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenClient: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + ciptr->addrlen = namelen; + ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX; + strcpy(((struct sockaddr *)ciptr->addr)->sa_data, "local"); + + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenCLient: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr); + return(NULL); + } + ciptr->peeraddrlen = namelen; + ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)ciptr->peeraddr)->sa_data,"local"); + + PRMSG (5, "Os2OpenCLient: Filled in struct: len %d %d name %s\n", + ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data); + + + ciptr->index=hfd; + ciptr->family=AF_UNIX; + if((ciptr->fd=_imphandle(hfd))<0){ + PRMSG(1, "Os2OpenClient: Could not import the pipe handle into EMX\n",0,0,0 ); + PRMSG(1, "\tProbable cause: EMX has run out of free file handles.\n",0,0,0 ); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } + PRMSG(5, "Os2OpenClient: pipe handle %d EMX handle %d\n",ciptr->index,ciptr->fd,0 ); + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + return ciptr; +} +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + APIRET rc; + HFILE hfd; + ULONG action; + char pipename[256]; + struct sockaddr *addr_name; + XtransConnInfo ciptr; + int namelen; + +#ifdef XSERV_t + if (! init_server_pipes()) return(NULL); +#endif + + PRMSG(2,"Os2OpenServer(%s,%s,%s)\n",protocol,host,port); + + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"Os2OpenServer: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + + if (port && *port ) { + if( *port == '/' ) { /* A full pathname */ + (void) sprintf(pipename, "\\PIPE\\X\\%s", port); + } else { + (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port); + } + } else { + (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); + } + + PRMSG(5, "Os2OpenServer: Creating pipe %s\n",pipename, 0,0 ); + + rc = DosCreateNPipe (pipename, &hfd, + NP_NOINHERIT | NP_ACCESS_INBOUND, + 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, + 0, 8192, 0); + if (rc != 0){ + PRMSG(1, "Os2OpenServer: Unable to create pipe %s, rc=%d\n", pipename,rc,0 ); + PRMSG(1, "\tProbable cause: there is already another XServer running on display :%s\n",port,0,0 ); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + + /* Connect to the pipe. */ + + rc = DosConnectNPipe (hfd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2OpenServer: Unable to connect to pipe %s\n", pipename,0,0 ); + DosClose (hfd); + xfree(ciptr); + return (NULL); + } + +/* Pipe is now connected and waiting for client connect */ + +/*** Put in info ***/ + + namelen=sizeof(struct sockaddr); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr); + return(NULL); + } + ciptr->addrlen = namelen; + ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)ciptr->addr)->sa_data, "local"); + + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr); + return(NULL); + } + + ciptr->peeraddrlen = namelen; + ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX; + strcpy(((struct sockaddr *)ciptr->peeraddr)->sa_data,"local"); + + PRMSG (5, "Os2OpenServer: Filled in struct: len %d %d name %s\n", + ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data); + + ciptr->index=hfd; /* Save this for later use in this unused member of struct */ + ciptr->flags=1; /* Listener */ + ciptr->family=AF_UNIX; + + if((ciptr->fd=_imphandle(hfd))<0){ + DosClose(hfd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } + PRMSG(5, "Os2OpenServer: Pipe handle %d EMX handle %d",ciptr->index,ciptr->fd,0 ); + +#ifdef XSERV_t +/* Attach the pipe sem to the pipe. Use handle index as key */ + rc = DosSetNPipeSem(ciptr->fd, (HSEM)hPipeSem, ciptr->fd); + if (rc){ + PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n", + hPipeSem,ciptr->fd,rc); + DosClose(ciptr->fd); + xfree(ciptr->addr); + xfree(ciptr->peeraddr); + xfree(ciptr); + return(NULL); + } +#endif + + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + return(ciptr); +} +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT +static XtransConnInfo +TRANS(Os2OpenCLTSClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCLTSClient(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenClient)(thistrans, protocol, host, port); +} +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_CLIENT +static XtransConnInfo +TRANS(Os2OpenCOTSClient)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCOTSClient(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenClient)(thistrans, protocol, host, port); +} +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenCLTSServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCLTSServer(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenServer)(thistrans, protocol, host, port); +} +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_SERVER +static XtransConnInfo +TRANS(Os2OpenCOTSServer)(Xtransport *thistrans, char *protocol, + char *host, char *port) +{ + PRMSG(2,"Os2OpenCOTSServer(%s,%s,%s)\n",protocol,host,port); + return TRANS(Os2OpenServer)(thistrans, protocol, host, port); +} +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN +static XtransConnInfo +TRANS(Os2ReopenCOTSServer)(Xtransport *thistrans, int fd, char *port) +{ + + XtransConnInfo ciptr; + char addr_name[256]; + int namelen; + + PRMSG(2,"Os2ReopenCOTSServer(%d,%s)\n", fd, port, 0); + + if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"Os2ReopenCOTSServer: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + strcpy(addr_name,"local"); + namelen=sizeof(addr_name); + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n", + 0, 0, 0); + xfree(ciptr); + return(NULL); + } + + ciptr->addrlen = namelen; + memcpy (ciptr->addr, addr_name, ciptr->addrlen); + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n", + 0, 0, 0); + xfree(ciptr); + return(NULL); + } + + ciptr->peeraddrlen = namelen; + memcpy (ciptr->peeraddr,addr_name, ciptr->addrlen); + + ciptr->fd = fd; + ciptr->family=AF_UNIX; + ciptr->flags=1; + PRMSG(1,"Os2ReopenCOTSServer: Filled-in info for handle %d on port %s.\n", fd, port, 0); + + return(ciptr); +} + +static XtransConnInfo +TRANS(Os2ReopenCLTSServer)(Xtransport *thistrans, int fd, char *port) +{ + PRMSG(2,"Os2ReopenCLTSServer(%d,%s)\n", fd, port, 0); + return TRANS(Os2ReopenCOTSServer)(thistrans, fd, port); +} +#endif + +static +TRANS(Os2SetOption)(XtransConnInfo ciptr, int option, int arg) +{ + PRMSG(2,"Os2SetOption(%d,%d,%d)\n",ciptr->fd,option,arg); + return -1; +} + +#ifdef TRANS_SERVER + +static +TRANS(Os2CreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags) +{ + PRMSG(2,"Os2CreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port); + return 0; +} + +static XtransConnInfo +TRANS(Os2Accept)(XtransConnInfo ciptr, int *status) +{ + XtransConnInfo newciptr; + HFILE hClient; + unsigned char length; + ULONG action; + char clientname[256]; + struct sockaddr *addr_name; + int in,namelen; + APIRET rc; + + + PRMSG(2,"Os2Accept(%x->%d)\n", ciptr, ciptr->fd,0); + if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL ) + { + PRMSG(1,"Os2Accept: xcalloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + +/* Read in length of client pipe name. If fails, then reset server pipe */ + if((in=read(ciptr->fd,&length,1))<=0){ + PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n", + in,errno,0 ); + *status = TRANS_ACCEPT_MISC_ERROR; + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + PRMSG(5, "Os2Accept: Bytes to read for name: %d\n",length,0,0 ); + + +/* Check length for valid length ?? */ + +/* Now read in length bytes from pipe for client pipe name */ + if((in=read(ciptr->fd,clientname,length))<=0){ + PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n", + in,errno,0 ); + *status = TRANS_ACCEPT_MISC_ERROR; + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + clientname[length]='\0'; + PRMSG(5, "Os2Accept: Server name %s length %d\n",clientname,length,0 ); + + +/* Now we have the client pipe name. Open it with DosOpen */ + + rc = DosOpen(clientname,&hClient, &action, 0, + FILE_NORMAL, FILE_OPEN, + OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE, + (PEAOP2)NULL); + + PRMSG(5, "Os2Accept: Open pipe %s, handle = %d, rc=%d\n",clientname,hClient,rc ); + + if (rc) { + PRMSG(1,"Os2Accept: Open pipe %s to client failed, rc=%d\n", + clientname,rc,0 ); + PRMSG(1, "\tProbable cause: the client has exited or timed-out.\n",0,0,0 ); + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + + rc = DosSetNPHState (hClient, NP_NOWAIT | NP_READMODE_BYTE); + if (rc != 0) + { + PRMSG(1,"Os2Accept: Could not set pipe %s to non-blocking mode, rc=%d\n", + hClient,rc,0 ); + xfree(newciptr); + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } + return NULL; + } + +/* OK, we seem to be well connected to client. Now disconnect server pipe and put again in listen */ + + rc = DosDisConnectNPipe(ciptr->fd); + rc = DosConnectNPipe (ciptr->fd); + PRMSG(5, "Os2Accept: Reconnecting server pipe %d, rc = %d\n",ciptr->fd,rc,0 ); + + if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED) + { + PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 ); + } /* Consider this non-fatal for present connection */ + +/* And finally fill-in info in newciptr */ + + namelen=sizeof(struct sockaddr); + if ((newciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2Accept: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hClient); + xfree(newciptr); + return(NULL); + } + + newciptr->addrlen = namelen; + ((struct sockaddr *)newciptr->addr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)newciptr->addr)->sa_data, "local"); + + if ((newciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, "Os2Accept: Can't allocate space for the addr\n", + 0, 0, 0); + DosClose(hClient); + xfree(ciptr->addr); + xfree(newciptr); + return(NULL); + } + + newciptr->peeraddrlen = namelen; + ((struct sockaddr *)newciptr->peeraddr)->sa_family = AF_UNIX; + strcpy (((struct sockaddr *)newciptr->peeraddr)->sa_data, "local"); + + PRMSG (5, "Os2Accept: Filled in struct: len %d %d name %s\n", + newciptr->addrlen,newciptr->peeraddrlen,newciptr->peeraddr); + + + newciptr->index=hClient; + newciptr->family=AF_UNIX; + if((newciptr->fd=_imphandle(hClient))<0){ + PRMSG(1,"Os2Accept: Could not import pipe %d into EMX, errno=%d\n", + hClient,errno,0 ); + PRMSG(1, "\tProbable cause: EMX has run out of file handles.\n",0,0,0 ); + DosClose(hClient); + xfree(newciptr->addr); + xfree(newciptr->peeraddr); + xfree(newciptr); + return(NULL); + } + PRMSG(5, "Os2Accept: Pipe handle %d EMX handle %d",newciptr->index,newciptr->fd,0 ); + +#ifdef XSERV_t +/* Attach the pipe sem to the pipe. Use handle index as key */ + rc = DosSetNPipeSem(newciptr->fd, (HSEM)hPipeSem, newciptr->fd); + if (rc){ + PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n", + hPipeSem,newciptr->fd,rc); + DosClose(newciptr->fd); + xfree(newciptr->addr); + xfree(newciptr->peeraddr); + xfree(newciptr); + return(NULL); + } +#endif + + fcntl(ciptr->fd,F_SETFL,O_NDELAY); + fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC); + *status=0; + return newciptr; +} + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + +static +TRANS(Os2Connect)(XtransConnInfo ciptr, char *host, char *port) +{ + PRMSG(2,"Os2Connect(%x->%d,%s)\n", ciptr, ciptr->fd, port); + return 0; +} + +#endif /* TRANS_CLIENT */ + +static int +TRANS(Os2BytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend ) +{ + ULONG rc, state, nread; + AVAILDATA avail; + char buffer; + + PRMSG(2,"Os2BytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend); + + rc = DosPeekNPipe (ciptr->fd, &buffer, 0, &nread, &avail, &state); + if (rc != 0) + { + errno = EPIPE; + *pend = 0; + return -1; + } + if (state == NP_STATE_CLOSING) + { + errno = EPIPE; + *pend = 0; + return -1; + } + errno = 0; + *pend = avail.cbpipe; + return 0; +} + +static int +TRANS(Os2Read)(XtransConnInfo ciptr, char *buf, int size) +{ + int ret; + APIRET rc; + ULONG ulRead; + PRMSG(2,"Os2Read(%d,%x,%d)\n", ciptr->fd, buf, size ); + errno = 0; + rc = DosRead(ciptr->fd, buf, size, &ulRead); + if (rc == 0){ + ret = ulRead; + } + else if ((rc == 232) || (rc == 231)){ + errno = EAGAIN; + ret = -1; + } + else if (rc == 6){ + errno = EBADF; + ret = -1; + } + else if ((rc == 109) || (rc == 230) || (rc == 233)){ + errno = EPIPE; + ret = -1; + } + else { + PRMSG(2,"Os2Read: Unknown return code from DosRead, fd %d rc=%d\n", ciptr->fd,rc,0 ); + errno = EINVAL; + ret = -1; + } + return (ret); +} + +static int +TRANS(Os2Write)(XtransConnInfo ciptr, char *buf, int size) +{ + int ret; + APIRET rc; + ULONG nWritten; + PRMSG(2,"Os2Write(%d,%x,%d)\n", ciptr->fd, buf, size ); + rc = DosWrite(ciptr->fd, buf, size, &nWritten); + if (rc == 0){ + ret = nWritten; + if(nWritten == 0) { + errno=EAGAIN; + ret = -1; + } + } + else if ((rc == 39) || (rc == 112)){ + errno = EAGAIN; + ret = -1; + } + else if ((rc == 109) || (rc == 230) || (rc == 233)){ + errno = EPIPE; + ret = -1; + } + else if (rc == 6){ + errno=EBADF; + ret = -1; + } + else { + PRMSG(2,"(Os2Write)Unknown return code from DosWrite, fd %d rc=%d\n", ciptr->fd,rc,0 ); + errno = EINVAL; + ret = -1; + } + return (ret); +} + +static int +TRANS(Os2Readv)(XtransConnInfo ciptr, struct iovec *buf, int size) +{ + int ret; + PRMSG(2,"Os2Readv(%d,%x,%d)\n", ciptr->fd, buf, size ); + ret = READV(ciptr,buf,size); + if ((ret <0) && (errno == EINVAL)) errno = EPIPE; + return (ret); +} + +static int +TRANS(Os2Writev)(XtransConnInfo ciptr, struct iovec *buf, int size) +{ + int ret; + PRMSG(2,"Os2Writev(%d,%x,%d)\n", ciptr->fd, buf, size ); + ret = WRITEV(ciptr,buf,size); + if ((ret <0) && (errno == EINVAL)) errno = EPIPE; + if ((ret <0) && (errno == ENOSPC)) errno = EAGAIN; + return (ret); +} + +static int +TRANS(Os2Disconnect)(XtransConnInfo ciptr) +{ + PRMSG(2,"Os2Disconnect(%x->%d)\n", ciptr, ciptr->fd, 0); + return 0; +} + +static int +TRANS(Os2Close)(XtransConnInfo ciptr) +{ + int ret; + PRMSG(2,"Os2Close(%x->%d)\n", ciptr, ciptr->fd ,0); + ret=close(ciptr->fd); + return ret; +} + +static int +TRANS(Os2CloseForCloning)(XtransConnInfo ciptr) +{ + int ret; + + PRMSG(2,"Os2CloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0); + ret=close(ciptr->fd); + return ret; +} + + +Xtransport TRANS(OS2LocalFuncs) = { + /* Local Interface */ + "local", + TRANS_LOCAL, +#ifdef TRANS_CLIENT + TRANS(Os2OpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + NULL, + TRANS(Os2OpenCOTSServer), +#endif /* TRANS_SERVER */ +#ifdef TRANS_CLIENT + TRANS(Os2OpenCLTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + TRANS(Os2OpenCLTSServer), +#endif /* TRANS_SERVER */ +#ifdef TRANS_REOPEN + TRANS(Os2ReopenCOTSServer), + TRANS(Os2ReopenCLTSServer), +#endif + TRANS(Os2SetOption), +#ifdef TRANS_SERVER + TRANS(Os2CreateListener), + NULL, /* ResetListener */ + TRANS(Os2Accept), +#endif /* TRANS_SERVER */ +#ifdef TRANS_CLIENT + TRANS(Os2Connect), +#endif /* TRANS_CLIENT */ + TRANS(Os2BytesReadable), + TRANS(Os2Read), + TRANS(Os2Write), + TRANS(Os2Readv), + TRANS(Os2Writev), + TRANS(Os2Disconnect), + TRANS(Os2Close), + TRANS(Os2CloseForCloning), +}; + +#ifdef XSERV_t +/* This function is used in the server to initialize the semaphore used with pipes */ + +BOOL init_server_pipes() +{ + static BOOL first_time=TRUE; + ULONG rc; + + if(first_time){ + rc = DosCreateEventSem(NULL, &hPipeSem,DC_SEM_SHARED,FALSE); + if (rc){ + PRMSG(1,"Os2OpenListener (init_server_pipes): Could not create pipe semaphore, rc=%d\n", + rc,0,0); + return(FALSE); + } + first_time=FALSE; + } +return(TRUE); +} +#endif /* XSERV_t */ diff --git a/Xtranssock.c b/Xtranssock.c index 50098f5..bacb8da 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -2,6 +2,7 @@ /* Copyright 1993, 1994, 1998 The Open Group +Copyright 2002 Sun Microsystems, Inc. All rights reserved. Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that @@ -20,13 +21,13 @@ 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 +Except as contained in this notice, the name of the copyright holders 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. +from the copyright holders. */ -/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.56 2002/11/26 01:12:30 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.65 2003/11/20 00:41:37 dawes Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -59,7 +60,9 @@ from The Open Group. #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) @@ -84,10 +87,11 @@ from The Open Group. #endif #ifndef NO_TCP_H -#ifdef __osf__ +#if defined(__osf__) || defined(linux) #include <sys/param.h> #endif /* osf */ #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) +#include <sys/param.h> #include <machine/endian.h> #endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */ #include <netinet/tcp.h> @@ -98,7 +102,7 @@ from The Open Group. #include <sys/filio.h> #endif -#if (defined(i386) && defined(SYSV)) && !defined(sco) +#if (defined(i386) && defined(SYSV)) && !defined(sco) && !defined(sun) #include <net/errno.h> #endif @@ -184,7 +188,13 @@ typedef struct _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 /* IPv6 */ + {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, + {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */ + {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0}, +#endif #endif /* TCPCONN */ #ifdef UNIXCONN {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0}, @@ -262,24 +272,33 @@ static Sockettrans2dev Sockettrans2devtab[] = { #define PORTBUFSIZE 32 /* + * This provides compatibility for apps linked against system libraries + * that don't have IPv6 support. + */ +#if defined(IPv6) && defined(AF_INET6) +static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT; +#pragma weak in6addr_any = local_in6addr_any +#endif + +/* * These are some utility function used by the real interface function below. */ static int -TRANS(SocketSelectFamily) (char *family) +TRANS(SocketSelectFamily) (int first, char *family) { int i; PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0); - for (i = 0; i < NUMSOCKETFAMILIES;i++) + for (i = first + 1; i < NUMSOCKETFAMILIES;i++) { if (!strcmp (family, Sockettrans2devtab[i].transname)) return i; } - return -1; + return (first == -1 ? -2 : -1); } @@ -292,14 +311,18 @@ static int TRANS(SocketINETGetAddr) (XtransConnInfo ciptr) { +#if defined(IPv6) && defined(AF_INET6) + struct sockaddr_storage sockname; +#else struct sockaddr_in sockname; +#endif #if defined(SVR4) || defined(SCO325) size_t namelen = sizeof sockname; #else int namelen = sizeof sockname; #endif - PRMSG (3,"SocketINETGetAddr(%x)\n", ciptr, 0, 0); + PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0); if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, (void *)&namelen) < 0) @@ -321,7 +344,11 @@ TRANS(SocketINETGetAddr) (XtransConnInfo ciptr) return -1; } +#if defined(IPv6) && defined(AF_INET6) + ciptr->family = ((struct sockaddr *)&sockname)->sa_family; +#else ciptr->family = sockname.sin_family; +#endif ciptr->addrlen = namelen; memcpy (ciptr->addr, &sockname, ciptr->addrlen); @@ -338,14 +365,18 @@ static int TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr) { +#if defined(IPv6) && defined(AF_INET6) + struct sockaddr_storage sockname; +#else struct sockaddr_in sockname; +#endif #if defined(SVR4) || defined(SCO325) size_t namelen = sizeof sockname; #else int namelen = sizeof sockname; #endif - PRMSG (3,"SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0); + PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0); if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, (void *)&namelen) < 0) @@ -397,7 +428,7 @@ TRANS(SocketOpen) (int i, int type) #endif #endif ) { - PRMSG (1, "SocketOpen: socket() failed for %s\n", + PRMSG (2, "SocketOpen: socket() failed for %s\n", Sockettrans2devtab[i].transname, 0, 0); xfree ((char *) ciptr); @@ -405,7 +436,11 @@ TRANS(SocketOpen) (int i, int type) } #ifdef TCP_NODELAY - if (Sockettrans2devtab[i].family == AF_INET) + if (Sockettrans2devtab[i].family == AF_INET +#if defined(IPv6) && defined(AF_INET6) + || Sockettrans2devtab[i].family == AF_INET6 +#endif + ) { /* * turn off TCP coalescence for INET sockets @@ -458,26 +493,25 @@ TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol, { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n", protocol, host, port); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketOpenCOTSClient: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); - return NULL; + while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) != NULL) + break; } - - if ((ciptr = TRANS(SocketOpen) ( - i, Sockettrans2devtab[i].devcotsname)) == NULL) - { - PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", - thistrans->TransName, 0, 0); + if (i < 0) { + if (i == -1) + PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n", + thistrans->TransName, 0, 0); + else + PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); return NULL; } @@ -499,25 +533,24 @@ TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol, { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketOpenCOTSServer: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); - return NULL; + while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) != NULL) + break; } - - if ((ciptr = TRANS(SocketOpen) ( - i, Sockettrans2devtab[i].devcotsname)) == NULL) - { - PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n", - thistrans->TransName, 0, 0); + 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; } @@ -528,17 +561,27 @@ TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol, #ifdef SO_REUSEADDR /* - * SO_REUSEADDR only applied to AF_INET + * SO_REUSEADDR only applied to AF_INET && AF_INET6 */ - if (Sockettrans2devtab[i].family == AF_INET) + 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 /* Save the index for later use */ ciptr->index = i; @@ -557,25 +600,24 @@ TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol, { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketOpenCLTSClient: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); - return NULL; + while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) != NULL) + break; } - - if ((ciptr = TRANS(SocketOpen) ( - i, Sockettrans2devtab[i].devcotsname)) == NULL) - { - PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n", - thistrans->TransName, 0, 0); + 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; } @@ -597,28 +639,34 @@ TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol, { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketOpenCLTSServer: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); + 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; } - if ((ciptr = TRANS(SocketOpen) ( - i, Sockettrans2devtab[i].devcotsname)) == NULL) +#ifdef IPV6_V6ONLY + if (Sockettrans2devtab[i].family == AF_INET6) { - PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n", - thistrans->TransName, 0, 0); - return NULL; + int one = 1; + setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int)); } - +#endif /* Save the index for later use */ ciptr->index = i; @@ -636,27 +684,25 @@ TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port) { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2, "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketReopenCOTSServer: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); - return NULL; + while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + if ((ciptr = TRANS(SocketReopen) ( + i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) + break; } - - if ((ciptr = TRANS(SocketReopen) ( - i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL) - { - PRMSG (1, - "SocketReopenCOTSServer: Unable to reopen socket for %s\n", - thistrans->TransName, 0, 0); + 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; } @@ -672,27 +718,25 @@ TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port) { XtransConnInfo ciptr; - int i; + int i = -1; PRMSG (2, "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0); SocketInitOnce(); - if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) - { - PRMSG (1, - "SocketReopenCLTSServer: Unable to determine socket type for %s\n", - thistrans->TransName, 0, 0); - return NULL; + while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) { + if ((ciptr = TRANS(SocketReopen) ( + i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL) + break; } - - if ((ciptr = TRANS(SocketReopen) ( - i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL) - { - PRMSG (1, - "SocketReopenCLTSServer: Unable to reopen socket for %s\n", - thistrans->TransName, 0, 0); + 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; } @@ -742,23 +786,31 @@ set_sun_path(const char *port, const char *upath, char *path) static int TRANS(SocketCreateListener) (XtransConnInfo ciptr, - struct sockaddr *sockname, int socknamelen) + struct sockaddr *sockname, + int socknamelen, unsigned int flags) { int namelen = socknamelen; int fd = ciptr->fd; int retry; - PRMSG (3, "SocketCreateListener(%x,%d)\n", ciptr, fd, 0); + PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0); - if (Sockettrans2devtab[ciptr->index].family == AF_INET) + 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 (errno == EADDRINUSE) { + if (flags & ADDR_IN_USE_ALLOWED) + break; + } else return TRANS_ADDR_IN_USE; if (retry-- == 0) { @@ -774,7 +826,11 @@ TRANS(SocketCreateListener) (XtransConnInfo ciptr, #endif /* SO_REUSEDADDR */ } - if (Sockettrans2devtab[ciptr->index].family == AF_INET) { + 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 @@ -804,10 +860,15 @@ TRANS(SocketCreateListener) (XtransConnInfo ciptr, #ifdef TCPCONN static int -TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port) +TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) { - struct sockaddr_in sockname; +#if defined(IPv6) && defined(AF_INET6) + struct sockaddr_storage sockname; +#else + struct sockaddr_in sockname; +#endif + unsigned short sport; int namelen = sizeof(sockname); int status; long tmpport; @@ -855,7 +916,7 @@ TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port) return TRANS_CREATE_LISTENER_FAILED; } /* we trust getservbyname to return a valid number */ - sockname.sin_port = htons (servp->s_port); + sport = servp->s_port; } else { @@ -869,20 +930,42 @@ TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port) if (tmpport < 1024 || tmpport > USHRT_MAX) return TRANS_CREATE_LISTENER_FAILED; - sockname.sin_port = htons (((unsigned short) tmpport)); + sport = (unsigned short) tmpport; } } else - sockname.sin_port = htons (0); + 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)) < 0) + (struct sockaddr *) &sockname, namelen, flags)) < 0) { PRMSG (1, "SocketINETCreateListener: ...SocketCreateListener() failed\n", @@ -907,7 +990,8 @@ TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port) #ifdef UNIXCONN static int -TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port) +TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port, + unsigned int flags) { struct sockaddr_un sockname; @@ -958,7 +1042,7 @@ TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port) unlink (sockname.sun_path); if ((status = TRANS(SocketCreateListener) (ciptr, - (struct sockaddr *) &sockname, namelen)) < 0) + (struct sockaddr *) &sockname, namelen, flags)) < 0) { PRMSG (1, "SocketUNIXCreateListener: ...SocketCreateListener() failed\n", @@ -1008,7 +1092,7 @@ TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr) int status = TRANS_RESET_NOOP; unsigned int mode; - PRMSG (3, "SocketUNIXResetListener(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0); if (stat (unsock->sun_path, &statb) == -1 || ((statb.st_mode & S_IFMT) != @@ -1080,7 +1164,7 @@ TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status) struct sockaddr_in sockname; int namelen = sizeof(sockname); - PRMSG (2, "SocketINETAccept(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0); if ((newciptr = (XtransConnInfo) xcalloc ( 1, sizeof(struct _XtransConnInfo))) == NULL) @@ -1160,7 +1244,7 @@ TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) int namelen = sizeof sockname; #endif - PRMSG (2, "SocketUNIXAccept(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0); if ((newciptr = (XtransConnInfo) xcalloc ( 1, sizeof(struct _XtransConnInfo))) == NULL) @@ -1229,29 +1313,47 @@ TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status) #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_in sockname; -#if defined(SVR4) || defined(SCO325) - size_t namelen = sizeof sockname; + struct sockaddr * socketaddr = NULL; + int socketaddrlen = 0; + int res; +#if defined(IPv6) && defined(AF_INET6) + struct addrinfo hints; + char ntopbuf[INET6_ADDRSTRLEN]; + struct sockaddr_in6 tmpsin6; + int resetonce = 0; #else - int namelen = sizeof sockname; -#endif + struct sockaddr_in sockname; #ifdef XTHREADS_NEEDS_BYNAMEPARAMS _Xgethostbynameparams hparams; _Xgetservbynameparams sparams; #endif struct hostent *hostp; struct servent *servp; - + unsigned long tmpaddr; +#endif #ifdef X11_t char portbuf[PORTBUFSIZE]; #endif +#if defined(X11_t) || !defined(IPv6) || !defined(AF_INET6) long tmpport; - unsigned long tmpaddr; +#endif char hostnamebuf[256]; /* tmp space */ PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); @@ -1281,6 +1383,116 @@ TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port) } #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, + "TRANS(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) { + /* Already checked entire list - no usable addresses */ + PRMSG (1, + "TRANS(SocketINETConnect) () no usable address for %s:%s\n", + host, port, 0); + return TRANS_CONNECT_FAILED; + } else { + /* Go back to beginning of list */ + 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,"TRANS(SocketINETConnect) sockname.sin_addr = %s\n", + inet_ntop(addrlist->addr->ai_family,&sin->sin_addr, + ntopbuf,sizeof(ntopbuf)), 0, 0); + + PRMSG (4,"TRANS(SocketINETConnect) sockname.sin_port = %d\n", + ntohs(sin->sin_port), 0, 0); + + if (Sockettrans2devtab[ciptr->index].family == AF_INET6) { + /* We have IPv6 socket, need to map IPv4 address to IPv6 */ + char *v4addr = (char *) &sin->sin_addr.s_addr; + bzero(&tmpsin6, sizeof(tmpsin6)); +#ifdef SIN6_LEN + tmpsin6.sin6_len = sizeof(tmpsin6); +#endif + tmpsin6.sin6_family = AF_INET6; + tmpsin6.sin6_port = sin->sin_port; + tmpsin6.sin6_addr.s6_addr[10] = 0xff; + tmpsin6.sin6_addr.s6_addr[11] = 0xff; + tmpsin6.sin6_addr.s6_addr[12] = v4addr[0]; + tmpsin6.sin6_addr.s6_addr[13] = v4addr[1]; + tmpsin6.sin6_addr.s6_addr[14] = v4addr[2]; + tmpsin6.sin6_addr.s6_addr[15] = v4addr[3]; + + socketaddr = (struct sockaddr *) &tmpsin6; + socketaddrlen = sizeof(tmpsin6); + PRMSG (4,"TRANS(SocketINETConnect) sockname.sin6_addr = %s\n", + inet_ntop(AF_INET6, &tmpsin6.sin6_addr, ntopbuf, + sizeof(ntopbuf)), 0, 0); + } + } else if (addrlist->addr->ai_family == AF_INET6) { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr; + + PRMSG (4,"TRANS(SocketINETConnect) sockname.sin6_addr = %s\n", + inet_ntop(addrlist->addr->ai_family, &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)), + 0, 0); + PRMSG (4,"TRANS(SocketINETConnect) sockname.sin6_port = %d\n", + ntohs(sin6->sin6_port), 0, 0); + + if (Sockettrans2devtab[ciptr->index].family == AF_INET) { + PRMSG (4,"TRANS(SocketINETConnect) Skipping IPv6 address\n", + 0,0,0); + socketaddr = NULL; + } + } else { + socketaddr = NULL; /* Unsupported address type */ + } + if (socketaddr == NULL) { + addrlist->addr = addrlist->addr->ai_next; + } + } +#else /* * Build the socket name. */ @@ -1305,7 +1517,7 @@ TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port) PRMSG (4,"SocketINETConnect: inet_addr(%s) = %x\n", host, tmpaddr, 0); - if (tmpaddr == -1) + if ((long)tmpaddr == -1L) { if ((hostp = _XGethostbyname(host,hparams)) == NULL) { @@ -1371,6 +1583,9 @@ else PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n", ntohs(sockname.sin_port), 0, 0); + socketaddr = (struct sockaddr *) &sockname; + socketaddrlen = sizeof(sockname); +#endif /* IPv6 */ /* * Turn on socket keepalive so the client process will eventually @@ -1393,7 +1608,7 @@ else * Do the connect() */ - if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) + if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0) { #ifdef WIN32 int olderrno = WSAGetLastError(); @@ -1410,43 +1625,65 @@ else * * If the error was EINTR, the connect was interrupted and we * should try again. + * + * If multiple addresses are found for a host then we should + * try to connect again with a different address for a larger + * number of errors that made us quit before, since those + * could be caused by trying to use an IPv6 address to contact + * a machine with an IPv4-only server or other reasons that + * only affect one of a set of addresses. */ - if (olderrno == ECONNREFUSED || olderrno == EINTR) - return TRANS_TRY_CONNECT_AGAIN; + 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)) +#endif + ) + res = TRANS_TRY_CONNECT_AGAIN; else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS) - return TRANS_IN_PROGRESS; + res = TRANS_IN_PROGRESS; else { PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n", olderrno,0, 0); - return TRANS_CONNECT_FAILED; + res = TRANS_CONNECT_FAILED; } - } + } else { + res = 0; - /* - * Sync up the address fields of ciptr. - */ + /* + * Sync up the address fields of ciptr. + */ - if (TRANS(SocketINETGetAddr) (ciptr) < 0) - { - PRMSG (1, - "SocketINETConnect: ...SocketINETGetAddr() failed:\n", - 0, 0, 0); - return TRANS_CONNECT_FAILED; - } + if (TRANS(SocketINETGetAddr) (ciptr) < 0) + { + PRMSG (1, + "SocketINETConnect: ...SocketINETGetAddr() failed:\n", + 0, 0, 0); + res = TRANS_CONNECT_FAILED; + } - if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) - { - PRMSG (1, - "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n", + else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) + { + PRMSG (1, + "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n", 0, 0, 0); - return TRANS_CONNECT_FAILED; + res = TRANS_CONNECT_FAILED; + } } - return 0; +#if defined(IPv6) && defined(AF_INET6) + if (res != 0) { + addrlist->addr = addrlist->addr->ai_next; + } +#endif + + return res; } #endif /* TCPCONN */ @@ -1473,6 +1710,53 @@ UnixHostReallyLocal (char *host) } 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 /* * A host may have more than one network address. If any of the * network addresses of 'host' (specified to the connect call) @@ -1542,6 +1826,7 @@ UnixHostReallyLocal (char *host) } return (equiv); +#endif } } @@ -1703,7 +1988,7 @@ static int TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) { - PRMSG (2,"SocketBytesReadable(%x,%d,%x)\n", + PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n", ciptr, ciptr->fd, pend); #if defined(QNX4) *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */ @@ -1728,7 +2013,7 @@ static int TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) { - PRMSG (2,"SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size); + PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); #if defined(WIN32) || defined(__UNIXOS2__) return recv ((SOCKET)ciptr->fd, buf, size, 0); @@ -1742,7 +2027,7 @@ static int TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) { - PRMSG (2,"SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size); + PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); #if defined(WIN32) || defined(__UNIXOS2__) return send ((SOCKET)ciptr->fd, buf, size, 0); @@ -1756,7 +2041,7 @@ static int TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) { - PRMSG (2,"SocketReadv(%d,%x,%d)\n", ciptr->fd, buf, size); + PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); return READV (ciptr, buf, size); } @@ -1766,7 +2051,7 @@ static int TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) { - PRMSG (2,"SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size); + PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); return WRITEV (ciptr, buf, size); } @@ -1776,7 +2061,7 @@ static int TRANS(SocketDisconnect) (XtransConnInfo ciptr) { - PRMSG (2,"SocketDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0); return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ } @@ -1787,7 +2072,7 @@ static int TRANS(SocketINETClose) (XtransConnInfo ciptr) { - PRMSG (2,"SocketINETClose(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0); return close (ciptr->fd); } @@ -1809,7 +2094,7 @@ TRANS(SocketUNIXClose) (XtransConnInfo ciptr) char path[200]; /* > sizeof sun_path +1 */ int ret; - PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0); + PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0); ret = close(ciptr->fd); @@ -1837,7 +2122,7 @@ TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) int ret; - PRMSG (2,"SocketUNIXCloseForCloning(%x,%d)\n", + PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n", ciptr, ciptr->fd, 0); ret = close(ciptr->fd); @@ -1849,14 +2134,19 @@ TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) #ifdef TCPCONN +# ifdef TRANS_SERVER +static char* tcp_nolisten[] = { "inet", "inet6", NULL }; +# endif + Xtransport TRANS(SocketTCPFuncs) = { /* Socket Interface */ "tcp", - 0, + TRANS_ALIAS, #ifdef TRANS_CLIENT TRANS(SocketOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + tcp_nolisten, TRANS(SocketOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -1891,11 +2181,12 @@ Xtransport TRANS(SocketTCPFuncs) = { Xtransport TRANS(SocketINETFuncs) = { /* Socket Interface */ "inet", - TRANS_ALIAS, + 0, #ifdef TRANS_CLIENT TRANS(SocketOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(SocketOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -1927,6 +2218,47 @@ Xtransport TRANS(SocketINETFuncs) = { TRANS(SocketINETClose), }; +#if defined(IPv6) && defined(AF_INET6) +Xtransport TRANS(SocketINET6Funcs) = { + /* Socket Interface */ + "inet6", + 0, +#ifdef TRANS_CLIENT + TRANS(SocketOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + NULL, + 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 /* IPv6 */ #endif /* TCPCONN */ #ifdef UNIXCONN @@ -1939,6 +2271,7 @@ Xtransport TRANS(SocketLocalFuncs) = { TRANS(SocketOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(SocketOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -1970,7 +2303,12 @@ Xtransport TRANS(SocketLocalFuncs) = { TRANS(SocketUNIXCloseForCloning), }; #endif /* !LOCALCONN */ - +# ifdef TRANS_SERVER +# if !defined(LOCALCONN) +static char* unix_nolisten[] = { "local" , NULL }; +# endif +# endif + Xtransport TRANS(SocketUNIXFuncs) = { /* Socket Interface */ "unix", @@ -1983,6 +2321,11 @@ Xtransport TRANS(SocketUNIXFuncs) = { TRANS(SocketOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER +#if !defined(LOCALCONN) + unix_nolisten, +#else + NULL, +#endif TRANS(SocketOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT diff --git a/Xtranstli.c b/Xtranstli.c index e189323..9f686c4 100644 --- a/Xtranstli.c +++ b/Xtranstli.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtranstli.c,v 3.11 2002/12/15 01:28:33 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtranstli.c,v 3.13 2003/08/26 15:38:39 tsi Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -751,7 +751,7 @@ TRANS(TLICreateListener)(XtransConnInfo ciptr, struct t_bind *req) static int -TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port) +TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags) { char portbuf[PORTBUFSIZE]; @@ -813,7 +813,7 @@ TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port) static int -TRANS(TLITLICreateListener)(XtransConnInfo ciptr, char *port) +TRANS(TLITLICreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags) { struct t_bind *req; @@ -1306,6 +1306,7 @@ Xtransport TRANS(TLITCPFuncs) = { TRANS(TLIOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(TLIOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -1337,6 +1338,9 @@ Xtransport TRANS(TLITCPFuncs) = { TRANS(TLICloseForCloning), }; +#ifdef TRANS_SERVER +static char * inet_aliases[] = { "tcp", NULL }; +#endif Xtransport TRANS(TLIINETFuncs) = { /* TLI Interface */ "inet", @@ -1345,6 +1349,7 @@ Xtransport TRANS(TLIINETFuncs) = { TRANS(TLIOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + inet_aliases, TRANS(TLIOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT @@ -1384,6 +1389,7 @@ Xtransport TRANS(TLITLIFuncs) = { TRANS(TLIOpenCOTSClient), #endif /* TRANS_CLIENT */ #ifdef TRANS_SERVER + NULL, TRANS(TLIOpenCOTSServer), #endif /* TRANS_SERVER */ #ifdef TRANS_CLIENT diff --git a/Xtransutil.c b/Xtransutil.c index 7130d99..c3757ca 100644 --- a/Xtransutil.c +++ b/Xtransutil.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/Xtransutil.c,v 3.23 2003/02/12 15:01:38 alanh Exp $ */ +/* $XFree86: xc/lib/xtrans/Xtransutil.c,v 3.27 2003/07/18 15:53:24 tsi Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -69,9 +69,10 @@ from The Open Group. * of these values are also defined by the ChangeHost protocol message. */ -#define FamilyInternet 0 +#define FamilyInternet 0 /* IPv4 */ #define FamilyDECnet 1 #define FamilyChaos 2 +#define FamilyInternet6 6 #define FamilyAmoeba 33 #define FamilyLocalHost 252 #define FamilyKrb5Principal 253 @@ -82,7 +83,7 @@ from The Open Group. /* * TRANS(ConvertAddress) converts a sockaddr based address to an * X authorization based address. Some of this is defined as part of - * the ChangeHost protocol. The rest is just doen in a consistent manner. + * the ChangeHost protocol. The rest is just done in a consistent manner. */ int @@ -130,6 +131,42 @@ TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp) } break; } + +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: + { + struct sockaddr_in6 saddr6; + + memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6)); + + if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr)) + { + *familyp=FamilyLocal; + } + else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) { + char *cp = (char *) &saddr6.sin6_addr.s6_addr[12]; + + if ((cp[0] == 127) && (cp[1] == 0) && + (cp[2] == 0) && (cp[3] == 1)) + { + *familyp=FamilyLocal; + } + else + { + *familyp=FamilyInternet; + *addrlenp = sizeof (struct in_addr); + memcpy(*addrp,cp,*addrlenp); + } + } + else + { + *familyp=FamilyInternet6; + *addrlenp=sizeof(saddr6.sin6_addr); + memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr)); + } + break; + } +#endif /* IPv6 */ #endif /* defined(TCPCONN) || defined(STREAMSCONN) */ #if defined(DNETCONN) @@ -147,13 +184,13 @@ TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp) } #endif /* defined(DNETCONN) */ -#if defined(UNIXCONN) || defined(LOCALCONN) +#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) case AF_UNIX: { *familyp=FamilyLocal; break; } -#endif /* defined(UNIXCONN) || defined(LOCALCONN) */ +#endif /* defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN*/ default: @@ -223,7 +260,7 @@ TRANS(GetMyNetworkId) (XtransConnInfo ciptr) switch (family) { -#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) +#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) case AF_UNIX: { struct sockaddr_un *saddr = (struct sockaddr_un *) addr; @@ -233,15 +270,30 @@ TRANS(GetMyNetworkId) (XtransConnInfo ciptr) hostnamebuf, saddr->sun_path); break; } -#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) */ +#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) */ #if defined(TCPCONN) || defined(STREAMSCONN) case AF_INET: +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: +#endif { struct sockaddr_in *saddr = (struct sockaddr_in *) addr; +#if defined(IPv6) && defined(AF_INET6) + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr; +#endif + int portnum; char portnumbuf[10]; - sprintf (portnumbuf, "%d", ntohs (saddr->sin_port)); + +#if defined(IPv6) && defined(AF_INET6) + if (family == AF_INET6) + portnum = ntohs (saddr6->sin6_port); + else +#endif + portnum = ntohs (saddr->sin_port); + + sprintf (portnumbuf, "%d", portnum); networkId = (char *) xalloc (3 + strlen (transName) + strlen (hostnamebuf) + strlen (portnumbuf)); sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf); @@ -273,7 +325,7 @@ TRANS(GetMyNetworkId) (XtransConnInfo ciptr) static jmp_buf env; #ifdef SIGALRM -static int nameserver_timedout = 0; +static volatile int nameserver_timedout = 0; static #ifdef SIGNALRETURNSINT @@ -301,29 +353,50 @@ TRANS(GetPeerNetworkId) (XtransConnInfo ciptr) char *peer_addr = ciptr->peeraddr; char *hostname; char addrbuf[256]; - char *addr = NULL; + const char *addr = NULL; switch (family) { case AF_UNSPEC: -#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) +#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) case AF_UNIX: { if (gethostname (addrbuf, sizeof (addrbuf)) == 0) addr = addrbuf; break; } -#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) */ +#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) */ #if defined(TCPCONN) || defined(STREAMSCONN) case AF_INET: +#if defined(IPv6) && defined(AF_INET6) + case AF_INET6: +#endif { struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr; +#if defined(IPv6) && defined(AF_INET6) + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr; +#endif + char *address; + int addresslen; #ifdef XTHREADS_NEEDS_BYNAMEPARAMS _Xgethostbynameparams hparams; #endif struct hostent * volatile hostp = NULL; +#if defined(IPv6) && defined(AF_INET6) + if (family == AF_INET6) + { + address = (char *) &saddr6->sin6_addr; + addresslen = sizeof (saddr6->sin6_addr); + } + else +#endif + { + address = (char *) &saddr->sin_addr; + addresslen = sizeof (saddr->sin_addr); + } + #ifdef SIGALRM /* * gethostbyaddr can take a LONG time if the host does not exist. @@ -338,8 +411,7 @@ TRANS(GetPeerNetworkId) (XtransConnInfo ciptr) alarm (4); if (setjmp(env) == 0) { #endif - hostp = _XGethostbyaddr ((char *) &saddr->sin_addr, - sizeof (saddr->sin_addr), AF_INET, hparams); + hostp = _XGethostbyaddr (address, addresslen, family, hparams); #ifdef SIGALRM } alarm (0); @@ -347,7 +419,11 @@ TRANS(GetPeerNetworkId) (XtransConnInfo ciptr) if (hostp != NULL) addr = hostp->h_name; else +#if defined(IPv6) && defined(AF_INET6) + addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf)); +#else addr = inet_ntoa (saddr->sin_addr); +#endif break; } @@ -497,14 +573,14 @@ trans_mkdir(char *path, int mode) if (updateOwner && !updatedOwner) { PRMSG(1, "mkdir: Owner of %s should be set to root\n", path, 0, 0); -#if !defined(__CYGWIN__) +#if !defined(__CYGWIN__) && !defined(__DARWIN__) sleep(5); #endif } if (updateMode && !updatedMode) { PRMSG(1, "mkdir: Mode of %s should be set to %04o\n", path, mode, 0); -#if !defined(__CYGWIN__) +#if !defined(__CYGWIN__) && !defined(__DARWIN__) sleep(5); #endif } diff --git a/transport.c b/transport.c index 3cc7149..e00a82a 100644 --- a/transport.c +++ b/transport.c @@ -26,7 +26,7 @@ other dealings in this Software without prior written authorization from The Open Group. */ -/* $XFree86: xc/lib/xtrans/transport.c,v 3.9 2002/05/31 18:45:51 dawes Exp $ */ +/* $XFree86: xc/lib/xtrans/transport.c,v 3.10 2003/03/25 04:18:15 dawes Exp $ */ /* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA * @@ -51,6 +51,10 @@ from The Open Group. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifdef __UNIXOS2__ +#define I_NEED_OS2_H +#endif + #ifdef XSERV_t #include "os.h" #else @@ -69,6 +73,9 @@ from The Open Group. #ifdef LOCALCONN #include "Xtranslcl.c" #endif +#ifdef OS2PIPECONN +#include "Xtransos2.c" +#endif #if defined(TCPCONN) || defined(UNIXCONN) #include "Xtranssock.c" #endif |