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