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