1/* 2 * Copyright (c) 2000, 2004, 2022, 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 25Copyright 1985, 1986, 1987, 1998 The Open Group 26 27All rights reserved. 28 29Permission is hereby granted, free of charge, to any person obtaining a 30copy of this software and associated documentation files (the 31"Software"), to deal in the Software without restriction, including 32without limitation the rights to use, copy, modify, merge, publish, 33distribute, and/or sell copies of the Software, and to permit persons 34to whom the Software is furnished to do so, provided that the above 35copyright notice(s) and this permission notice appear in all copies of 36the Software and that both the above copyright notice(s) and this 37permission notice appear in supporting documentation. 38 39THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 40OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 42OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 43HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 44INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 45FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 46NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 47WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 48 49Except as contained in this notice, the name of a copyright holder 50shall not be used in advertising or otherwise to promote the sale, use 51or other dealings in this Software without prior written authorization 52of the copyright holder. 53 54X Window System is a trademark of The Open Group. 55 56*/ 57 58#ifdef HAVE_CONFIG_H 59#include "config.h" 60#endif 61 62#ifdef TCPCONN 63#define NEEDSOCKETS 64#endif 65#ifdef UNIXCONN 66#define NEEDSOCKETS 67#endif 68 69#include <X11/Xlib.h> 70#include <X11/Xos.h> 71#include <X11/Xproto.h> 72#include <X11/Xfuncs.h> 73#include <stdio.h> 74#include <stdlib.h> 75#include <signal.h> 76#include <ctype.h> 77#include <X11/Xauth.h> 78#include <X11/Xmu/Error.h> 79#include <stdlib.h> 80 81#ifdef NEEDSOCKETS 82#ifdef WIN32 83#include <X11/Xwinsock.h> 84#else 85#include <sys/socket.h> 86#include <netdb.h> 87#include <netinet/in.h> 88#endif 89#endif /* NEEDSOCKETS */ 90 91#ifndef WIN32 92#include <arpa/inet.h> 93#endif 94 95 96#ifdef SECURE_RPC 97#include <pwd.h> 98#include <rpc/rpc.h> 99#ifdef X_POSIX_C_SOURCE 100#define _POSIX_C_SOURCE X_POSIX_C_SOURCE 101#include <limits.h> 102#undef _POSIX_C_SOURCE 103#else 104#ifdef _POSIX_SOURCE 105#include <limits.h> 106#else 107#define _POSIX_SOURCE 108#include <limits.h> 109#undef _POSIX_SOURCE 110#endif 111#endif 112#ifndef NGROUPS_MAX 113#include <sys/param.h> 114#define NGROUPS_MAX NGROUPS 115#endif 116#ifdef sun 117/* Go figure, there's no getdomainname() prototype available */ 118extern int getdomainname(char *name, size_t len); 119#endif 120#endif 121 122#ifdef USE_GETTEXT 123# include <locale.h> /* setlocale() */ 124# include <libintl.h> /* gettext(), textdomain(), etc. */ 125#else 126# define gettext(a) (a) 127#endif 128 129static int change_host(Display *dpy, char *name, Bool add); 130static const char *get_hostname(XHostAddress *ha); 131static int local_xerror(Display *dpy, XErrorEvent *rep); 132static void nameserver_lost(int sig); 133 134#define NAMESERVER_TIMEOUT 5 /* time to wait for nameserver */ 135 136static volatile int nameserver_timedout; 137 138static char *ProgramName; 139 140#ifdef NEEDSOCKETS 141static int 142XFamily(int af) 143{ 144 unsigned int i; 145 static struct _familyMap { 146 int af, xf; 147 } familyMap[] = { 148#ifdef AF_DECnet 149 { AF_DECnet, FamilyDECnet }, 150#endif 151#ifdef AF_CHAOS 152 { AF_CHAOS, FamilyChaos }, 153#endif 154#ifdef AF_INET 155 { AF_INET, FamilyInternet }, 156#if defined(IPv6) && defined(AF_INET6) 157 { AF_INET6, FamilyInternet6 }, 158#endif 159#endif 160}; 161 162#define FAMILIES ((sizeof familyMap)/(sizeof familyMap[0])) 163 164 for (i = 0; i < FAMILIES; i++) 165 if (familyMap[i].af == af) return familyMap[i].xf; 166 return -1; 167} 168#endif /* NEEDSOCKETS */ 169 170#if defined(__CYGWIN__) || defined(WIN32) 171void sethostent(int x) 172{} 173 174void endhostent() 175{} 176#endif 177 178int 179main(int argc, char *argv[]) 180{ 181 register char *arg; 182 int i, nhosts = 0; 183 const char *hostname; 184 int nfailed = 0; 185 XHostAddress *list; 186 Bool enabled = False; 187 Display *dpy; 188 189#ifdef USE_GETTEXT 190 const char *domaindir; 191 192 setlocale(LC_ALL, ""); 193 textdomain("xhost"); 194 195 /* mainly for debugging */ 196 if ((domaindir = getenv("TEXTDOMAINDIR")) == NULL) { 197 domaindir = LOCALEDIR; 198 } 199 bindtextdomain("xhost", domaindir); 200#endif 201 202 ProgramName = argv[0]; 203 204 if (argc == 2 && !strcmp(argv[1], "-help")) { 205 fprintf(stderr, gettext("usage: %s [[+-]hostname ...]\n"), argv[0]); 206 exit(1); 207 } 208 209 if ((dpy = XOpenDisplay(NULL)) == NULL) { 210 fprintf(stderr, 211 gettext("%s: unable to open display \"%s\"\n"), 212 ProgramName, XDisplayName (NULL)); 213 exit(1); 214 } 215 216 XSetErrorHandler(local_xerror); 217 218 219 if (argc == 1) { 220 sethostent(1); /* don't close the data base each time */ 221 list = XListHosts(dpy, &nhosts, &enabled); 222 if (enabled) 223 printf (gettext("access control enabled, only authorized clients can connect\n")); 224 else 225 printf (gettext("access control disabled, clients can connect from any host\n")); 226 227 if (nhosts != 0) { 228 for (i = 0; i < nhosts; i++ ) { 229 hostname = get_hostname(&list[i]); 230 if (hostname) { 231 switch (list[i].family) { 232 case FamilyInternet: 233 printf("INET:"); 234 break; 235 case FamilyInternet6: 236 printf("INET6:"); 237 break; 238 case FamilyDECnet: 239 printf("DNET:"); 240 break; 241 case FamilyNetname: 242 printf("NIS:"); 243 break; 244 case FamilyKrb5Principal: 245 printf("KRB:"); 246 break; 247 case FamilyLocalHost: 248 printf("LOCAL:"); 249 break; 250 case FamilyServerInterpreted: 251 printf("SI:"); 252 break; 253 default: 254 printf(gettext("<unknown family type %d>:"), list[i].family); 255 break; 256 } 257 printf ("%s", hostname); 258 } else { 259 printf (gettext("<unknown address in family %d>"), 260 list[i].family); 261 } 262 if (nameserver_timedout) { 263 printf(gettext("\t(no nameserver response within %d seconds)\n"), 264 NAMESERVER_TIMEOUT); 265 nameserver_timedout = 0; 266 } else 267 printf("\n"); 268 } 269 free(list); 270 endhostent(); 271 } 272 exit(0); 273 } 274 275 for (i = 1; i < argc; i++) { 276 arg = argv[i]; 277 if (*arg == '-') { 278 279 if (!argv[i][1] && ((i+1) == argc)) { 280 printf (gettext("access control enabled, only authorized clients can connect\n")); 281 XEnableAccessControl(dpy); 282 } else { 283 arg = argv[i][1]? &argv[i][1] : argv[++i]; 284 if (!change_host (dpy, arg, False)) { 285 fprintf (stderr, gettext("%s: bad hostname \"%s\"\n"), 286 ProgramName, arg); 287 nfailed++; 288 } 289 } 290 } else { 291 if (*arg == '+' && !argv[i][1] && ((i+1) == argc)) { 292 printf (gettext("access control disabled, clients can connect from any host\n")); 293 XDisableAccessControl(dpy); 294 } else { 295 if (*arg == '+') { 296 arg = argv[i][1]? &argv[i][1] : argv[++i]; 297 } 298 if (!change_host (dpy, arg, True)) { 299 fprintf (stderr, gettext("%s: bad hostname \"%s\"\n"), 300 ProgramName, arg); 301 nfailed++; 302 } 303 } 304 } 305 } 306 XCloseDisplay (dpy); /* does an XSync first */ 307 exit(nfailed); 308} 309 310 311 312/* 313 * change_host - edit the list of hosts that may connect to the server; 314 * it parses DECnet names (expo::), Internet addresses (18.30.0.212), or 315 * Internet names (expo.lcs.mit.edu); if 4.3bsd macro h_addr is defined 316 * (from <netdb.h>), it will add or remove all addresses with the given 317 * address. 318 */ 319 320static int 321change_host(Display *dpy, char *name, Bool add) 322{ 323 XHostAddress ha; 324 char *lname; 325 size_t namelen, i; 326 int family = FamilyWild; 327#ifdef K5AUTH 328 krb5_principal princ; 329 krb5_data kbuf; 330#endif 331#ifdef NEEDSOCKETS 332 static struct in_addr addr; /* so we can point at it */ 333#if defined(IPv6) && defined(AF_INET6) 334 static struct in6_addr addr6; /* so we can point at it */ 335#else 336 struct hostent *hp; 337#endif 338#endif 339 char *cp; 340 const char *add_msg = gettext("being added to access control list"); 341 const char *remove_msg = gettext("being removed from access control list"); 342 343 namelen = strlen(name); 344 if ((lname = (char *)malloc(namelen+1)) == NULL) { 345 fprintf (stderr, gettext("%s: malloc bombed in change_host\n"), 346 ProgramName); 347 exit (1); 348 } 349 for (i = 0; i < namelen; i++) { 350 lname[i] = tolower(name[i]); 351 } 352 lname[namelen] = '\0'; 353 if (!strncmp("inet:", lname, 5)) { 354#ifdef TCPCONN 355 family = FamilyInternet; 356 name += 5; 357#else 358 fprintf (stderr, gettext("%s: not compiled for TCP/IP\n"), ProgramName); 359 free(lname); 360 return 0; 361#endif 362 } 363 else if (!strncmp("inet6:", lname, 6)) { 364#if defined(TCPCONN) && defined(IPv6) && defined(AF_INET6) 365 family = FamilyInternet6; 366 name += 6; 367#else 368 fprintf (stderr, gettext("%s: not compiled for IPv6\n"), ProgramName); 369 free(lname); 370 return 0; 371#endif 372 } 373#ifdef ACCEPT_INETV6 /* Allow inetv6 as an alias for inet6 for compatibility 374 with original X11 over IPv6 draft. */ 375 else if (!strncmp("inetv6:", lname, 7)) { 376#if defined(TCPCONN) && defined(IPv6) && defined(AF_INET6) 377 family = FamilyInternet6; 378 name += 7; 379#else 380 fprintf (stderr, gettext("%s: not compiled for IPv6\n"), ProgramName); 381 free(lname); 382 return 0; 383#endif 384 } 385#endif /* ACCEPT_INETV6 */ 386 else if (!strncmp("dnet:", lname, 5)) { 387 fprintf (stderr, gettext("%s: not compiled for DECnet\n"), ProgramName); 388 free(lname); 389 return 0; 390 } 391 else if (!strncmp("nis:", lname, 4)) { 392#ifdef SECURE_RPC 393 family = FamilyNetname; 394 name += 4; 395#else 396 fprintf (stderr, gettext("%s: not compiled for Secure RPC\n"), ProgramName); 397 free(lname); 398 return 0; 399#endif 400 } 401 else if (!strncmp("krb:", lname, 4)) { 402#ifdef K5AUTH 403 family = FamilyKrb5Principal; 404 name +=4; 405#else 406 fprintf (stderr, gettext("%s: not compiled for Kerberos 5\n"), ProgramName); 407 free(lname); 408 return 0; 409#endif 410 } 411 else if (!strncmp("local:", lname, 6)) { 412 family = FamilyLocalHost; 413 } 414 else if (!strncmp("si:", lname, 3)) { 415 family = FamilyServerInterpreted; 416 name += 3; 417 } 418 if (family == FamilyWild && (cp = strchr(lname, ':'))) { 419#ifdef IPv6 420 /* 421 * Check to see if inet_pton() can grok it as an IPv6 address 422 */ 423 if (inet_pton(AF_INET6, lname, &addr6.s6_addr) == 1) { 424 family = FamilyInternet6; 425 } else 426#endif 427 { 428 *cp = '\0'; 429 fprintf (stderr, gettext("%s: unknown address family \"%s\"\n"), 430 ProgramName, lname); 431 free(lname); 432 return 0; 433 } 434 } 435 free(lname); 436 437 if (family == FamilyServerInterpreted) { 438 XServerInterpretedAddress siaddr; 439 int rc; 440 441 cp = strchr(name, ':'); 442 if (cp == NULL || cp == name) { 443 fprintf(stderr, gettext( 444 "%s: type must be specified for server interpreted family \"%s\"\n"), 445 ProgramName, name); 446 return 0; 447 } 448 siaddr.type = name; 449 siaddr.typelength = cp - name; 450 siaddr.value = ++cp; 451 siaddr.valuelength = strlen(cp); 452 ha.family = FamilyServerInterpreted; 453 ha.address = (char *) &siaddr; 454 if (add) 455 rc = XAddHost(dpy, &ha); 456 else 457 rc = XRemoveHost(dpy, &ha); 458 printf( "%s %s%s\n", name, rc == 1 ? "" : "failed when ", 459 add ? add_msg : remove_msg); 460 if (rc != 1) 461 return 0; 462 return 1; 463 } 464 465#ifdef K5AUTH 466 if (family == FamilyKrb5Principal) { 467 krb5_error_code retval; 468 469 retval = krb5_parse_name(name, &princ); 470 if (retval) { 471 krb5_init_ets(); /* init krb errs for error_message() */ 472 fprintf(stderr, gettext("%s: cannot parse Kerberos name: %s\n"), 473 ProgramName, error_message(retval)); 474 return 0; 475 } 476 XauKrb5Encode(princ, &kbuf); 477 ha.length = kbuf.length; 478 ha.address = kbuf.data; 479 ha.family = family; 480 if (add) 481 XAddHost(dpy, &ha); 482 else 483 XRemoveHost(dpy, &ha); 484 krb5_free_principal(princ); 485 free(kbuf.data); 486 printf( "%s %s\n", name, add ? add_msg : remove_msg); 487 return 1; 488 } 489#endif 490 if (family == FamilyLocalHost) { 491 char empty[] = ""; 492 ha.length = 0; 493 ha.address = empty; 494 ha.family = family; 495 if (add) 496 XAddHost(dpy, &ha); 497 else 498 XRemoveHost(dpy, &ha); 499 printf( gettext("non-network local connections %s\n"), add ? add_msg : remove_msg); 500 return 1; 501 } 502 /* 503 * If it has an '@', it's a netname 504 */ 505 if ((family == FamilyNetname && (cp = strchr(name, '@'))) || 506 (cp = strchr(name, '@'))) { 507 char *netname = name; 508#ifdef SECURE_RPC 509 static char username[MAXNETNAMELEN]; 510 511 if (!cp[1]) { 512 struct passwd *pwd; 513 static char domainname[128]; 514 515 *cp = '\0'; 516 pwd = getpwnam(name); 517 if (!pwd) { 518 fprintf(stderr, gettext("no such user \"%s\"\n"), name); 519 return 0; 520 } 521 getdomainname(domainname, sizeof(domainname)); 522 if (!user2netname(username, pwd->pw_uid, domainname)) { 523 fprintf(stderr, gettext("failed to get netname for \"%s\"\n"), name); 524 return 0; 525 } 526 netname = username; 527 } 528#endif 529 ha.family = FamilyNetname; 530 ha.length = strlen(netname); 531 ha.address = netname; 532 if (add) 533 XAddHost (dpy, &ha); 534 else 535 XRemoveHost (dpy, &ha); 536 if (netname != name) 537 printf ("%s@ (%s) %s\n", name, netname, add ? add_msg : remove_msg); 538 else 539 printf ("%s %s\n", netname, add ? add_msg : remove_msg); 540 return 1; 541 } 542#ifdef NEEDSOCKETS 543 /* 544 * First see if inet_aton/inet_addr can grok the name; if so, then use it. 545 */ 546 if (((family == FamilyWild) || (family == FamilyInternet)) && 547#ifdef HAVE_INET_ATON 548 (inet_aton (name, &addr) != 0) 549#else 550 ((addr.s_addr = inet_addr(name)) != -1) 551#endif 552 ) { 553 ha.family = FamilyInternet; 554 ha.length = sizeof(addr.s_addr); 555 ha.address = (char *) &addr.s_addr; 556 if (add) { 557 XAddHost (dpy, &ha); 558 printf ("%s %s\n", name, add_msg); 559 } else { 560 XRemoveHost (dpy, &ha); 561 printf ("%s %s\n", name, remove_msg); 562 } 563 return 1; 564 } 565#if defined(IPv6) && defined(AF_INET6) 566 /* 567 * Check to see if inet_pton() can grok it as an IPv6 address 568 */ 569 else if (((family == FamilyWild) || (family == FamilyInternet6)) && 570 (inet_pton(AF_INET6, name, &addr6.s6_addr) == 1)) { 571 ha.family = FamilyInternet6; 572 ha.length = sizeof(addr6.s6_addr); 573 ha.address = (char *) &addr6.s6_addr; 574 if (add) { 575 XAddHost (dpy, &ha); 576 printf ("%s %s\n", name, add_msg); 577 } else { 578 XRemoveHost (dpy, &ha); 579 printf ("%s %s\n", name, remove_msg); 580 } 581 return 1; 582 } else { 583 /* 584 * Is it in the namespace? 585 * 586 * If no family was specified, use both Internet v4 & v6 addresses. 587 * Otherwise, use only addresses matching specified family. 588 */ 589 struct addrinfo *addresses; 590 struct addrinfo *a; 591 Bool didit = False; 592 593 if (getaddrinfo(name, NULL, NULL, &addresses) != 0) 594 return 0; 595 596 for (a = addresses; a != NULL; a = a->ai_next) { 597 if ( ((a->ai_family == AF_INET) && (family != FamilyInternet6)) 598 || ((a->ai_family == AF_INET6) && (family != FamilyInternet)) ) { 599 char ad[INET6_ADDRSTRLEN]; 600 ha.family = XFamily(a->ai_family); 601 if (a->ai_family == AF_INET6) { 602 ha.address = (char *) 603 &((struct sockaddr_in6 *) a->ai_addr)->sin6_addr; 604 ha.length = 605 sizeof (((struct sockaddr_in6 *) a->ai_addr)->sin6_addr); 606 } else { 607 ha.address = (char *) 608 &((struct sockaddr_in *) a->ai_addr)->sin_addr; 609 ha.length = 610 sizeof (((struct sockaddr_in *) a->ai_addr)->sin_addr); 611 } 612 inet_ntop(a->ai_family, ha.address, ad, sizeof(ad)); 613 /* printf("Family: %d\nLength: %d\n", a->ai_family, ha.length); */ 614 /* printf("Address: %s\n", ad); */ 615 616 if (add) { 617 XAddHost (dpy, &ha); 618 } else { 619 XRemoveHost (dpy, &ha); 620 } 621 didit = True; 622 } 623 } 624 if (didit == True) { 625 printf ("%s %s\n", name, add ? add_msg : remove_msg); 626 } else { 627 const char *familyMsg = ""; 628 629 if (family == FamilyInternet6) { 630 familyMsg = "inet6 "; 631 } else if (family == FamilyInternet) { 632 familyMsg = "inet "; 633 } 634 635 fprintf(stderr, gettext("%s: unable to get %saddress for \"%s\"\n"), 636 ProgramName, familyMsg, name); 637 } 638 freeaddrinfo(addresses); 639 return 1; 640 } 641#else /* !IPv6 */ 642 /* 643 * Is it in the namespace? 644 */ 645 else if (((hp = gethostbyname(name)) == (struct hostent *)NULL) 646 || hp->h_addrtype != AF_INET) { 647 return 0; 648 } else { 649 ha.family = XFamily(hp->h_addrtype); 650 ha.length = hp->h_length; 651#ifdef h_addr /* new 4.3bsd version of gethostent */ 652 { 653 char **list; 654 655 /* iterate over the hosts */ 656 for (list = hp->h_addr_list; *list; list++) { 657 ha.address = *list; 658 if (add) { 659 XAddHost (dpy, &ha); 660 } else { 661 XRemoveHost (dpy, &ha); 662 } 663 } 664 } 665#else 666 ha.address = hp->h_addr; 667 if (add) { 668 XAddHost (dpy, &ha); 669 } else { 670 XRemoveHost (dpy, &ha); 671 } 672#endif 673 printf ("%s %s\n", name, add ? add_msg : remove_msg); 674 return 1; 675 } 676#endif /* IPv6 */ 677#else /* NEEDSOCKETS */ 678 return 0; 679#endif /* NEEDSOCKETS */ 680} 681 682 683/* 684 * get_hostname - Given an internet address, return a name (CHARON.MIT.EDU) 685 * or a string representing the address (18.58.0.13) if the name cannot 686 * be found. 687 */ 688 689 690static const char * 691get_hostname(XHostAddress *ha) 692{ 693#if defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6)) 694 static struct hostent *hp = NULL; 695#endif 696#ifdef K5AUTH 697 krb5_principal princ; 698 krb5_data kbuf; 699 char *kname; 700 static char kname_out[255]; 701#endif 702#ifdef SIGALRM 703 struct sigaction sa; 704#endif 705 706#ifdef TCPCONN 707#if defined(IPv6) && defined(AF_INET6) 708 if ((ha->family == FamilyInternet) || (ha->family == FamilyInternet6)) { 709 struct sockaddr_storage saddr; 710 static char inetname[NI_MAXHOST]; 711 unsigned int saddrlen; 712 713 inetname[0] = '\0'; 714 memset(&saddr, 0, sizeof saddr); 715 if (ha->family == FamilyInternet) { 716 struct sockaddr_in *sin = (struct sockaddr_in *) &saddr; 717#ifdef BSD44SOCKETS 718 sin->sin_len = sizeof(struct sockaddr_in); 719#endif 720 sin->sin_family = AF_INET; 721 sin->sin_port = 0; 722 if (sizeof(sin->sin_addr) > ha->length) 723 return ""; 724 memcpy(&sin->sin_addr, ha->address, sizeof(sin->sin_addr)); 725 saddrlen = sizeof(struct sockaddr_in); 726 } else { 727 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &saddr; 728#ifdef SIN6_LEN 729 sin6->sin6_len = sizeof(struct sockaddr_in6); 730#endif 731 sin6->sin6_family = AF_INET6; 732 sin6->sin6_port = 0; 733 if (sizeof(sin6->sin6_addr) > ha->length) 734 return ""; 735 memcpy(&sin6->sin6_addr, ha->address, sizeof(sin6->sin6_addr)); 736 saddrlen = sizeof(struct sockaddr_in6); 737 } 738 739 /* gethostbyaddr can take a LONG time if the host does not exist. 740 Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 741 that something is wrong and do not make the user wait. 742 gethostbyaddr will continue after a signal, so we have to 743 jump out of it. 744 */ 745#ifdef SIGALRM 746 memset(&sa, 0, sizeof sa); 747 sa.sa_handler = nameserver_lost; 748 sa.sa_flags = 0; /* don't restart syscalls */ 749 sigaction(SIGALRM, &sa, NULL); 750 alarm(NAMESERVER_TIMEOUT); 751#endif 752 getnameinfo((struct sockaddr *) &saddr, saddrlen, inetname, 753 sizeof(inetname), NULL, 0, 0); 754#ifdef SIGALRM 755 alarm(0); 756#endif 757 if (nameserver_timedout || inetname[0] == '\0') 758 inet_ntop(((struct sockaddr *)&saddr)->sa_family, ha->address, 759 inetname, sizeof(inetname)); 760 return inetname; 761 } 762#else 763 if (ha->family == FamilyInternet) { 764 /* gethostbyaddr can take a LONG time if the host does not exist. 765 Assume that if it does not respond in NAMESERVER_TIMEOUT seconds 766 that something is wrong and do not make the user wait. 767 gethostbyaddr will continue after a signal, so we have to 768 jump out of it. 769 */ 770#ifdef SIGALRM 771 memset(&sa, 0, sizeof sa); 772 sa.sa_handler = nameserver_lost; 773 sa.sa_flags = 0; /* don't restart syscalls */ 774 sigaction(SIGALRM, &sa, NULL); 775 alarm(4); 776#endif 777 hp = gethostbyaddr (ha->address, ha->length, AF_INET); 778#ifdef SIGALRM 779 alarm(0); 780#endif 781 if (hp) 782 return (hp->h_name); 783 else return (inet_ntoa(*((struct in_addr *)(ha->address)))); 784 } 785#endif /* IPv6 */ 786#endif 787 if (ha->family == FamilyNetname) { 788 static char netname[512]; 789 int len; 790#ifdef SECURE_RPC 791 int gidlen; 792 uid_t uid; 793 gid_t gid, gidlist[NGROUPS_MAX]; 794#endif 795 796 if (ha->length < sizeof(netname) - 1) 797 len = ha->length; 798 else 799 len = sizeof(netname) - 1; 800 memmove( netname, ha->address, len); 801 netname[len] = '\0'; 802#ifdef SECURE_RPC 803 if (netname2user(netname, &uid, &gid, &gidlen, gidlist)) { 804 struct passwd *pwd; 805 806 pwd = getpwuid(uid); 807 if (pwd) 808 snprintf(netname, sizeof(netname), "%s@ (%*.*s)", 809 pwd->pw_name, ha->length, ha->length, ha->address); 810 } 811#endif 812 return (netname); 813 } 814#ifdef K5AUTH 815 if (ha->family == FamilyKrb5Principal) { 816 kbuf.data = ha->address; 817 kbuf.length = ha->length; 818 XauKrb5Decode(kbuf, &princ); 819 krb5_unparse_name(princ, &kname); 820 krb5_free_principal(princ); 821 strncpy(kname_out, kname, sizeof (kname_out)); 822 free(kname); 823 return kname_out; 824 } 825#endif 826 if (ha->family == FamilyLocalHost) { 827 return ""; 828 } 829 if (ha->family == FamilyServerInterpreted) { 830 XServerInterpretedAddress *sip; 831 static char *addressString; 832 static size_t addressStringSize; 833 size_t neededSize; 834 835 sip = (XServerInterpretedAddress *) ha->address; 836 neededSize = sip->typelength + sip->valuelength + 2; 837 838 if (addressStringSize < neededSize) { 839 if (addressString != NULL) { 840 free(addressString); 841 } 842 addressStringSize = neededSize; 843 addressString = malloc(addressStringSize); 844 } 845 if (addressString != NULL) { 846 char *cp = addressString; 847 848 memcpy(cp, sip->type, sip->typelength); 849 cp += sip->typelength; 850 *cp++ = ':'; 851 memcpy(cp, sip->value, sip->valuelength); 852 cp += sip->valuelength; 853 *cp = '\0'; 854 } 855 return addressString; 856 } 857 return (NULL); 858} 859 860/*ARGUSED*/ 861static void 862nameserver_lost(_X_UNUSED int sig) 863{ 864 nameserver_timedout = 1; 865} 866 867/* 868 * local_xerror - local non-fatal error handling routine. If the error was 869 * that an X_GetHosts request for an unknown address format was received, just 870 * return, otherwise print the normal error message and continue. 871 */ 872static int 873local_xerror(Display *dpy, XErrorEvent *rep) 874{ 875 if ((rep->error_code == BadAccess) && (rep->request_code == X_ChangeHosts)) { 876 fprintf (stderr, 877 gettext("%s: must be on local machine to add or remove hosts.\n"), 878 ProgramName); 879 return 1; 880 } else if ((rep->error_code == BadAccess) && 881 (rep->request_code == X_SetAccessControl)) { 882 fprintf (stderr, 883 gettext("%s: must be on local machine to enable or disable access control.\n"), 884 ProgramName); 885 return 1; 886 } else if ((rep->error_code == BadValue) && 887 (rep->request_code == X_ListHosts)) { 888 return 1; 889 } 890 891 XmuPrintDefaultErrorMessage (dpy, rep, stderr); 892 return 0; 893} 894