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