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