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