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