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