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