Xtranssock.c
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:59k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2. Copyright 1993, 1994, 1998  The Open Group
  3. Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
  4. Permission to use, copy, modify, distribute, and sell this software and its
  5. documentation for any purpose is hereby granted without fee, provided that
  6. the above copyright notice appear in all copies and that both that
  7. copyright notice and this permission notice appear in supporting
  8. documentation.
  9. The above copyright notice and this permission notice shall be included
  10. in all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  12. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  13. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  14. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  15. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  16. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  17. OTHER DEALINGS IN THE SOFTWARE.
  18. Except as contained in this notice, the name of the copyright holders shall
  19. not be used in advertising or otherwise to promote the sale, use or
  20. other dealings in this Software without prior written authorization
  21. from the copyright holders.
  22.  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
  23.  *
  24.  * All Rights Reserved
  25.  *
  26.  * Permission to use, copy, modify, and distribute this software and its
  27.  * documentation for any purpose and without fee is hereby granted, provided
  28.  * that the above copyright notice appear in all copies and that both that
  29.  * copyright notice and this permission notice appear in supporting
  30.  * documentation, and that the name NCR not be used in advertising
  31.  * or publicity pertaining to distribution of the software without specific,
  32.  * written prior permission.  NCR makes no representations about the
  33.  * suitability of this software for any purpose.  It is provided "as is"
  34.  * without express or implied warranty.
  35.  *
  36.  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  37.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  38.  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  39.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  40.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  41.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  42.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  43.  */
  44. #include <ctype.h>
  45. #ifdef XTHREADS
  46. #include <X11/Xthreads.h>
  47. #endif
  48. #ifndef WIN32
  49. #if defined(TCPCONN) || defined(UNIXCONN)
  50. #include <sys/socket.h>
  51. #include <netinet/in.h>
  52. #include <arpa/inet.h>
  53. #endif
  54. #if defined(TCPCONN) || defined(UNIXCONN)
  55. #define X_INCLUDE_NETDB_H
  56. #define XOS_USE_NO_LOCKING
  57. #include <X11/Xos_r.h>
  58. #endif
  59. #ifdef UNIXCONN
  60. #ifndef X_NO_SYS_UN
  61. #include <sys/un.h>
  62. #endif
  63. #include <sys/stat.h>
  64. #endif
  65. #ifndef NO_TCP_H
  66. #if defined(linux) || defined(__GLIBC__) 
  67. #include <sys/param.h>
  68. #endif /* osf */
  69. #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
  70. #include <sys/param.h>
  71. #include <machine/endian.h>
  72. #endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
  73. #include <netinet/tcp.h>
  74. #endif /* !NO_TCP_H */
  75. #include <sys/ioctl.h>
  76. #if defined(SVR4) 
  77. #include <sys/filio.h>
  78. #endif
  79. #if (defined(__i386__) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
  80. #include <net/errno.h>
  81. #endif 
  82. #if defined(__i386__) && defined(SYSV) 
  83. #include <sys/stropts.h>
  84. #endif 
  85. #include <unistd.h>
  86. #else /* !WIN32 */
  87. #include <X11/Xwinsock.h>
  88. #include <X11/Xwindows.h>
  89. #include <X11/Xw32defs.h>
  90. #undef close
  91. #define close closesocket
  92. #define ECONNREFUSED WSAECONNREFUSED
  93. #define EADDRINUSE WSAEADDRINUSE
  94. #define EPROTOTYPE WSAEPROTOTYPE
  95. #undef EWOULDBLOCK
  96. #define EWOULDBLOCK WSAEWOULDBLOCK
  97. #define EINPROGRESS WSAEINPROGRESS
  98. #undef EINTR
  99. #define EINTR WSAEINTR
  100. #define X_INCLUDE_NETDB_H
  101. #define XOS_USE_MTSAFE_NETDBAPI
  102. #include <X11/Xos_r.h>
  103. #endif /* WIN32 */
  104. #if defined(SO_DONTLINGER) && defined(SO_LINGER)
  105. #undef SO_DONTLINGER
  106. #endif
  107. /* others don't need this */
  108. #define SocketInitOnce() /**/
  109. #ifdef linux
  110. #define HAVE_ABSTRACT_SOCKETS
  111. #endif
  112. #define MIN_BACKLOG 128
  113. #ifdef SOMAXCONN
  114. #if SOMAXCONN > MIN_BACKLOG
  115. #define BACKLOG SOMAXCONN
  116. #endif
  117. #endif
  118. #ifndef BACKLOG
  119. #define BACKLOG MIN_BACKLOG
  120. #endif
  121. /*
  122.  * This is the Socket implementation of the X Transport service layer
  123.  *
  124.  * This file contains the implementation for both the UNIX and INET domains,
  125.  * and can be built for either one, or both.
  126.  *
  127.  */
  128. typedef struct _Sockettrans2dev {      
  129.     char *transname;
  130.     int family;
  131.     int devcotsname;
  132.     int devcltsname;
  133.     int protocol;
  134. } Sockettrans2dev;
  135. static Sockettrans2dev Sockettrans2devtab[] = {
  136. #ifdef TCPCONN
  137.     {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
  138. #if !defined(IPv6) || !defined(AF_INET6)
  139.     {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
  140. #else /* IPv6 */
  141.     {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
  142.     {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
  143.     {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
  144. #endif
  145. #endif /* TCPCONN */
  146. #ifdef UNIXCONN
  147.     {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
  148. #if !defined(LOCALCONN)
  149.     {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
  150. #endif /* !LOCALCONN */
  151. #endif /* UNIXCONN */
  152. };
  153. #define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
  154. #ifdef TCPCONN
  155. static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
  156. #endif
  157. #ifdef UNIXCONN
  158. #if defined(X11_t)
  159. #define UNIX_PATH "/tmp/.X11-unix/X"
  160. #define UNIX_DIR "/tmp/.X11-unix"
  161. #endif /* X11_t */
  162. #if defined(XIM_t)
  163. #define UNIX_PATH "/tmp/.XIM-unix/XIM"
  164. #define UNIX_DIR "/tmp/.XIM-unix"
  165. #endif /* XIM_t */
  166. #if defined(FS_t) || defined(FONT_t)
  167. #define UNIX_PATH "/tmp/.font-unix/fs"
  168. #define UNIX_DIR "/tmp/.font-unix"
  169. #endif /* FS_t || FONT_t */
  170. #if defined(ICE_t)
  171. #define UNIX_PATH "/tmp/.ICE-unix/"
  172. #define UNIX_DIR "/tmp/.ICE-unix"
  173. #endif /* ICE_t */
  174. #if defined(TEST_t)
  175. #define UNIX_PATH "/tmp/.Test-unix/test"
  176. #define UNIX_DIR "/tmp/.Test-unix"
  177. #endif
  178. #if defined(LBXPROXY_t)
  179. #define UNIX_PATH "/tmp/.X11-unix/X"
  180. #define UNIX_DIR  "/tmp/.X11-unix"
  181. #endif
  182. #endif /* UNIXCONN */
  183. #define PORTBUFSIZE 32
  184. #ifndef MAXHOSTNAMELEN
  185. #define MAXHOSTNAMELEN 255
  186. #endif
  187. #if defined HAVE_SOCKLEN_T || (defined(IPv6) && defined(AF_INET6))
  188. # define SOCKLEN_T socklen_t
  189. #elif defined(SVR4) || defined(__SCO__)
  190. # define SOCKLEN_T size_t 
  191. #else
  192. # define SOCKLEN_T int
  193. #endif
  194. /*
  195.  * This provides compatibility for apps linked against system libraries
  196.  * that don't have IPv6 support.
  197.  */
  198. #if defined(IPv6) && defined(AF_INET6)
  199. static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
  200. #pragma weak in6addr_any = local_in6addr_any
  201. #ifndef __USLC__
  202. #pragma weak getaddrinfo
  203. #endif
  204. static int haveIPv6 = 1;
  205. #endif
  206. /*
  207.  * These are some utility function used by the real interface function below.
  208.  */
  209. static int
  210. TRANS(SocketSelectFamily) (int first, char *family)
  211. {
  212.     int     i;
  213.     PRMSG (3,"SocketSelectFamily(%s)n", family, 0, 0);
  214.     for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
  215.     {
  216.         if (!strcmp (family, Sockettrans2devtab[i].transname))
  217.     return i;
  218.     }
  219.     return (first == -1 ? -2 : -1);
  220. }
  221. /*
  222.  * This function gets the local address of the socket and stores it in the
  223.  * XtransConnInfo structure for the connection.
  224.  */
  225. static int
  226. TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
  227. {
  228. #if defined(IPv6) && defined(AF_INET6)
  229.     struct sockaddr_storage socknamev6;
  230. #endif
  231.     struct sockaddr_in socknamev4;
  232.     void *socknamePtr;
  233.     SOCKLEN_T namelen;
  234.     PRMSG (3,"SocketINETGetAddr(%p)n", ciptr, 0, 0);
  235. #if defined(IPv6) && defined(AF_INET6)
  236.     if (haveIPv6)
  237.     {
  238. namelen = sizeof(socknamev6);
  239. socknamePtr = &socknamev6;
  240.     }
  241.     else
  242. #endif
  243.     {
  244. namelen = sizeof(socknamev4);
  245. socknamePtr = &socknamev4;
  246.     }
  247.     bzero(socknamePtr, namelen);
  248.     
  249.     if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
  250.      (void *)&namelen) < 0)
  251.     {
  252. #ifdef WIN32
  253. errno = WSAGetLastError();
  254. #endif
  255. PRMSG (1,"SocketINETGetAddr: getsockname() failed: %dn",
  256.     EGET(),0, 0);
  257. return -1;
  258.     }
  259.     /*
  260.      * Everything looks good: fill in the XtransConnInfo structure.
  261.      */
  262.     if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
  263.     {
  264.         PRMSG (1,
  265.     "SocketINETGetAddr: Can't allocate space for the addrn",
  266.     0, 0, 0);
  267.         return -1;
  268.     }
  269. #if defined(IPv6) && defined(AF_INET6)
  270.     if (haveIPv6)
  271.     {
  272. ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
  273.     }
  274.     else
  275. #endif
  276.     {
  277. ciptr->family = socknamev4.sin_family;
  278.     }
  279.     ciptr->addrlen = namelen;
  280.     memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
  281.     return 0;
  282. }
  283. /*
  284.  * This function gets the remote address of the socket and stores it in the
  285.  * XtransConnInfo structure for the connection.
  286.  */
  287. static int
  288. TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
  289. {
  290. #if defined(IPv6) && defined(AF_INET6)
  291.     struct sockaddr_storage socknamev6;
  292. #endif
  293.     struct sockaddr_in  socknamev4;
  294.     void *socknamePtr;
  295.     SOCKLEN_T namelen;
  296. #if defined(IPv6) && defined(AF_INET6)
  297.     if (haveIPv6 && ciptr->family == AF_INET6)
  298.     {
  299. namelen = sizeof(socknamev6);
  300. socknamePtr = &socknamev6;
  301.     }
  302.     else
  303. #endif
  304.     {
  305. namelen = sizeof(socknamev4);
  306. socknamePtr = &socknamev4;
  307.     }
  308.     bzero(socknamePtr, namelen);
  309.     
  310.     PRMSG (3,"SocketINETGetPeerAddr(%p)n", ciptr, 0, 0);
  311.     if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
  312.      (void *)&namelen) < 0)
  313.     {
  314. #ifdef WIN32
  315. errno = WSAGetLastError();
  316. #endif
  317. PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %dn",
  318.     EGET(), 0, 0);
  319. return -1;
  320.     }
  321.     /*
  322.      * Everything looks good: fill in the XtransConnInfo structure.
  323.      */
  324.     if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
  325.     {
  326.         PRMSG (1,
  327.    "SocketINETGetPeerAddr: Can't allocate space for the addrn",
  328.    0, 0, 0);
  329.         return -1;
  330.     }
  331.     ciptr->peeraddrlen = namelen;
  332.     memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
  333.     return 0;
  334. }
  335. static XtransConnInfo
  336. TRANS(SocketOpen) (int i, int type)
  337. {
  338.     XtransConnInfo ciptr;
  339.     PRMSG (3,"SocketOpen(%d,%d)n", i, type, 0);
  340. #if defined(IPv6) && defined(AF_INET6)
  341.     if (getaddrinfo == NULL)
  342. haveIPv6 = 0;
  343.     if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
  344. return NULL;
  345. #endif
  346.     if ((ciptr = (XtransConnInfo) xcalloc (
  347. 1, sizeof(struct _XtransConnInfo))) == NULL)
  348.     {
  349. PRMSG (1, "SocketOpen: malloc failedn", 0, 0, 0);
  350. return NULL;
  351.     }
  352.     if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
  353. Sockettrans2devtab[i].protocol)) < 0
  354. #ifndef WIN32
  355. #if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
  356.        || ciptr->fd >= sysconf(_SC_OPEN_MAX)
  357. #endif
  358. #endif
  359.       ) {
  360. #ifdef WIN32
  361. errno = WSAGetLastError();
  362. #endif
  363. PRMSG (2, "SocketOpen: socket() failed for %sn",
  364.     Sockettrans2devtab[i].transname, 0, 0);
  365. xfree ((char *) ciptr);
  366. return NULL;
  367.     }
  368. #ifdef TCP_NODELAY
  369.     if (Sockettrans2devtab[i].family == AF_INET
  370. #if defined(IPv6) && defined(AF_INET6)
  371.       || Sockettrans2devtab[i].family == AF_INET6
  372. #endif
  373.     )
  374.     {
  375. /*
  376.  * turn off TCP coalescence for INET sockets
  377.  */
  378. int tmp = 1;
  379. setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
  380.     (char *) &tmp, sizeof (int));
  381.     }
  382. #endif
  383.     return ciptr;
  384. }
  385. #ifdef TRANS_REOPEN
  386. static XtransConnInfo
  387. TRANS(SocketReopen) (int i, int type, int fd, char *port)
  388. {
  389.     XtransConnInfo ciptr;
  390.     int portlen;
  391.     struct sockaddr *addr;
  392.     PRMSG (3,"SocketReopen(%d,%d,%s)n", type, fd, port);
  393.     if (port == NULL) {
  394.       PRMSG (1, "SocketReopen: port was null!n", 0, 0, 0);
  395.       return NULL;
  396.     }
  397.     portlen = strlen(port) + 1; // include space for trailing null
  398. #ifdef SOCK_MAXADDRLEN
  399.     if (portlen < 0 || portlen > (SOCK_MAXADDRLEN + 2)) {
  400.       PRMSG (1, "SocketReopen: invalid portlen %dn", portlen, 0, 0);
  401.       return NULL;
  402.     }
  403.     if (portlen < 14) portlen = 14;
  404. #else
  405.     if (portlen < 0 || portlen > 14) {
  406.       PRMSG (1, "SocketReopen: invalid portlen %dn", portlen, 0, 0);
  407.       return NULL;
  408.     }
  409. #endif /*SOCK_MAXADDRLEN*/
  410.     if ((ciptr = (XtransConnInfo) xcalloc (
  411. 1, sizeof(struct _XtransConnInfo))) == NULL)
  412.     {
  413. PRMSG (1, "SocketReopen: malloc(ciptr) failedn", 0, 0, 0);
  414. return NULL;
  415.     }
  416.     ciptr->fd = fd;
  417.     if ((addr = (struct sockaddr *) xcalloc (1, portlen + 2)) == NULL) {
  418. PRMSG (1, "SocketReopen: malloc(addr) failedn", 0, 0, 0);
  419. return NULL;
  420.     }
  421.     ciptr->addr = (char *) addr;
  422.     ciptr->addrlen = portlen + 2;
  423.     if ((ciptr->peeraddr = (char *) xcalloc (1, portlen + 2)) == NULL) {
  424. PRMSG (1, "SocketReopen: malloc(portaddr) failedn", 0, 0, 0);
  425. return NULL;
  426.     }
  427.     ciptr->peeraddrlen = portlen + 2;
  428.     /* Initialize ciptr structure as if it were a normally-opened unix socket */
  429.     ciptr->flags = TRANS_LOCAL | TRANS_NOUNLINK;
  430. #ifdef BSD44SOCKETS
  431.     addr->sa_len = portlen + 1;
  432. #endif
  433.     addr->sa_family = AF_UNIX;
  434. #ifdef HAS_STRLCPY
  435.     strlcpy(addr->sa_data, port, portlen);
  436. #else
  437.     strncpy(addr->sa_data, port, portlen);
  438. #endif
  439.     ciptr->family = AF_UNIX;
  440.     memcpy(ciptr->peeraddr, ciptr->addr, sizeof(struct sockaddr));
  441.     ciptr->port = rindex(addr->sa_data, ':');
  442.     if (ciptr->port[0] == ':') ciptr->port++; /* port should now point to portnum or NULL */
  443.     return ciptr;
  444. }
  445. #endif /* TRANS_REOPEN */
  446. /*
  447.  * These functions are the interface supplied in the Xtransport structure
  448.  */
  449. #ifdef TRANS_CLIENT
  450. static XtransConnInfo
  451. TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
  452. char *host, char *port, int previndex)
  453. {
  454.     XtransConnInfo ciptr;
  455.     int i = previndex;
  456.     PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)n",
  457. protocol, host, port);
  458.     SocketInitOnce();
  459.     while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
  460. if ((ciptr = TRANS(SocketOpen) (
  461.  i, Sockettrans2devtab[i].devcotsname)) != NULL)
  462.     break;
  463.     }
  464.     if (i < 0) {
  465. if (i == -1)
  466.     PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %sn",
  467.    transname, 0, 0);
  468. else
  469.     PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %sn",
  470.    transname, 0, 0);
  471. return NULL;
  472.     }
  473.     /* Save the index for later use */
  474.     ciptr->index = i;
  475.     return ciptr;
  476. }
  477. static XtransConnInfo
  478. TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol, 
  479.      char *host, char *port)
  480. {
  481.     return TRANS(SocketOpenCOTSClientBase)(
  482. thistrans->TransName, protocol, host, port, -1);
  483. }
  484. #endif /* TRANS_CLIENT */
  485. #ifdef TRANS_SERVER
  486. static XtransConnInfo
  487. TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol, 
  488.      char *host, char *port)
  489. {
  490.     XtransConnInfo ciptr;
  491.     int i = -1;
  492.     PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)n", protocol, host, port);
  493.     SocketInitOnce();
  494.     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
  495. if ((ciptr = TRANS(SocketOpen) (
  496.  i, Sockettrans2devtab[i].devcotsname)) != NULL)
  497.     break;
  498.     }
  499.     if (i < 0) {
  500. if (i == -1)
  501.     PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %sn",
  502.    thistrans->TransName, 0, 0);
  503. else
  504.     PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %sn",
  505.    thistrans->TransName, 0, 0);
  506. return NULL;
  507.     }
  508.     /*
  509.      * Using this prevents the bind() check for an existing server listening
  510.      * on the same port, but it is required for other reasons.
  511.      */
  512. #ifdef SO_REUSEADDR
  513.     /*
  514.      * SO_REUSEADDR only applied to AF_INET && AF_INET6
  515.      */
  516.     if (Sockettrans2devtab[i].family == AF_INET
  517. #if defined(IPv6) && defined(AF_INET6)
  518.       || Sockettrans2devtab[i].family == AF_INET6
  519. #endif
  520.     )
  521.     {
  522. int one = 1;
  523. setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
  524.     (char *) &one, sizeof (int));
  525.     }
  526. #endif
  527. #ifdef IPV6_V6ONLY
  528.     if (Sockettrans2devtab[i].family == AF_INET6)
  529.     {
  530. int one = 1;
  531. setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
  532.     }
  533. #endif
  534.     /* Save the index for later use */
  535.     ciptr->index = i;
  536.     return ciptr;
  537. }
  538. #endif /* TRANS_SERVER */
  539. #ifdef TRANS_CLIENT
  540. static XtransConnInfo
  541. TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol, 
  542.      char *host, char *port)
  543. {
  544.     XtransConnInfo ciptr;
  545.     int i = -1;
  546.     PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)n", protocol, host, port);
  547.     SocketInitOnce();
  548.     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
  549. if ((ciptr = TRANS(SocketOpen) (
  550.  i, Sockettrans2devtab[i].devcotsname)) != NULL)
  551.     break;
  552.     }
  553.     if (i < 0) {
  554. if (i == -1)
  555.     PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %sn",
  556.    thistrans->TransName, 0, 0);
  557. else
  558.     PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %sn",
  559.    thistrans->TransName, 0, 0);
  560. return NULL;
  561.     }
  562.     /* Save the index for later use */
  563.     ciptr->index = i;
  564.     return ciptr;
  565. }
  566. #endif /* TRANS_CLIENT */
  567. #ifdef TRANS_SERVER
  568. static XtransConnInfo
  569. TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol, 
  570.      char *host, char *port)
  571. {
  572.     XtransConnInfo ciptr;
  573.     int i = -1;
  574.     PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)n", protocol, host, port);
  575.     SocketInitOnce();
  576.     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
  577. if ((ciptr = TRANS(SocketOpen) (
  578.  i, Sockettrans2devtab[i].devcotsname)) != NULL)
  579.     break;
  580.     }
  581.     if (i < 0) {
  582. if (i == -1)
  583.     PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %sn",
  584.    thistrans->TransName, 0, 0);
  585. else
  586.     PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %sn",
  587.    thistrans->TransName, 0, 0);
  588. return NULL;
  589.     }
  590. #ifdef IPV6_V6ONLY
  591.     if (Sockettrans2devtab[i].family == AF_INET6)
  592.     {
  593. int one = 1;
  594. setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
  595.     }
  596. #endif
  597.     /* Save the index for later use */
  598.     ciptr->index = i;
  599.     return ciptr;
  600. }
  601. #endif /* TRANS_SERVER */
  602. #ifdef TRANS_REOPEN
  603. static XtransConnInfo
  604. TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
  605. {
  606.     XtransConnInfo ciptr;
  607.     int i = -1;
  608.     PRMSG (2,
  609. "SocketReopenCOTSServer(%d, %s)n", fd, port, 0);
  610.     SocketInitOnce();
  611.     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
  612. if ((ciptr = TRANS(SocketReopen) (
  613.  i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
  614.     break;
  615.     }
  616.     if (i < 0) {
  617. if (i == -1)
  618.     PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %sn",
  619.    thistrans->TransName, 0, 0);
  620. else
  621.     PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %sn",
  622.    thistrans->TransName, 0, 0);
  623. return NULL;
  624.     }
  625.     /* Save the index for later use */
  626.     ciptr->index = i;
  627.     return ciptr;
  628. }
  629. static XtransConnInfo
  630. TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
  631. {
  632.     XtransConnInfo ciptr;
  633.     int i = -1;
  634.     PRMSG (2,
  635. "SocketReopenCLTSServer(%d, %s)n", fd, port, 0);
  636.     SocketInitOnce();
  637.     while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
  638. if ((ciptr = TRANS(SocketReopen) (
  639.  i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
  640.     break;
  641.     }
  642.     if (i < 0) {
  643. if (i == -1)
  644.     PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %sn",
  645.    thistrans->TransName, 0, 0);
  646. else
  647.     PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %sn",
  648.    thistrans->TransName, 0, 0);
  649. return NULL;
  650.     }
  651.     /* Save the index for later use */
  652.     ciptr->index = i;
  653.     return ciptr;
  654. }
  655. #endif /* TRANS_REOPEN */
  656. static int
  657. TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
  658. {
  659.     PRMSG (2,"SocketSetOption(%d,%d,%d)n", ciptr->fd, option, arg);
  660.     return -1;
  661. }
  662. #ifdef UNIXCONN
  663. static int
  664. set_sun_path(const char *port, const char *upath, char *path, int abstract)
  665. {
  666.     struct sockaddr_un s;
  667.     int maxlen = sizeof(s.sun_path) - 1;
  668.     const char *at = "";
  669.     if (!port || !*port || !path)
  670. return -1;
  671. #ifdef HAVE_ABSTRACT_SOCKETS
  672.     if (port[0] == '@')
  673. upath = "";
  674.     else if (abstract)
  675. at = "@";
  676. #endif
  677.     if (*port == '/') /* a full pathname */
  678. upath = "";
  679.     if (strlen(port) + strlen(upath) > maxlen)
  680. return -1;
  681.     sprintf(path, "%s%s%s", at, upath, port);
  682.     return 0;
  683. }
  684. #endif
  685. #ifdef TRANS_SERVER
  686. static int
  687. TRANS(SocketCreateListener) (XtransConnInfo ciptr, 
  688.      struct sockaddr *sockname,
  689.      int socknamelen, unsigned int flags)
  690. {
  691.     SOCKLEN_T namelen = socknamelen;
  692.     int fd = ciptr->fd;
  693.     int retry;
  694.     PRMSG (3, "SocketCreateListener(%x,%p)n", ciptr, fd, 0);
  695.     if (Sockettrans2devtab[ciptr->index].family == AF_INET
  696. #if defined(IPv6) && defined(AF_INET6)
  697.       || Sockettrans2devtab[ciptr->index].family == AF_INET6
  698. #endif
  699. )
  700. retry = 20;
  701.     else
  702. retry = 0;
  703.     while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
  704.     {
  705. if (errno == EADDRINUSE) {
  706.     if (flags & ADDR_IN_USE_ALLOWED)
  707. break;
  708.     else
  709. return TRANS_ADDR_IN_USE;
  710. }
  711. if (retry-- == 0) {
  712.     PRMSG (1, "SocketCreateListener: failed to bind listenern",
  713. 0, 0, 0);
  714.     close (fd);
  715.     return TRANS_CREATE_LISTENER_FAILED;
  716. }
  717. #ifdef SO_REUSEADDR
  718. sleep (1);
  719. #else
  720. sleep (10);
  721. #endif /* SO_REUSEDADDR */
  722.     }
  723.     if (Sockettrans2devtab[ciptr->index].family == AF_INET
  724. #if defined(IPv6) && defined(AF_INET6)
  725.       || Sockettrans2devtab[ciptr->index].family == AF_INET6
  726. #endif
  727. ) {
  728. #ifdef SO_DONTLINGER
  729. setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
  730. #else
  731. #ifdef SO_LINGER
  732.     {
  733. static int linger[2] = { 0, 0 };
  734. setsockopt (fd, SOL_SOCKET, SO_LINGER,
  735. (char *) linger, sizeof (linger));
  736.     }
  737. #endif
  738. #endif
  739. }
  740.     if (listen (fd, BACKLOG) < 0)
  741.     {
  742. PRMSG (1, "SocketCreateListener: listen() failedn", 0, 0, 0);
  743. close (fd);
  744. return TRANS_CREATE_LISTENER_FAILED;
  745.     }
  746.     /* Set a flag to indicate that this connection is a listener */
  747.     ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
  748.     return 0;
  749. }
  750. #ifdef TCPCONN
  751. static int
  752. TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
  753. {
  754. #if defined(IPv6) && defined(AF_INET6)
  755.     struct sockaddr_storage sockname;
  756. #else
  757.     struct sockaddr_in     sockname;
  758. #endif
  759.     unsigned short     sport;
  760.     SOCKLEN_T namelen = sizeof(sockname);
  761.     int status;
  762.     long tmpport;
  763. #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
  764.     _Xgetservbynameparams sparams;
  765. #endif
  766.     struct servent *servp;
  767. #ifdef X11_t
  768.     char portbuf[PORTBUFSIZE];
  769. #endif
  770.     
  771.     PRMSG (2, "SocketINETCreateListener(%s)n", port, 0, 0);
  772. #ifdef X11_t
  773.     /*
  774.      * X has a well known port, that is transport dependent. It is easier
  775.      * to handle it here, than try and come up with a transport independent
  776.      * representation that can be passed in and resolved the usual way.
  777.      *
  778.      * The port that is passed here is really a string containing the idisplay
  779.      * from ConnectDisplay().
  780.      */
  781.     if (is_numeric (port))
  782.     {
  783. /* fixup the server port address */
  784. tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
  785. sprintf (portbuf,"%lu", tmpport);
  786. port = portbuf;
  787.     }
  788. #endif
  789.     if (port && *port)
  790.     {
  791. /* Check to see if the port string is just a number (handles X11) */
  792. if (!is_numeric (port))
  793. {
  794.     if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
  795.     {
  796. PRMSG (1,
  797.      "SocketINETCreateListener: Unable to get service for %sn",
  798.       port, 0, 0);
  799. return TRANS_CREATE_LISTENER_FAILED;
  800.     }
  801.     /* we trust getservbyname to return a valid number */
  802.     sport = servp->s_port;
  803. }
  804. else
  805. {
  806.     tmpport = strtol (port, (char**)NULL, 10);
  807.     /* 
  808.      * check that somehow the port address isn't negative or in
  809.      * the range of reserved port addresses. This can happen and
  810.      * be very bad if the server is suid-root and the user does 
  811.      * something (dumb) like `X :60049`. 
  812.      */
  813.     if (tmpport < 1024 || tmpport > USHRT_MAX)
  814. return TRANS_CREATE_LISTENER_FAILED;
  815.     sport = (unsigned short) tmpport;
  816. }
  817.     }
  818.     else
  819. sport = 0;
  820.     bzero(&sockname, sizeof(sockname));
  821. #if defined(IPv6) && defined(AF_INET6)
  822.     if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
  823. namelen = sizeof (struct sockaddr_in);
  824. #ifdef BSD44SOCKETS
  825. ((struct sockaddr_in *)&sockname)->sin_len = namelen;
  826. #endif
  827. ((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
  828. ((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
  829. ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
  830.     } else {
  831. namelen = sizeof (struct sockaddr_in6);
  832. #ifdef SIN6_LEN
  833. ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
  834. #endif
  835. ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
  836. ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
  837. ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
  838.     }
  839. #else
  840. #ifdef BSD44SOCKETS
  841.     sockname.sin_len = sizeof (sockname);
  842. #endif
  843.     sockname.sin_family = AF_INET;
  844.     sockname.sin_port = htons (sport);
  845.     sockname.sin_addr.s_addr = htonl (INADDR_ANY);
  846. #endif
  847.     if ((status = TRANS(SocketCreateListener) (ciptr,
  848. (struct sockaddr *) &sockname, namelen, flags)) < 0)
  849.     {
  850. PRMSG (1,
  851.     "SocketINETCreateListener: ...SocketCreateListener() failedn",
  852.     0, 0, 0);
  853. return status;
  854.     }
  855.     if (TRANS(SocketINETGetAddr) (ciptr) < 0)
  856.     {
  857. PRMSG (1,
  858.        "SocketINETCreateListener: ...SocketINETGetAddr() failedn",
  859.     0, 0, 0);
  860. return TRANS_CREATE_LISTENER_FAILED;
  861.     }
  862.     return 0;
  863. }
  864. #endif /* TCPCONN */
  865. #ifdef UNIXCONN
  866. static int
  867. TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
  868.  unsigned int flags)
  869. {
  870.     struct sockaddr_un sockname;
  871.     int namelen;
  872.     int oldUmask;
  873.     int status;
  874.     unsigned int mode;
  875.     char tmpport[108];
  876.     int abstract = 0;
  877. #ifdef HAVE_ABSTRACT_SOCKETS
  878.     abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
  879. #endif
  880.     PRMSG (2, "SocketUNIXCreateListener(%s)n",
  881. port ? port : "NULL", 0, 0);
  882.     /* Make sure the directory is created */
  883.     oldUmask = umask (0);
  884. #ifdef UNIX_DIR
  885. #ifdef HAS_STICKY_DIR_BIT
  886.     mode = 01777;
  887. #else
  888.     mode = 0777;
  889. #endif
  890.     if (!abstract && trans_mkdir(UNIX_DIR, mode) == -1) {
  891. PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %dn",
  892.        UNIX_DIR, errno, 0);
  893. (void) umask (oldUmask);
  894. return TRANS_CREATE_LISTENER_FAILED;
  895.     }
  896. #endif
  897.     memset(&sockname, 0, sizeof(sockname));
  898.     sockname.sun_family = AF_UNIX;
  899.     if (!(port && *port)) {
  900. snprintf (tmpport, sizeof(tmpport), "%s%ld", UNIX_PATH, (long)getpid());
  901. port = tmpport;
  902.     }
  903.     if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
  904. PRMSG (1, "SocketUNIXCreateListener: path too longn", 0, 0, 0);
  905. return TRANS_CREATE_LISTENER_FAILED;
  906.     }
  907. #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 
  908.     sockname.sun_len = strlen(sockname.sun_path);
  909. #endif
  910. #if defined(BSD44SOCKETS) || defined(SUN_LEN)
  911.     namelen = SUN_LEN(&sockname);
  912. #else
  913.     namelen = strlen(sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
  914. #endif
  915.     if (abstract) {
  916. sockname.sun_path[0] = '';
  917. namelen = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(&sockname.sun_path[1]);
  918.     }
  919.     else
  920. unlink (sockname.sun_path);
  921.     if ((status = TRANS(SocketCreateListener) (ciptr,
  922. (struct sockaddr *) &sockname, namelen, flags)) < 0)
  923.     {
  924. PRMSG (1,
  925.     "SocketUNIXCreateListener: ...SocketCreateListener() failedn",
  926.     0, 0, 0);
  927. (void) umask (oldUmask);
  928. return status;
  929.     }
  930.     /*
  931.      * Now that the listener is esablished, create the addr info for
  932.      * this connection. getpeername() doesn't work for UNIX Domain Sockets
  933.      * on some systems (hpux at least), so we will just do it manually, instead
  934.      * of calling something like TRANS(SocketUNIXGetAddr).
  935.      */
  936.     namelen = sizeof (sockname); /* this will always make it the same size */
  937.     if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
  938.     {
  939.         PRMSG (1,
  940.         "SocketUNIXCreateListener: Can't allocate space for the addrn",
  941.     0, 0, 0);
  942. (void) umask (oldUmask);
  943.         return TRANS_CREATE_LISTENER_FAILED;
  944.     }
  945.     if (abstract)
  946. sockname.sun_path[0] = '@';
  947.     ciptr->family = sockname.sun_family;
  948.     ciptr->addrlen = namelen;
  949.     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
  950.     (void) umask (oldUmask);
  951.     return 0;
  952. }
  953. static int
  954. TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
  955. {
  956.     /*
  957.      * See if the unix domain socket has disappeared.  If it has, recreate it.
  958.      */
  959.     struct sockaddr_un  *unsock = (struct sockaddr_un *) ciptr->addr;
  960.     struct stat statb;
  961.     int  status = TRANS_RESET_NOOP;
  962.     unsigned int mode;
  963.     int abstract = 0;
  964. #ifdef HAVE_ABSTRACT_SOCKETS
  965.     abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
  966. #endif
  967.     PRMSG (3, "SocketUNIXResetListener(%p,%d)n", ciptr, ciptr->fd, 0);
  968.     if (!abstract && (
  969. stat (unsock->sun_path, &statb) == -1 ||
  970.         ((statb.st_mode & S_IFMT) !=
  971. #if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
  972.    S_IFIFO
  973. #else
  974. S_IFSOCK
  975. #endif
  976. )))
  977.     {
  978. int oldUmask = umask (0);
  979. #ifdef UNIX_DIR
  980. #ifdef HAS_STICKY_DIR_BIT
  981. mode = 01777;
  982. #else
  983. mode = 0777;
  984. #endif
  985.         if (trans_mkdir(UNIX_DIR, mode) == -1) {
  986.             PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %dn",
  987.     UNIX_DIR, errno, 0);
  988.     (void) umask (oldUmask);
  989.     return TRANS_RESET_FAILURE;
  990.         }
  991. #endif
  992. close (ciptr->fd);
  993. unlink (unsock->sun_path);
  994. if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
  995. {
  996.     TRANS(FreeConnInfo) (ciptr);
  997.     (void) umask (oldUmask);
  998.     return TRANS_RESET_FAILURE;
  999. }
  1000. if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
  1001. {
  1002.     close (ciptr->fd);
  1003.     TRANS(FreeConnInfo) (ciptr);
  1004.     return TRANS_RESET_FAILURE;
  1005. }
  1006. if (listen (ciptr->fd, BACKLOG) < 0)
  1007. {
  1008.     close (ciptr->fd);
  1009.     TRANS(FreeConnInfo) (ciptr);
  1010.     (void) umask (oldUmask);
  1011.     return TRANS_RESET_FAILURE;
  1012. }
  1013. umask (oldUmask);
  1014. status = TRANS_RESET_NEW_FD;
  1015.     }
  1016.     return status;
  1017. }
  1018. #endif /* UNIXCONN */
  1019. #ifdef TCPCONN
  1020. static XtransConnInfo
  1021. TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
  1022. {
  1023.     XtransConnInfo newciptr;
  1024.     struct sockaddr_in sockname;
  1025.     SOCKLEN_T namelen = sizeof(sockname);
  1026.     PRMSG (2, "SocketINETAccept(%p,%d)n", ciptr, ciptr->fd, 0);
  1027.     if ((newciptr = (XtransConnInfo) xcalloc (
  1028. 1, sizeof(struct _XtransConnInfo))) == NULL)
  1029.     {
  1030. PRMSG (1, "SocketINETAccept: malloc failedn", 0, 0, 0);
  1031. *status = TRANS_ACCEPT_BAD_MALLOC;
  1032. return NULL;
  1033.     }
  1034.     if ((newciptr->fd = accept (ciptr->fd,
  1035. (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
  1036.     {
  1037. #ifdef WIN32
  1038. errno = WSAGetLastError();
  1039. #endif
  1040. PRMSG (1, "SocketINETAccept: accept() failedn", 0, 0, 0);
  1041. xfree (newciptr);
  1042. *status = TRANS_ACCEPT_FAILED;
  1043. return NULL;
  1044.     }
  1045. #ifdef TCP_NODELAY
  1046.     {
  1047. /*
  1048.  * turn off TCP coalescence for INET sockets
  1049.  */
  1050. int tmp = 1;
  1051. setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
  1052.     (char *) &tmp, sizeof (int));
  1053.     }
  1054. #endif
  1055.     /*
  1056.      * Get this address again because the transport may give a more 
  1057.      * specific address now that a connection is established.
  1058.      */
  1059.     if (TRANS(SocketINETGetAddr) (newciptr) < 0)
  1060.     {
  1061. PRMSG (1,
  1062.     "SocketINETAccept: ...SocketINETGetAddr() failed:n",
  1063.     0, 0, 0);
  1064. close (newciptr->fd);
  1065. xfree (newciptr);
  1066. *status = TRANS_ACCEPT_MISC_ERROR;
  1067.         return NULL;
  1068.     }
  1069.     if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
  1070.     {
  1071. PRMSG (1,
  1072.   "SocketINETAccept: ...SocketINETGetPeerAddr() failed:n",
  1073. 0, 0, 0);
  1074. close (newciptr->fd);
  1075. if (newciptr->addr) xfree (newciptr->addr);
  1076. xfree (newciptr);
  1077. *status = TRANS_ACCEPT_MISC_ERROR;
  1078.         return NULL;
  1079.     }
  1080.     *status = 0;
  1081.     return newciptr;
  1082. }
  1083. #endif /* TCPCONN */
  1084. #ifdef UNIXCONN
  1085. static XtransConnInfo
  1086. TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
  1087. {
  1088.     XtransConnInfo newciptr;
  1089.     struct sockaddr_un sockname;
  1090.     SOCKLEN_T  namelen = sizeof sockname;
  1091.     PRMSG (2, "SocketUNIXAccept(%p,%d)n", ciptr, ciptr->fd, 0);
  1092.     if ((newciptr = (XtransConnInfo) xcalloc (
  1093. 1, sizeof(struct _XtransConnInfo))) == NULL)
  1094.     {
  1095. PRMSG (1, "SocketUNIXAccept: malloc() failedn", 0, 0, 0);
  1096. *status = TRANS_ACCEPT_BAD_MALLOC;
  1097. return NULL;
  1098.     }
  1099.     if ((newciptr->fd = accept (ciptr->fd,
  1100. (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
  1101.     {
  1102. PRMSG (1, "SocketUNIXAccept: accept() failedn", 0, 0, 0);
  1103. xfree (newciptr);
  1104. *status = TRANS_ACCEPT_FAILED;
  1105. return NULL;
  1106.     }
  1107. ciptr->addrlen = namelen;
  1108.     /*
  1109.      * Get the socket name and the peer name from the listener socket,
  1110.      * since this is unix domain.
  1111.      */
  1112.     if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
  1113.     {
  1114.         PRMSG (1,
  1115.         "SocketUNIXAccept: Can't allocate space for the addrn",
  1116.       0, 0, 0);
  1117. close (newciptr->fd);
  1118. xfree (newciptr);
  1119. *status = TRANS_ACCEPT_BAD_MALLOC;
  1120.         return NULL;
  1121.     }
  1122.     /*
  1123.      * if the socket is abstract, we already modified the address to have a
  1124.      * @ instead of the initial NUL, so no need to do that again here.
  1125.      */
  1126.     newciptr->addrlen = ciptr->addrlen;
  1127.     memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
  1128.     if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
  1129.     {
  1130.         PRMSG (1,
  1131.       "SocketUNIXAccept: Can't allocate space for the addrn",
  1132.       0, 0, 0);
  1133. close (newciptr->fd);
  1134. if (newciptr->addr) xfree (newciptr->addr);
  1135. xfree (newciptr);
  1136. *status = TRANS_ACCEPT_BAD_MALLOC;
  1137.         return NULL;
  1138.     }
  1139.     
  1140.     newciptr->peeraddrlen = ciptr->addrlen;
  1141.     memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
  1142.     newciptr->family = AF_UNIX;
  1143.     *status = 0;
  1144.     return newciptr;
  1145. }
  1146. #endif /* UNIXCONN */
  1147. #endif /* TRANS_SERVER */
  1148. #ifdef TRANS_CLIENT
  1149. #ifdef TCPCONN
  1150. #if defined(IPv6) && defined(AF_INET6)
  1151. struct addrlist {
  1152.     struct addrinfo * addr;
  1153.     struct addrinfo * firstaddr; 
  1154.     char  port[PORTBUFSIZE];
  1155.     char  host[MAXHOSTNAMELEN];
  1156. };
  1157. static struct addrlist  *addrlist = NULL;
  1158. #endif
  1159. static int
  1160. TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
  1161. {
  1162.     struct sockaddr * socketaddr = NULL;
  1163.     int socketaddrlen = 0;
  1164.     int res;
  1165. #if defined(IPv6) && defined(AF_INET6)
  1166.     struct addrinfo  hints;
  1167.     char ntopbuf[INET6_ADDRSTRLEN];
  1168.     int resetonce = 0;
  1169. #endif
  1170.     struct sockaddr_in sockname;
  1171. #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
  1172.     _Xgethostbynameparams hparams;
  1173.     _Xgetservbynameparams sparams;
  1174. #endif
  1175.     struct hostent *hostp;
  1176.     struct servent *servp;
  1177.     unsigned long  tmpaddr;
  1178. #ifdef X11_t
  1179.     char portbuf[PORTBUFSIZE];
  1180. #endif
  1181.     long tmpport;
  1182.     char  hostnamebuf[256]; /* tmp space */
  1183.     PRMSG (2,"SocketINETConnect(%d,%s,%s)n", ciptr->fd, host, port);
  1184.     if (!host)
  1185.     {
  1186. hostnamebuf[0] = '';
  1187. (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
  1188. host = hostnamebuf;
  1189.     }
  1190. #ifdef X11_t
  1191.     /*
  1192.      * X has a well known port, that is transport dependent. It is easier
  1193.      * to handle it here, than try and come up with a transport independent
  1194.      * representation that can be passed in and resolved the usual way.
  1195.      *
  1196.      * The port that is passed here is really a string containing the idisplay
  1197.      * from ConnectDisplay().
  1198.      */
  1199.     if (is_numeric (port))
  1200.     {
  1201. tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
  1202. sprintf (portbuf, "%lu", tmpport);
  1203. port = portbuf;
  1204.     }
  1205. #endif
  1206. #if defined(IPv6) && defined(AF_INET6)
  1207.     if (haveIPv6) {
  1208. if (addrlist != NULL) {
  1209.     if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
  1210. if (addrlist->firstaddr)
  1211.     freeaddrinfo(addrlist->firstaddr);
  1212. addrlist->firstaddr = NULL;
  1213.     }
  1214. } else {
  1215.     addrlist = malloc(sizeof(struct addrlist));
  1216.     addrlist->firstaddr = NULL;
  1217. }
  1218. if (addrlist->firstaddr == NULL) {
  1219.     strncpy(addrlist->port, port, sizeof(addrlist->port));
  1220.     addrlist->port[sizeof(addrlist->port) - 1] = '';
  1221.     strncpy(addrlist->host, host, sizeof(addrlist->host));
  1222.     addrlist->host[sizeof(addrlist->host) - 1] = '';
  1223.     bzero(&hints,sizeof(hints));
  1224.     hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
  1225.     res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
  1226.     if (res != 0) {
  1227. PRMSG (1, "SocketINETConnect() can't get address "
  1228. "for %s:%s: %sn", host, port, gai_strerror(res));
  1229. ESET(EINVAL);
  1230. return TRANS_CONNECT_FAILED;
  1231.     }
  1232.     for (res = 0, addrlist->addr = addrlist->firstaddr;
  1233.  addrlist->addr ; res++) {
  1234. addrlist->addr = addrlist->addr->ai_next;
  1235.     }
  1236.     PRMSG(4,"Got New Address list with %d addressesn", res, 0, 0);
  1237.     res = 0;
  1238.     addrlist->addr = NULL;
  1239. }
  1240. while (socketaddr == NULL) {
  1241.     if (addrlist->addr == NULL) {
  1242. if (resetonce) { 
  1243.     /* Already checked entire list - no usable addresses */
  1244.     PRMSG (1, "SocketINETConnect() no usable address "
  1245.    "for %s:%sn", host, port, 0);
  1246.     return TRANS_CONNECT_FAILED;
  1247. } else {
  1248.     /* Go back to beginning of list */
  1249.     resetonce = 1;
  1250.     addrlist->addr = addrlist->firstaddr;
  1251. }
  1252.     } 
  1253.     socketaddr = addrlist->addr->ai_addr;
  1254.     socketaddrlen = addrlist->addr->ai_addrlen;
  1255.     if (addrlist->addr->ai_family == AF_INET) {
  1256. struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
  1257. PRMSG (4,"SocketINETConnect() sockname.sin_addr = %sn",
  1258. inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
  1259. ntopbuf,sizeof(ntopbuf)), 0, 0); 
  1260. PRMSG (4,"SocketINETConnect() sockname.sin_port = %dn",
  1261. ntohs(sin->sin_port), 0, 0); 
  1262. if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
  1263.     if (strcmp(Sockettrans2devtab[ciptr->index].transname,
  1264. "tcp") == 0) {
  1265. XtransConnInfo newciptr;
  1266. /*
  1267.  * Our socket is an IPv6 socket, but the address is
  1268.  * IPv4.  Close it and get an IPv4 socket.  This is
  1269.  * needed for IPv4 connections to work on platforms
  1270.  * that don't allow IPv4 over IPv6 sockets.
  1271.  */
  1272. TRANS(SocketINETClose)(ciptr);
  1273. newciptr = TRANS(SocketOpenCOTSClientBase)(
  1274. "tcp", "tcp", host, port, ciptr->index);
  1275. if (newciptr)
  1276.     ciptr->fd = newciptr->fd;
  1277. if (!newciptr ||
  1278.     Sockettrans2devtab[newciptr->index].family !=
  1279. AF_INET) {
  1280.     socketaddr = NULL;
  1281.     PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
  1282. " socketfor IPv4 addressn", 0,0,0);
  1283. }
  1284. if (newciptr)
  1285.     xfree(newciptr);
  1286.     } else {
  1287. socketaddr = NULL;
  1288. PRMSG (4,"SocketINETConnect Skipping IPv4 addressn",
  1289. 0,0,0);
  1290.     }
  1291. }
  1292.     } else if (addrlist->addr->ai_family == AF_INET6) {
  1293. struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
  1294. PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %sn",
  1295. inet_ntop(addrlist->addr->ai_family,
  1296.   &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
  1297. 0, 0); 
  1298. PRMSG (4,"SocketINETConnect() sockname.sin6_port = %dn",
  1299. ntohs(sin6->sin6_port), 0, 0); 
  1300. if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
  1301.     if (strcmp(Sockettrans2devtab[ciptr->index].transname,
  1302. "tcp") == 0) {
  1303. XtransConnInfo newciptr;
  1304. /*
  1305.  * Close the IPv4 socket and try to open an IPv6 socket.
  1306.  */
  1307. TRANS(SocketINETClose)(ciptr);
  1308. newciptr = TRANS(SocketOpenCOTSClientBase)(
  1309. "tcp", "tcp", host, port, -1);
  1310. if (newciptr)
  1311.     ciptr->fd = newciptr->fd;
  1312. if (!newciptr ||
  1313.     Sockettrans2devtab[newciptr->index].family !=
  1314. AF_INET6) {
  1315.     socketaddr = NULL;
  1316.     PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
  1317.    "socket for IPv6 addressn", 0,0,0);
  1318. }
  1319. if (newciptr)
  1320.     xfree(newciptr);
  1321.     }
  1322.     else
  1323.     {
  1324. socketaddr = NULL;
  1325. PRMSG (4,"SocketINETConnect() Skipping IPv6 addressn",
  1326. 0,0,0);
  1327.     }
  1328. }
  1329.     } else {
  1330. socketaddr = NULL; /* Unsupported address type */
  1331.     }
  1332.     if (socketaddr == NULL) {
  1333. addrlist->addr = addrlist->addr->ai_next;
  1334.     }
  1335.     } else
  1336. #endif
  1337.     {
  1338. /*
  1339.  * Build the socket name.
  1340.  */
  1341. #ifdef BSD44SOCKETS
  1342. sockname.sin_len = sizeof (struct sockaddr_in);
  1343. #endif
  1344. sockname.sin_family = AF_INET;
  1345. /*
  1346.  * fill in sin_addr
  1347.  */
  1348. #ifndef INADDR_NONE
  1349. #define INADDR_NONE ((in_addr_t) 0xffffffff)
  1350. #endif
  1351. /* check for ww.xx.yy.zz host string */
  1352. if (isascii (host[0]) && isdigit (host[0])) {
  1353.     tmpaddr = inet_addr (host); /* returns network byte order */
  1354. } else {
  1355.     tmpaddr = INADDR_NONE;
  1356. }
  1357. PRMSG (4,"SocketINETConnect() inet_addr(%s) = %xn", host, tmpaddr, 0);
  1358. if (tmpaddr == INADDR_NONE) {
  1359.     if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
  1360. PRMSG (1,"SocketINETConnect: Can't get address for %sn",
  1361. host, 0, 0);
  1362. ESET(EINVAL);
  1363. return TRANS_CONNECT_FAILED;
  1364.     }
  1365.     if (hostp->h_addrtype != AF_INET) {  /* is IP host? */
  1366. PRMSG (1,"SocketINETConnect: not INET host%sn", host, 0, 0);
  1367. ESET(EPROTOTYPE);
  1368. return TRANS_CONNECT_FAILED;
  1369.     }
  1370.     memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
  1371.     sizeof (sockname.sin_addr));
  1372. } else {
  1373.     sockname.sin_addr.s_addr = tmpaddr;
  1374.         }
  1375. /*
  1376.  * fill in sin_port
  1377.  */
  1378. /* Check for number in the port string */
  1379. if (!is_numeric (port)) {
  1380.     if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
  1381. PRMSG (1,"SocketINETConnect: can't get service for %sn",
  1382. port, 0, 0);
  1383. return TRANS_CONNECT_FAILED;
  1384.     }
  1385.     sockname.sin_port = htons (servp->s_port);
  1386. } else {
  1387.     tmpport = strtol (port, (char**)NULL, 10);
  1388.     if (tmpport < 1024 || tmpport > USHRT_MAX)
  1389. return TRANS_CONNECT_FAILED;
  1390.     sockname.sin_port = htons (((unsigned short) tmpport));
  1391. }
  1392. PRMSG (4,"SocketINETConnect: sockname.sin_port = %dn",
  1393. ntohs(sockname.sin_port), 0, 0);
  1394. socketaddr = (struct sockaddr *) &sockname;
  1395. socketaddrlen = sizeof(sockname);
  1396.     }
  1397.     /*
  1398.      * Turn on socket keepalive so the client process will eventually
  1399.      * be notified with a SIGPIPE signal if the display server fails
  1400.      * to respond to a periodic transmission of messages
  1401.      * on the connected socket.
  1402.      * This is useful to avoid hung application processes when the
  1403.      * processes are not spawned from the xdm session and
  1404.      * the display server terminates abnormally.
  1405.      * (Someone turned off the power switch.)
  1406.      */
  1407.     {
  1408. int tmp = 1;
  1409. setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
  1410. (char *) &tmp, sizeof (int));
  1411.     }
  1412.     /*
  1413.      * Do the connect()
  1414.      */
  1415.     if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
  1416.     {
  1417. #ifdef WIN32
  1418. int olderrno = WSAGetLastError();
  1419. #else
  1420. int olderrno = errno;
  1421. #endif
  1422. /*
  1423.  * If the error was ECONNREFUSED, the server may be overloaded
  1424.  * and we should try again.
  1425.  *
  1426.  * If the error was EWOULDBLOCK or EINPROGRESS then the socket
  1427.  * was non-blocking and we should poll using select
  1428.  *
  1429.  * If the error was EINTR, the connect was interrupted and we
  1430.  * should try again.
  1431.  *
  1432.  * If multiple addresses are found for a host then we should
  1433.  * try to connect again with a different address for a larger
  1434.  * number of errors that made us quit before, since those
  1435.  * could be caused by trying to use an IPv6 address to contact
  1436.  * a machine with an IPv4-only server or other reasons that
  1437.  * only affect one of a set of addresses.  
  1438.  */
  1439. if (olderrno == ECONNREFUSED || olderrno == EINTR
  1440. #if defined(IPv6) && defined(AF_INET6)
  1441.   || (haveIPv6 && ((addrlist->addr->ai_next != NULL) || 
  1442.         (addrlist->addr != addrlist->firstaddr)) &&
  1443.                (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
  1444.  olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
  1445. #if defined(EHOSTDOWN)
  1446.    || olderrno == EHOSTDOWN
  1447. #endif
  1448.        ))
  1449. #endif
  1450.     )
  1451.     res = TRANS_TRY_CONNECT_AGAIN;
  1452. else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
  1453.     res = TRANS_IN_PROGRESS;
  1454. else
  1455. {
  1456.     PRMSG (2,"SocketINETConnect: Can't connect: errno = %dn",
  1457.    olderrno,0, 0);
  1458.     res = TRANS_CONNECT_FAILED;
  1459. }
  1460.     } else {
  1461. res = 0;
  1462.     
  1463. /*
  1464.  * Sync up the address fields of ciptr.
  1465.  */
  1466.     
  1467. if (TRANS(SocketINETGetAddr) (ciptr) < 0)
  1468. {
  1469.     PRMSG (1,
  1470.      "SocketINETConnect: ...SocketINETGetAddr() failed:n",
  1471.       0, 0, 0);
  1472.     res = TRANS_CONNECT_FAILED;
  1473. }
  1474. else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
  1475. {
  1476.     PRMSG (1,
  1477.       "SocketINETConnect: ...SocketINETGetPeerAddr() failed:n",
  1478.       0, 0, 0);
  1479.     res = TRANS_CONNECT_FAILED;
  1480. }
  1481.     }
  1482. #if defined(IPv6) && defined(AF_INET6)
  1483.    if (haveIPv6 && res != 0) { 
  1484. addrlist->addr = addrlist->addr->ai_next;
  1485.    }
  1486. #endif
  1487.     return res;
  1488. }
  1489. #endif /* TCPCONN */
  1490. #ifdef UNIXCONN
  1491. /*
  1492.  * Make sure 'host' is really local.
  1493.  */
  1494. static int
  1495. UnixHostReallyLocal (char *host)
  1496. {
  1497.     char hostnamebuf[256];
  1498. #if defined(IPv6) && defined(AF_INET6)
  1499.     if (getaddrinfo == NULL)
  1500. haveIPv6 = 0;
  1501. #endif
  1502.     TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
  1503.     if (strcmp (hostnamebuf, host) == 0)
  1504.     {
  1505. return (1);
  1506.     }
  1507. #if defined(IPv6) && defined(AF_INET6)
  1508.     else if (haveIPv6)
  1509.     {
  1510. struct addrinfo *localhostaddr;
  1511. struct addrinfo *otherhostaddr;
  1512. struct addrinfo *i, *j;
  1513. int equiv = 0;
  1514. if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
  1515.     return 0;
  1516. if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
  1517.     freeaddrinfo(localhostaddr);
  1518.     return 0;
  1519. }
  1520. for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
  1521.     for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
  1522. if (i->ai_family == j->ai_family) {
  1523.     if (i->ai_family == AF_INET) {
  1524. struct sockaddr_in *sinA 
  1525.   = (struct sockaddr_in *) i->ai_addr;
  1526. struct sockaddr_in *sinB
  1527.   = (struct sockaddr_in *) j->ai_addr;
  1528. struct in_addr *A = &sinA->sin_addr;
  1529. struct in_addr *B = &sinB->sin_addr;
  1530. if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
  1531.     equiv = 1;
  1532. }
  1533.     } else if (i->ai_family == AF_INET6) {
  1534. struct sockaddr_in6 *sinA 
  1535.   = (struct sockaddr_in6 *) i->ai_addr;
  1536. struct sockaddr_in6 *sinB 
  1537.   = (struct sockaddr_in6 *) j->ai_addr;
  1538. struct in6_addr *A = &sinA->sin6_addr;
  1539. struct in6_addr *B = &sinB->sin6_addr;
  1540. if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
  1541.     equiv = 1;
  1542. }
  1543.     }
  1544. }
  1545.     }
  1546. }
  1547. freeaddrinfo(localhostaddr);
  1548. freeaddrinfo(otherhostaddr);
  1549. return equiv;
  1550.     }
  1551. #endif
  1552.     else
  1553.     {
  1554. /*
  1555.  * A host may have more than one network address.  If any of the
  1556.  * network addresses of 'host' (specified to the connect call)
  1557.  * match any of the network addresses of 'hostname' (determined
  1558.  * by TRANS(GetHostname)), then the two hostnames are equivalent,
  1559.  * and we know that 'host' is really a local host.
  1560.  */
  1561. char specified_local_addr_list[10][4];
  1562. int scount, equiv, i, j;
  1563. #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
  1564. _Xgethostbynameparams hparams;
  1565. #endif
  1566. struct hostent *hostp;
  1567. if ((hostp = _XGethostbyname (host,hparams)) == NULL)
  1568.     return (0);
  1569. scount = 0;
  1570. while (hostp->h_addr_list[scount] && scount <= 8)
  1571. {
  1572.     /*
  1573.      * The 2nd call to gethostname() overrides the data
  1574.      * from the 1st call, so we must save the address list.
  1575.      */
  1576.     specified_local_addr_list[scount][0] = 
  1577. hostp->h_addr_list[scount][0];
  1578.     specified_local_addr_list[scount][1] = 
  1579. hostp->h_addr_list[scount][1];
  1580.     specified_local_addr_list[scount][2] = 
  1581. hostp->h_addr_list[scount][2];
  1582.     specified_local_addr_list[scount][3] = 
  1583. hostp->h_addr_list[scount][3];
  1584.     scount++;
  1585. }
  1586. if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
  1587.     return (0);
  1588. equiv = 0;
  1589. i = 0;
  1590. while (i < scount && !equiv)
  1591. {
  1592.     j = 0;
  1593.     while (hostp->h_addr_list[j])
  1594.     {
  1595. if ((specified_local_addr_list[i][0] == 
  1596. hostp->h_addr_list[j][0]) &&
  1597.     (specified_local_addr_list[i][1] == 
  1598. hostp->h_addr_list[j][1]) &&
  1599.     (specified_local_addr_list[i][2] == 
  1600. hostp->h_addr_list[j][2]) &&
  1601.     (specified_local_addr_list[i][3] == 
  1602. hostp->h_addr_list[j][3]))
  1603. {
  1604.     /* They're equal, so we're done */
  1605.     
  1606.     equiv = 1;
  1607.     break;
  1608. }
  1609. j++;
  1610.     }
  1611.     i++;
  1612. }
  1613. return (equiv);
  1614.     }
  1615. }
  1616. static int
  1617. TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
  1618. {
  1619.     struct sockaddr_un sockname;
  1620.     SOCKLEN_T namelen;
  1621.     int abstract = 0;
  1622. #ifdef HAVE_ABSTRACT_SOCKETS
  1623.     abstract = ciptr->transptr->flags & TRANS_ABSTRACT;
  1624. #endif
  1625.     PRMSG (2,"SocketUNIXConnect(%d,%s,%s)n", ciptr->fd, host, port);
  1626.     
  1627.     /*
  1628.      * Make sure 'host' is really local.  If not, we return failure.
  1629.      * The reason we make this check is because a process may advertise
  1630.      * a "local" network ID for which it can accept connections, but if
  1631.      * a process on a remote machine tries to connect to this network ID,
  1632.      * we know for sure it will fail.
  1633.      */
  1634.     if (host && *host && host[0]!='/' && strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
  1635.     {
  1636. PRMSG (1,
  1637.    "SocketUNIXConnect: Cannot connect to non-local host %sn",
  1638.        host, 0, 0);
  1639. return TRANS_CONNECT_FAILED;
  1640.     }
  1641.     /*
  1642.      * Check the port.
  1643.      */
  1644.     if (!port || !*port)
  1645.     {
  1646. PRMSG (1,"SocketUNIXConnect: Missing port specificationn",
  1647.       0, 0, 0);
  1648. return TRANS_CONNECT_FAILED;
  1649.     }
  1650.     /*
  1651.      * Build the socket name.
  1652.      */
  1653.     
  1654.     sockname.sun_family = AF_UNIX;
  1655.     if (set_sun_path(port, UNIX_PATH, sockname.sun_path, abstract) != 0) {
  1656. PRMSG (1, "SocketUNIXConnect: path too longn", 0, 0, 0);
  1657. return TRANS_CONNECT_FAILED;
  1658.     }
  1659. #if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) 
  1660.     sockname.sun_len = strlen (sockname.sun_path);
  1661. #endif
  1662. #if defined(BSD44SOCKETS) || defined(SUN_LEN)
  1663.     namelen = SUN_LEN (&sockname);
  1664. #else
  1665.     namelen = strlen (sockname.sun_path) + offsetof(struct sockaddr_un, sun_path);
  1666. #endif
  1667.     /*
  1668.      * Adjust the socket path if using abstract sockets.
  1669.      * Done here because otherwise all the strlen() calls above would fail.
  1670.      */
  1671.     if (abstract) {
  1672. sockname.sun_path[0] = '';
  1673.     }
  1674.     /*
  1675.      * Do the connect()
  1676.      */
  1677.     if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
  1678.     {
  1679. int olderrno = errno;
  1680. int connected = 0;
  1681. if (!connected)
  1682. {
  1683.     errno = olderrno;
  1684.     
  1685.     /*
  1686.      * If the error was ENOENT, the server may be starting up; we used
  1687.      * to suggest to try again in this case with
  1688.      * TRANS_TRY_CONNECT_AGAIN, but this introduced problems for
  1689.      * processes still referencing stale sockets in their environment.
  1690.      * Hence, we now return a hard error, TRANS_CONNECT_FAILED, and it
  1691.      * is suggested that higher level stacks handle retries on their
  1692.      * level when they face a slow starting server.
  1693.      *
  1694.      * If the error was EWOULDBLOCK or EINPROGRESS then the socket
  1695.      * was non-blocking and we should poll using select
  1696.      *
  1697.      * If the error was EINTR, the connect was interrupted and we
  1698.      * should try again.
  1699.      */
  1700.     if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
  1701. return TRANS_IN_PROGRESS;
  1702.     else if (olderrno == EINTR)
  1703. return TRANS_TRY_CONNECT_AGAIN;
  1704.     else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
  1705. /* If opening as abstract socket failed, try again normally */
  1706. if (abstract) {
  1707.     ciptr->transptr->flags &= ~(TRANS_ABSTRACT);
  1708.     return TRANS_TRY_CONNECT_AGAIN;
  1709. } else {
  1710.     return TRANS_CONNECT_FAILED;
  1711. }
  1712.     } else {
  1713. PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %dn",
  1714.        EGET(),0, 0);
  1715. return TRANS_CONNECT_FAILED;
  1716.     }
  1717. }
  1718.     }
  1719.     /*
  1720.      * Get the socket name and the peer name from the connect socket,
  1721.      * since this is unix domain.
  1722.      */
  1723.     if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
  1724.        (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
  1725.     {
  1726.         PRMSG (1,
  1727. "SocketUNIXCreateListener: Can't allocate space for the addrn",
  1728.       0, 0, 0);
  1729.         return TRANS_CONNECT_FAILED;
  1730.     }
  1731.     if (abstract)
  1732. sockname.sun_path[0] = '@';
  1733.     ciptr->family = AF_UNIX;
  1734.     ciptr->addrlen = namelen;
  1735.     ciptr->peeraddrlen = namelen;
  1736.     memcpy (ciptr->addr, &sockname, ciptr->addrlen);
  1737.     memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
  1738.     return 0;
  1739. }
  1740. #endif /* UNIXCONN */
  1741. #endif /* TRANS_CLIENT */
  1742. static int
  1743. TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
  1744. {
  1745.     PRMSG (2,"SocketBytesReadable(%p,%d,%p)n",
  1746. ciptr, ciptr->fd, pend);
  1747. #ifdef WIN32
  1748.     {
  1749. int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
  1750. if (ret == SOCKET_ERROR) errno = WSAGetLastError();
  1751. return ret;
  1752.     }
  1753. #else
  1754. #if defined(__i386__) && defined(SYSV) && !defined(SCO325) 
  1755.     return ioctl (ciptr->fd, I_NREAD, (char *) pend);
  1756. #else
  1757.     return ioctl (ciptr->fd, FIONREAD, (char *) pend);
  1758. #endif /* __i386__ && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
  1759. #endif /* WIN32 */
  1760. }
  1761. static int
  1762. TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
  1763. {
  1764.     PRMSG (2,"SocketRead(%d,%p,%d)n", ciptr->fd, buf, size);
  1765. #if defined(WIN32) 
  1766.     {
  1767. int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
  1768. #ifdef WIN32
  1769. if (ret == SOCKET_ERROR) errno = WSAGetLastError();
  1770. #endif
  1771. return ret;
  1772.     }
  1773. #else
  1774.     return read (ciptr->fd, buf, size);
  1775. #endif /* WIN32 */
  1776. }
  1777. static int
  1778. TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
  1779. {
  1780.     PRMSG (2,"SocketWrite(%d,%p,%d)n", ciptr->fd, buf, size);
  1781. #if defined(WIN32) 
  1782.     {
  1783. int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
  1784. #ifdef WIN32
  1785. if (ret == SOCKET_ERROR) errno = WSAGetLastError();
  1786. #endif
  1787. return ret;
  1788.     }
  1789. #else
  1790.     return write (ciptr->fd, buf, size);
  1791. #endif /* WIN32 */
  1792. }
  1793. static int
  1794. TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
  1795. {
  1796.     PRMSG (2,"SocketReadv(%d,%p,%d)n", ciptr->fd, buf, size);
  1797.     return READV (ciptr, buf, size);
  1798. }
  1799. static int
  1800. TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
  1801. {
  1802.     PRMSG (2,"SocketWritev(%d,%p,%d)n", ciptr->fd, buf, size);
  1803.     return WRITEV (ciptr, buf, size);
  1804. }
  1805. static int
  1806. TRANS(SocketDisconnect) (XtransConnInfo ciptr)
  1807. {
  1808.     PRMSG (2,"SocketDisconnect(%p,%d)n", ciptr, ciptr->fd, 0);
  1809. #ifdef WIN32
  1810.     { 
  1811. int ret = shutdown (ciptr->fd, 2);
  1812. if (ret == SOCKET_ERROR) errno = WSAGetLastError();
  1813. return ret;
  1814.     }
  1815. #else
  1816.     return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
  1817. #endif
  1818. }
  1819. #ifdef TCPCONN
  1820. static int
  1821. TRANS(SocketINETClose) (XtransConnInfo ciptr)
  1822. {
  1823.     PRMSG (2,"SocketINETClose(%p,%d)n", ciptr, ciptr->fd, 0);
  1824. #ifdef WIN32
  1825.     {
  1826. int ret = close (ciptr->fd);
  1827. if (ret == SOCKET_ERROR) errno = WSAGetLastError();
  1828. return ret;
  1829.     }
  1830. #else
  1831.     return close (ciptr->fd);
  1832. #endif
  1833. }
  1834. #endif /* TCPCONN */
  1835. #ifdef UNIXCONN
  1836. static int
  1837. TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
  1838. {
  1839.     /*
  1840.      * If this is the server side, then once the socket is closed,
  1841.      * it must be unlinked to completely close it
  1842.      */
  1843.     struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
  1844.     int ret;
  1845.     PRMSG (2,"SocketUNIXClose(%p,%d)n", ciptr, ciptr->fd, 0);
  1846.     ret = close(ciptr->fd);
  1847.     if (ciptr->flags
  1848.        && sockname
  1849.        && sockname->sun_family == AF_UNIX
  1850.        && sockname->sun_path[0])
  1851.     {
  1852. if (!(ciptr->flags & TRANS_NOUNLINK
  1853.     || ciptr->transptr->flags & TRANS_ABSTRACT))
  1854. unlink (sockname->sun_path);
  1855.     }
  1856.     return ret;
  1857. }
  1858. static int
  1859. TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
  1860. {
  1861.     /*
  1862.      * Don't unlink path.
  1863.      */
  1864.     int ret;
  1865.     PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)n",
  1866. ciptr, ciptr->fd, 0);
  1867.     ret = close(ciptr->fd);
  1868.     return ret;
  1869. }
  1870. #endif /* UNIXCONN */
  1871. #ifdef TCPCONN
  1872. # ifdef TRANS_SERVER
  1873. static char* tcp_nolisten[] = {
  1874. "inet",
  1875. #if defined(IPv6) && defined(AF_INET6)
  1876. "inet6",
  1877. #endif
  1878. NULL
  1879. };
  1880. # endif
  1881. Xtransport TRANS(SocketTCPFuncs) = {
  1882. /* Socket Interface */
  1883. "tcp",
  1884.         TRANS_ALIAS,
  1885. #ifdef TRANS_CLIENT
  1886. TRANS(SocketOpenCOTSClient),
  1887. #endif /* TRANS_CLIENT */
  1888. #ifdef TRANS_SERVER
  1889. tcp_nolisten,
  1890. TRANS(SocketOpenCOTSServer),
  1891. #endif /* TRANS_SERVER */
  1892. #ifdef TRANS_CLIENT
  1893. TRANS(SocketOpenCLTSClient),
  1894. #endif /* TRANS_CLIENT */
  1895. #ifdef TRANS_SERVER
  1896. TRANS(SocketOpenCLTSServer),
  1897. #endif /* TRANS_SERVER */
  1898. #ifdef TRANS_REOPEN
  1899. TRANS(SocketReopenCOTSServer),
  1900. TRANS(SocketReopenCLTSServer),
  1901. #endif
  1902. TRANS(SocketSetOption),
  1903. #ifdef TRANS_SERVER
  1904. TRANS(SocketINETCreateListener),
  1905. NULL,         /* ResetListener */
  1906. TRANS(SocketINETAccept),
  1907. #endif /* TRANS_SERVER */
  1908. #ifdef TRANS_CLIENT
  1909. TRANS(SocketINETConnect),
  1910. #endif /* TRANS_CLIENT */
  1911. TRANS(SocketBytesReadable),
  1912. TRANS(SocketRead),
  1913. TRANS(SocketWrite),
  1914. TRANS(SocketReadv),
  1915. TRANS(SocketWritev),
  1916. TRANS(SocketDisconnect),
  1917. TRANS(SocketINETClose),
  1918. TRANS(SocketINETClose),
  1919. };
  1920. Xtransport TRANS(SocketINETFuncs) = {
  1921. /* Socket Interface */
  1922. "inet",
  1923. 0,
  1924. #ifdef TRANS_CLIENT
  1925. TRANS(SocketOpenCOTSClient),
  1926. #endif /* TRANS_CLIENT */
  1927. #ifdef TRANS_SERVER
  1928. NULL,
  1929. TRANS(SocketOpenCOTSServer),
  1930. #endif /* TRANS_SERVER */
  1931. #ifdef TRANS_CLIENT
  1932. TRANS(SocketOpenCLTSClient),
  1933. #endif /* TRANS_CLIENT */
  1934. #ifdef TRANS_SERVER
  1935. TRANS(SocketOpenCLTSServer),
  1936. #endif /* TRANS_SERVER */
  1937. #ifdef TRANS_REOPEN
  1938. TRANS(SocketReopenCOTSServer),
  1939. TRANS(SocketReopenCLTSServer),
  1940. #endif
  1941. TRANS(SocketSetOption),
  1942. #ifdef TRANS_SERVER
  1943. TRANS(SocketINETCreateListener),
  1944. NULL,         /* ResetListener */
  1945. TRANS(SocketINETAccept),
  1946. #endif /* TRANS_SERVER */
  1947. #ifdef TRANS_CLIENT
  1948. TRANS(SocketINETConnect),
  1949. #endif /* TRANS_CLIENT */
  1950. TRANS(SocketBytesReadable),
  1951. TRANS(SocketRead),
  1952. TRANS(SocketWrite),
  1953. TRANS(SocketReadv),
  1954. TRANS(SocketWritev),
  1955. TRANS(SocketDisconnect),
  1956. TRANS(SocketINETClose),
  1957. TRANS(SocketINETClose),
  1958. };
  1959. #if defined(IPv6) && defined(AF_INET6)
  1960. Xtransport     TRANS(SocketINET6Funcs) = {
  1961. /* Socket Interface */
  1962. "inet6",
  1963. 0,
  1964. #ifdef TRANS_CLIENT
  1965. TRANS(SocketOpenCOTSClient),
  1966. #endif /* TRANS_CLIENT */
  1967. #ifdef TRANS_SERVER
  1968. NULL,
  1969. TRANS(SocketOpenCOTSServer),
  1970. #endif /* TRANS_SERVER */
  1971. #ifdef TRANS_CLIENT
  1972. TRANS(SocketOpenCLTSClient),
  1973. #endif /* TRANS_CLIENT */
  1974. #ifdef TRANS_SERVER
  1975. TRANS(SocketOpenCLTSServer),
  1976. #endif /* TRANS_SERVER */
  1977. #ifdef TRANS_REOPEN
  1978. TRANS(SocketReopenCOTSServer),
  1979. TRANS(SocketReopenCLTSServer),
  1980. #endif
  1981. TRANS(SocketSetOption),
  1982. #ifdef TRANS_SERVER
  1983. TRANS(SocketINETCreateListener),
  1984. NULL, /* ResetListener */
  1985. TRANS(SocketINETAccept),
  1986. #endif /* TRANS_SERVER */
  1987. #ifdef TRANS_CLIENT
  1988. TRANS(SocketINETConnect),
  1989. #endif /* TRANS_CLIENT */
  1990. TRANS(SocketBytesReadable),
  1991. TRANS(SocketRead),
  1992. TRANS(SocketWrite),
  1993. TRANS(SocketReadv),
  1994. TRANS(SocketWritev),
  1995. TRANS(SocketDisconnect),
  1996. TRANS(SocketINETClose),
  1997. TRANS(SocketINETClose),
  1998. };
  1999. #endif /* IPv6 */
  2000. #endif /* TCPCONN */
  2001. #ifdef UNIXCONN
  2002. #if !defined(LOCALCONN)
  2003. Xtransport TRANS(SocketLocalFuncs) = {
  2004. /* Socket Interface */
  2005. "local",
  2006. #ifdef HAVE_ABSTRACT_SOCKETS
  2007. TRANS_ABSTRACT,
  2008. #else
  2009. 0,
  2010. #endif
  2011. #ifdef TRANS_CLIENT
  2012. TRANS(SocketOpenCOTSClient),
  2013. #endif /* TRANS_CLIENT */
  2014. #ifdef TRANS_SERVER
  2015. NULL,
  2016. TRANS(SocketOpenCOTSServer),
  2017. #endif /* TRANS_SERVER */
  2018. #ifdef TRANS_CLIENT
  2019. TRANS(SocketOpenCLTSClient),
  2020. #endif /* TRANS_CLIENT */
  2021. #ifdef TRANS_SERVER
  2022. TRANS(SocketOpenCLTSServer),
  2023. #endif /* TRANS_SERVER */
  2024. #ifdef TRANS_REOPEN
  2025. TRANS(SocketReopenCOTSServer),
  2026. TRANS(SocketReopenCLTSServer),
  2027. #endif
  2028. TRANS(SocketSetOption),
  2029. #ifdef TRANS_SERVER
  2030. TRANS(SocketUNIXCreateListener),
  2031. TRANS(SocketUNIXResetListener),
  2032. TRANS(SocketUNIXAccept),
  2033. #endif /* TRANS_SERVER */
  2034. #ifdef TRANS_CLIENT
  2035. TRANS(SocketUNIXConnect),
  2036. #endif /* TRANS_CLIENT */
  2037. TRANS(SocketBytesReadable),
  2038. TRANS(SocketRead),
  2039. TRANS(SocketWrite),
  2040. TRANS(SocketReadv),
  2041. TRANS(SocketWritev),
  2042. TRANS(SocketDisconnect),
  2043. TRANS(SocketUNIXClose),
  2044. TRANS(SocketUNIXCloseForCloning),
  2045. };
  2046. #endif /* !LOCALCONN */
  2047. # ifdef TRANS_SERVER
  2048. #  if !defined(LOCALCONN)
  2049. static char* unix_nolisten[] = { "local" , NULL };
  2050. #  endif
  2051. # endif
  2052.     
  2053. Xtransport TRANS(SocketUNIXFuncs) = {
  2054. /* Socket Interface */
  2055. "unix",
  2056. #if !defined(LOCALCONN) && !defined(HAVE_ABSTRACT_SOCKETS)
  2057.         TRANS_ALIAS,
  2058. #else
  2059. 0,
  2060. #endif
  2061. #ifdef TRANS_CLIENT
  2062. TRANS(SocketOpenCOTSClient),
  2063. #endif /* TRANS_CLIENT */
  2064. #ifdef TRANS_SERVER
  2065. #if !defined(LOCALCONN)
  2066. unix_nolisten,
  2067. #else
  2068. NULL,
  2069. #endif
  2070. TRANS(SocketOpenCOTSServer),
  2071. #endif /* TRANS_SERVER */
  2072. #ifdef TRANS_CLIENT
  2073. TRANS(SocketOpenCLTSClient),
  2074. #endif /* TRANS_CLIENT */
  2075. #ifdef TRANS_SERVER
  2076. TRANS(SocketOpenCLTSServer),
  2077. #endif /* TRANS_SERVER */
  2078. #ifdef TRANS_REOPEN
  2079. TRANS(SocketReopenCOTSServer),
  2080. TRANS(SocketReopenCLTSServer),
  2081. #endif
  2082. TRANS(SocketSetOption),
  2083. #ifdef TRANS_SERVER
  2084. TRANS(SocketUNIXCreateListener),
  2085. TRANS(SocketUNIXResetListener),
  2086. TRANS(SocketUNIXAccept),
  2087. #endif /* TRANS_SERVER */
  2088. #ifdef TRANS_CLIENT
  2089. TRANS(SocketUNIXConnect),
  2090. #endif /* TRANS_CLIENT */
  2091. TRANS(SocketBytesReadable),
  2092. TRANS(SocketRead),
  2093. TRANS(SocketWrite),
  2094. TRANS(SocketReadv),
  2095. TRANS(SocketWritev),
  2096. TRANS(SocketDisconnect),
  2097. TRANS(SocketUNIXClose),
  2098. TRANS(SocketUNIXCloseForCloning),
  2099. };
  2100. #endif /* UNIXCONN */