1 /* $NetBSD: gethnamaddr.c,v 1.40 2001/04/26 12:55:32 kleink Exp $ */ 2 3 /* 4 * ++Copyright++ 1985, 1988, 1993 5 * - 6 * Copyright (c) 1985, 1988, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * - 37 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 38 * 39 * Permission to use, copy, modify, and distribute this software for any 40 * purpose with or without fee is hereby granted, provided that the above 41 * copyright notice and this permission notice appear in all copies, and that 42 * the name of Digital Equipment Corporation not be used in advertising or 43 * publicity pertaining to distribution of the document or software without 44 * specific, written prior permission. 45 * 46 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 47 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 49 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 50 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 51 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 52 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 53 * SOFTWARE. 54 * - 55 * --Copyright-- 56 */ 57 58 #include <sys/cdefs.h> 59 #if defined(LIBC_SCCS) && !defined(lint) 60 #if 0 61 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 62 static char rcsid[] = "Id: gethnamaddr.c,v 8.21 1997/06/01 20:34:37 vixie Exp "; 63 #else 64 __RCSID("$NetBSD: gethnamaddr.c,v 1.40 2001/04/26 12:55:32 kleink Exp $"); 65 #endif 66 #endif /* LIBC_SCCS and not lint */ 67 68 #if defined(_LIBC) 69 #include "namespace.h" 70 #endif 71 #include <sys/param.h> 72 #include <sys/socket.h> 73 #include <netinet/in.h> 74 #include <arpa/inet.h> 75 #include <arpa/nameser.h> 76 77 #include <assert.h> 78 #include <ctype.h> 79 #include <errno.h> 80 #include <netdb.h> 81 #include <resolv.h> 82 #include <stdio.h> 83 #include <syslog.h> 84 85 #ifdef __STDC__ 86 #include <stdarg.h> 87 #else 88 #include <varargs.h> 89 #endif 90 91 #ifndef LOG_AUTH 92 # define LOG_AUTH 0 93 #endif 94 95 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 96 97 #include <nsswitch.h> 98 #include <stdlib.h> 99 #include <string.h> 100 101 #ifdef YP 102 #include <rpc/rpc.h> 103 #include <rpcsvc/yp_prot.h> 104 #include <rpcsvc/ypclnt.h> 105 #endif 106 107 #if defined(_LIBC) && defined(__weak_alias) 108 __weak_alias(gethostbyaddr,_gethostbyaddr) 109 __weak_alias(gethostbyname,_gethostbyname) 110 #endif 111 112 #define MAXALIASES 35 113 #define MAXADDRS 35 114 115 static const char AskedForGot[] = 116 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 117 118 static char *h_addr_ptrs[MAXADDRS + 1]; 119 120 #ifdef YP 121 static char *__ypdomain; 122 #endif 123 124 static struct hostent host; 125 static char *host_aliases[MAXALIASES]; 126 static char hostbuf[8*1024]; 127 static u_int32_t host_addr[16 / sizeof(u_int32_t)]; /* IPv4 or IPv6 */ 128 static FILE *hostf = NULL; 129 static int stayopen = 0; 130 131 132 #if PACKETSZ > 1024 133 #define MAXPACKET PACKETSZ 134 #else 135 #define MAXPACKET 1024 136 #endif 137 138 typedef union { 139 HEADER hdr; 140 u_char buf[MAXPACKET]; 141 } querybuf; 142 143 typedef union { 144 int32_t al; 145 char ac; 146 } align; 147 148 #ifdef DEBUG 149 static void dprintf __P((char *, ...)) 150 __attribute__((__format__(__printf__, 1, 2))); 151 #endif 152 static struct hostent *getanswer __P((const querybuf *, int, 153 const char *, int)); 154 static void map_v4v6_address __P((const char *, char *)); 155 static void map_v4v6_hostent __P((struct hostent *, char **, int *)); 156 #ifdef RESOLVSORT 157 static void addrsort __P((char **, int)); 158 #endif 159 160 void _sethtent __P((int)); 161 void _endhtent __P((void)); 162 struct hostent *_gethtent __P((void)); 163 struct hostent *_gethtbyname2 __P((const char *, int)); 164 void ht_sethostent __P((int)); 165 void ht_endhostent __P((void)); 166 struct hostent *ht_gethostbyname __P((char *)); 167 struct hostent *ht_gethostbyaddr __P((const char *, int, int )); 168 void dns_service __P((void)); 169 #undef dn_skipname 170 int dn_skipname __P((const u_char *, const u_char *)); 171 int _gethtbyaddr __P((void *, void *, va_list)); 172 int _gethtbyname __P((void *, void *, va_list)); 173 int _dns_gethtbyaddr __P((void *, void *, va_list)); 174 int _dns_gethtbyname __P((void *, void *, va_list)); 175 #ifdef YP 176 struct hostent *_yphostent __P((char *, int)); 177 int _yp_gethtbyaddr __P((void *, void *, va_list)); 178 int _yp_gethtbyname __P((void *, void *, va_list)); 179 #endif 180 181 static const ns_src default_dns_files[] = { 182 { NSSRC_FILES, NS_SUCCESS }, 183 { NSSRC_DNS, NS_SUCCESS }, 184 { 0 } 185 }; 186 187 188 #ifdef DEBUG 189 static void 190 dprintf(char *msg, ...) 191 { 192 _DIAGASSERT(msg != NULL); 193 194 if (_res.options & RES_DEBUG) { 195 int save = errno; 196 va_list ap; 197 198 va_start (ap, msg); 199 vprintf(msg, ap); 200 va_end (ap); 201 202 errno = save; 203 } 204 } 205 #else 206 # define dprintf(msg, num) /*nada*/ 207 #endif 208 209 #define BOUNDED_INCR(x) \ 210 do { \ 211 cp += x; \ 212 if (cp > eom) { \ 213 h_errno = NO_RECOVERY; \ 214 return (NULL); \ 215 } \ 216 } while (/*CONSTCOND*/0) 217 218 #define BOUNDS_CHECK(ptr, count) \ 219 do { \ 220 if ((ptr) + (count) > eom) { \ 221 h_errno = NO_RECOVERY; \ 222 return (NULL); \ 223 } \ 224 } while (/*CONSTCOND*/0) 225 226 static struct hostent * 227 getanswer(answer, anslen, qname, qtype) 228 const querybuf *answer; 229 int anslen; 230 const char *qname; 231 int qtype; 232 { 233 const HEADER *hp; 234 const u_char *cp; 235 int n; 236 const u_char *eom, *erdata; 237 char *bp, **ap, **hap; 238 int type, class, buflen, ancount, qdcount; 239 int haveanswer, had_error; 240 int toobig = 0; 241 char tbuf[MAXDNAME]; 242 const char *tname; 243 int (*name_ok) __P((const char *)); 244 245 _DIAGASSERT(answer != NULL); 246 _DIAGASSERT(qname != NULL); 247 248 tname = qname; 249 host.h_name = NULL; 250 eom = answer->buf + anslen; 251 switch (qtype) { 252 case T_A: 253 case T_AAAA: 254 name_ok = res_hnok; 255 break; 256 case T_PTR: 257 name_ok = res_dnok; 258 break; 259 default: 260 return (NULL); /* XXX should be abort(); */ 261 } 262 /* 263 * find first satisfactory answer 264 */ 265 hp = &answer->hdr; 266 ancount = ntohs(hp->ancount); 267 qdcount = ntohs(hp->qdcount); 268 bp = hostbuf; 269 buflen = sizeof hostbuf; 270 cp = answer->buf; 271 BOUNDED_INCR(HFIXEDSZ); 272 if (qdcount != 1) { 273 h_errno = NO_RECOVERY; 274 return (NULL); 275 } 276 n = dn_expand(answer->buf, eom, cp, bp, buflen); 277 if ((n < 0) || !(*name_ok)(bp)) { 278 h_errno = NO_RECOVERY; 279 return (NULL); 280 } 281 BOUNDED_INCR(n + QFIXEDSZ); 282 if (qtype == T_A || qtype == T_AAAA) { 283 /* res_send() has already verified that the query name is the 284 * same as the one we sent; this just gets the expanded name 285 * (i.e., with the succeeding search-domain tacked on). 286 */ 287 n = strlen(bp) + 1; /* for the \0 */ 288 if (n >= MAXHOSTNAMELEN) { 289 h_errno = NO_RECOVERY; 290 return (NULL); 291 } 292 host.h_name = bp; 293 bp += n; 294 buflen -= n; 295 /* The qname can be abbreviated, but h_name is now absolute. */ 296 qname = host.h_name; 297 } 298 ap = host_aliases; 299 *ap = NULL; 300 host.h_aliases = host_aliases; 301 hap = h_addr_ptrs; 302 *hap = NULL; 303 host.h_addr_list = h_addr_ptrs; 304 haveanswer = 0; 305 had_error = 0; 306 while (ancount-- > 0 && cp < eom && !had_error) { 307 n = dn_expand(answer->buf, eom, cp, bp, buflen); 308 if ((n < 0) || !(*name_ok)(bp)) { 309 had_error++; 310 continue; 311 } 312 cp += n; /* name */ 313 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 314 type = _getshort(cp); 315 cp += INT16SZ; /* type */ 316 class = _getshort(cp); 317 cp += INT16SZ + INT32SZ; /* class, TTL */ 318 n = _getshort(cp); 319 cp += INT16SZ; /* len */ 320 BOUNDS_CHECK(cp, n); 321 erdata = cp + n; 322 if (class != C_IN) { 323 /* XXX - debug? syslog? */ 324 cp += n; 325 continue; /* XXX - had_error++ ? */ 326 } 327 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 328 if (ap >= &host_aliases[MAXALIASES-1]) 329 continue; 330 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 331 if ((n < 0) || !(*name_ok)(tbuf)) { 332 had_error++; 333 continue; 334 } 335 cp += n; 336 if (cp != erdata) { 337 h_errno = NO_RECOVERY; 338 return (NULL); 339 } 340 /* Store alias. */ 341 *ap++ = bp; 342 n = strlen(bp) + 1; /* for the \0 */ 343 if (n >= MAXHOSTNAMELEN) { 344 had_error++; 345 continue; 346 } 347 bp += n; 348 buflen -= n; 349 /* Get canonical name. */ 350 n = strlen(tbuf) + 1; /* for the \0 */ 351 if (n > buflen || n >= MAXHOSTNAMELEN) { 352 had_error++; 353 continue; 354 } 355 strcpy(bp, tbuf); 356 host.h_name = bp; 357 bp += n; 358 buflen -= n; 359 continue; 360 } 361 if (qtype == T_PTR && type == T_CNAME) { 362 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 363 if (n < 0 || !res_dnok(tbuf)) { 364 had_error++; 365 continue; 366 } 367 cp += n; 368 if (cp != erdata) { 369 h_errno = NO_RECOVERY; 370 return (NULL); 371 } 372 /* Get canonical name. */ 373 n = strlen(tbuf) + 1; /* for the \0 */ 374 if (n > buflen || n >= MAXHOSTNAMELEN) { 375 had_error++; 376 continue; 377 } 378 strcpy(bp, tbuf); 379 tname = bp; 380 bp += n; 381 buflen -= n; 382 continue; 383 } 384 if (type != qtype) { 385 if (type != T_KEY && type != T_SIG) 386 syslog(LOG_NOTICE|LOG_AUTH, 387 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 388 qname, p_class(C_IN), p_type(qtype), 389 p_type(type)); 390 cp += n; 391 continue; /* XXX - had_error++ ? */ 392 } 393 switch (type) { 394 case T_PTR: 395 if (strcasecmp(tname, bp) != 0) { 396 syslog(LOG_NOTICE|LOG_AUTH, 397 AskedForGot, qname, bp); 398 cp += n; 399 continue; /* XXX - had_error++ ? */ 400 } 401 n = dn_expand(answer->buf, eom, cp, bp, buflen); 402 if ((n < 0) || !res_hnok(bp)) { 403 had_error++; 404 break; 405 } 406 #if MULTI_PTRS_ARE_ALIASES 407 cp += n; 408 if (cp != erdata) { 409 h_errno = NO_RECOVERY; 410 return (NULL); 411 } 412 if (!haveanswer) 413 host.h_name = bp; 414 else if (ap < &host_aliases[MAXALIASES-1]) 415 *ap++ = bp; 416 else 417 n = -1; 418 if (n != -1) { 419 n = strlen(bp) + 1; /* for the \0 */ 420 if (n >= MAXHOSTNAMELEN) { 421 had_error++; 422 break; 423 } 424 bp += n; 425 buflen -= n; 426 } 427 break; 428 #else 429 host.h_name = bp; 430 if (_res.options & RES_USE_INET6) { 431 n = strlen(bp) + 1; /* for the \0 */ 432 if (n >= MAXHOSTNAMELEN) { 433 had_error++; 434 break; 435 } 436 bp += n; 437 buflen -= n; 438 map_v4v6_hostent(&host, &bp, &buflen); 439 } 440 h_errno = NETDB_SUCCESS; 441 return (&host); 442 #endif 443 case T_A: 444 case T_AAAA: 445 if (strcasecmp(host.h_name, bp) != 0) { 446 syslog(LOG_NOTICE|LOG_AUTH, 447 AskedForGot, host.h_name, bp); 448 cp += n; 449 continue; /* XXX - had_error++ ? */ 450 } 451 if (n != host.h_length) { 452 cp += n; 453 continue; 454 } 455 if (!haveanswer) { 456 int nn; 457 458 host.h_name = bp; 459 nn = strlen(bp) + 1; /* for the \0 */ 460 bp += nn; 461 buflen -= nn; 462 } 463 464 bp += sizeof(align) - 465 (size_t)((u_long)bp % sizeof(align)); 466 467 if (bp + n >= &hostbuf[sizeof hostbuf]) { 468 dprintf("size (%d) too big\n", n); 469 had_error++; 470 continue; 471 } 472 if (hap >= &h_addr_ptrs[MAXADDRS-1]) { 473 if (!toobig++) 474 dprintf("Too many addresses (%d)\n", 475 MAXADDRS); 476 cp += n; 477 continue; 478 } 479 (void)memcpy(*hap++ = bp, cp, (size_t)n); 480 bp += n; 481 buflen -= n; 482 cp += n; 483 if (cp != erdata) { 484 h_errno = NO_RECOVERY; 485 return (NULL); 486 } 487 break; 488 default: 489 abort(); 490 } 491 if (!had_error) 492 haveanswer++; 493 } 494 if (haveanswer) { 495 *ap = NULL; 496 *hap = NULL; 497 # if defined(RESOLVSORT) 498 /* 499 * Note: we sort even if host can take only one address 500 * in its return structures - should give it the "best" 501 * address in that case, not some random one 502 */ 503 if (_res.nsort && haveanswer > 1 && qtype == T_A) 504 addrsort(h_addr_ptrs, haveanswer); 505 # endif /*RESOLVSORT*/ 506 if (!host.h_name) { 507 n = strlen(qname) + 1; /* for the \0 */ 508 if (n > buflen || n >= MAXHOSTNAMELEN) 509 goto no_recovery; 510 strcpy(bp, qname); 511 host.h_name = bp; 512 bp += n; 513 buflen -= n; 514 } 515 if (_res.options & RES_USE_INET6) 516 map_v4v6_hostent(&host, &bp, &buflen); 517 h_errno = NETDB_SUCCESS; 518 return (&host); 519 } 520 no_recovery: 521 h_errno = NO_RECOVERY; 522 return (NULL); 523 } 524 525 struct hostent * 526 gethostbyname(name) 527 const char *name; 528 { 529 struct hostent *hp; 530 531 _DIAGASSERT(name != NULL); 532 533 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 534 h_errno = NETDB_INTERNAL; 535 return (NULL); 536 } 537 if (_res.options & RES_USE_INET6) { 538 hp = gethostbyname2(name, AF_INET6); 539 if (hp) 540 return (hp); 541 } 542 return (gethostbyname2(name, AF_INET)); 543 } 544 545 struct hostent * 546 gethostbyname2(name, af) 547 const char *name; 548 int af; 549 { 550 const char *cp; 551 char *bp; 552 int size, len; 553 struct hostent *hp; 554 static const ns_dtab dtab[] = { 555 NS_FILES_CB(_gethtbyname, NULL) 556 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */ 557 NS_NIS_CB(_yp_gethtbyname, NULL) 558 { 0 } 559 }; 560 561 _DIAGASSERT(name != NULL); 562 563 switch (af) { 564 case AF_INET: 565 size = INADDRSZ; 566 break; 567 case AF_INET6: 568 size = IN6ADDRSZ; 569 break; 570 default: 571 h_errno = NETDB_INTERNAL; 572 errno = EAFNOSUPPORT; 573 return (NULL); 574 } 575 576 host.h_addrtype = af; 577 host.h_length = size; 578 579 /* 580 * if there aren't any dots, it could be a user-level alias. 581 * this is also done in res_query() since we are not the only 582 * function that looks up host names. 583 */ 584 if (!strchr(name, '.') && (cp = __hostalias(name))) 585 name = cp; 586 587 /* 588 * disallow names consisting only of digits/dots, unless 589 * they end in a dot. 590 */ 591 if (isdigit((u_char) name[0])) 592 for (cp = name;; ++cp) { 593 if (!*cp) { 594 if (*--cp == '.') 595 break; 596 /* 597 * All-numeric, no dot at the end. 598 * Fake up a hostent as if we'd actually 599 * done a lookup. 600 */ 601 if (inet_pton(af, name, 602 (char *)(void *)host_addr) <= 0) { 603 h_errno = HOST_NOT_FOUND; 604 return (NULL); 605 } 606 strncpy(hostbuf, name, MAXDNAME); 607 hostbuf[MAXDNAME] = '\0'; 608 bp = hostbuf + MAXDNAME; 609 len = sizeof hostbuf - MAXDNAME; 610 host.h_name = hostbuf; 611 host.h_aliases = host_aliases; 612 host_aliases[0] = NULL; 613 h_addr_ptrs[0] = (char *)(void *)host_addr; 614 h_addr_ptrs[1] = NULL; 615 host.h_addr_list = h_addr_ptrs; 616 if (_res.options & RES_USE_INET6) 617 map_v4v6_hostent(&host, &bp, &len); 618 h_errno = NETDB_SUCCESS; 619 return (&host); 620 } 621 if (!isdigit((u_char) *cp) && *cp != '.') 622 break; 623 } 624 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || 625 name[0] == ':') 626 for (cp = name;; ++cp) { 627 if (!*cp) { 628 if (*--cp == '.') 629 break; 630 /* 631 * All-IPv6-legal, no dot at the end. 632 * Fake up a hostent as if we'd actually 633 * done a lookup. 634 */ 635 if (inet_pton(af, name, 636 (char *)(void *)host_addr) <= 0) { 637 h_errno = HOST_NOT_FOUND; 638 return (NULL); 639 } 640 strncpy(hostbuf, name, MAXDNAME); 641 hostbuf[MAXDNAME] = '\0'; 642 bp = hostbuf + MAXDNAME; 643 len = sizeof hostbuf - MAXDNAME; 644 host.h_name = hostbuf; 645 host.h_aliases = host_aliases; 646 host_aliases[0] = NULL; 647 h_addr_ptrs[0] = (char *)(void *)host_addr; 648 h_addr_ptrs[1] = NULL; 649 host.h_addr_list = h_addr_ptrs; 650 h_errno = NETDB_SUCCESS; 651 return (&host); 652 } 653 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') 654 break; 655 } 656 657 hp = (struct hostent *)NULL; 658 h_errno = NETDB_INTERNAL; 659 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname", 660 default_dns_files, name, len, af) != NS_SUCCESS) 661 return (struct hostent *)NULL; 662 h_errno = NETDB_SUCCESS; 663 return (hp); 664 } 665 666 struct hostent * 667 gethostbyaddr(addr, len, af) 668 const char *addr; /* XXX should have been def'd as u_char! */ 669 socklen_t len; 670 int af; 671 { 672 const u_char *uaddr = (const u_char *)addr; 673 int size; 674 struct hostent *hp; 675 static const ns_dtab dtab[] = { 676 NS_FILES_CB(_gethtbyaddr, NULL) 677 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */ 678 NS_NIS_CB(_yp_gethtbyaddr, NULL) 679 { 0 } 680 }; 681 682 _DIAGASSERT(addr != NULL); 683 684 if (af == AF_INET6 && len == IN6ADDRSZ && 685 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) || 686 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) { 687 /* Unmap. */ 688 addr += IN6ADDRSZ - INADDRSZ; 689 uaddr += IN6ADDRSZ - INADDRSZ; 690 af = AF_INET; 691 len = INADDRSZ; 692 } 693 switch (af) { 694 case AF_INET: 695 size = INADDRSZ; 696 break; 697 case AF_INET6: 698 size = IN6ADDRSZ; 699 break; 700 default: 701 errno = EAFNOSUPPORT; 702 h_errno = NETDB_INTERNAL; 703 return (NULL); 704 } 705 if (size != len) { 706 errno = EINVAL; 707 h_errno = NETDB_INTERNAL; 708 return (NULL); 709 } 710 hp = (struct hostent *)NULL; 711 h_errno = NETDB_INTERNAL; 712 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr", 713 default_dns_files, uaddr, len, af) != NS_SUCCESS) 714 return (struct hostent *)NULL; 715 h_errno = NETDB_SUCCESS; 716 return (hp); 717 } 718 719 void 720 _sethtent(f) 721 int f; 722 { 723 if (!hostf) 724 hostf = fopen(_PATH_HOSTS, "r" ); 725 else 726 rewind(hostf); 727 stayopen = f; 728 } 729 730 void 731 _endhtent() 732 { 733 if (hostf && !stayopen) { 734 (void) fclose(hostf); 735 hostf = NULL; 736 } 737 } 738 739 struct hostent * 740 _gethtent() 741 { 742 char *p; 743 char *cp, **q; 744 int af, len; 745 746 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { 747 h_errno = NETDB_INTERNAL; 748 return (NULL); 749 } 750 again: 751 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { 752 h_errno = HOST_NOT_FOUND; 753 return (NULL); 754 } 755 if (*p == '#') 756 goto again; 757 if (!(cp = strpbrk(p, "#\n"))) 758 goto again; 759 *cp = '\0'; 760 if (!(cp = strpbrk(p, " \t"))) 761 goto again; 762 *cp++ = '\0'; 763 if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) { 764 af = AF_INET6; 765 len = IN6ADDRSZ; 766 } else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) { 767 if (_res.options & RES_USE_INET6) { 768 map_v4v6_address((char *)(void *)host_addr, 769 (char *)(void *)host_addr); 770 af = AF_INET6; 771 len = IN6ADDRSZ; 772 } else { 773 af = AF_INET; 774 len = INADDRSZ; 775 } 776 } else { 777 goto again; 778 } 779 /* if this is not something we're looking for, skip it. */ 780 if (host.h_addrtype != af) 781 goto again; 782 if (host.h_length != len) 783 goto again; 784 h_addr_ptrs[0] = (char *)(void *)host_addr; 785 h_addr_ptrs[1] = NULL; 786 host.h_addr_list = h_addr_ptrs; 787 host.h_length = len; 788 host.h_addrtype = af; 789 while (*cp == ' ' || *cp == '\t') 790 cp++; 791 host.h_name = cp; 792 q = host.h_aliases = host_aliases; 793 if ((cp = strpbrk(cp, " \t")) != NULL) 794 *cp++ = '\0'; 795 while (cp && *cp) { 796 if (*cp == ' ' || *cp == '\t') { 797 cp++; 798 continue; 799 } 800 if (q < &host_aliases[MAXALIASES - 1]) 801 *q++ = cp; 802 if ((cp = strpbrk(cp, " \t")) != NULL) 803 *cp++ = '\0'; 804 } 805 *q = NULL; 806 h_errno = NETDB_SUCCESS; 807 return (&host); 808 } 809 810 /*ARGSUSED*/ 811 int 812 _gethtbyname(rv, cb_data, ap) 813 void *rv; 814 void *cb_data; 815 va_list ap; 816 { 817 struct hostent *hp; 818 const char *name; 819 int af; 820 821 _DIAGASSERT(rv != NULL); 822 823 name = va_arg(ap, char *); 824 /* NOSTRICT skip len */(void)va_arg(ap, int); 825 af = va_arg(ap, int); 826 827 hp = NULL; 828 #if 0 829 if (_res.options & RES_USE_INET6) 830 hp = _gethtbyname2(name, AF_INET6); 831 if (hp==NULL) 832 hp = _gethtbyname2(name, AF_INET); 833 #else 834 hp = _gethtbyname2(name, af); 835 #endif 836 *((struct hostent **)rv) = hp; 837 if (hp==NULL) { 838 h_errno = HOST_NOT_FOUND; 839 return NS_NOTFOUND; 840 } 841 return NS_SUCCESS; 842 } 843 844 struct hostent * 845 _gethtbyname2(name, af) 846 const char *name; 847 int af; 848 { 849 struct hostent *p; 850 char *tmpbuf, *ptr, **cp; 851 int num; 852 size_t len; 853 854 _DIAGASSERT(name != NULL); 855 856 _sethtent(0); 857 ptr = tmpbuf = NULL; 858 num = 0; 859 while ((p = _gethtent()) != NULL && num < MAXADDRS) { 860 if (p->h_addrtype != af) 861 continue; 862 if (strcasecmp(p->h_name, name) != 0) { 863 for (cp = p->h_aliases; *cp != NULL; cp++) 864 if (strcasecmp(*cp, name) == 0) 865 break; 866 if (*cp == NULL) continue; 867 } 868 869 if (num == 0) { 870 size_t bufsize; 871 char *src; 872 873 bufsize = strlen(p->h_name) + 2 + 874 MAXADDRS * p->h_length + 875 ALIGNBYTES; 876 for (cp = p->h_aliases; *cp != NULL; cp++) 877 bufsize += strlen(*cp) + 1; 878 879 if ((tmpbuf = malloc(bufsize)) == NULL) { 880 h_errno = NETDB_INTERNAL; 881 return NULL; 882 } 883 884 ptr = tmpbuf; 885 src = p->h_name; 886 while ((*ptr++ = *src++) != '\0'); 887 for (cp = p->h_aliases; *cp != NULL; cp++) { 888 src = *cp; 889 while ((*ptr++ = *src++) != '\0'); 890 } 891 *ptr++ = '\0'; 892 893 ptr = (char *)(void *)ALIGN(ptr); 894 } 895 896 (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length); 897 ptr += p->h_length; 898 num++; 899 } 900 _endhtent(); 901 if (num == 0) return NULL; 902 903 len = ptr - tmpbuf; 904 if (len > (sizeof(hostbuf) - ALIGNBYTES)) { 905 free(tmpbuf); 906 errno = ENOSPC; 907 h_errno = NETDB_INTERNAL; 908 return NULL; 909 } 910 ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len); 911 free(tmpbuf); 912 913 host.h_name = ptr; 914 while (*ptr++); 915 916 cp = host_aliases; 917 while (*ptr) { 918 *cp++ = ptr; 919 while (*ptr++); 920 } 921 ptr++; 922 *cp = NULL; 923 924 ptr = (char *)(void *)ALIGN(ptr); 925 cp = h_addr_ptrs; 926 while (num--) { 927 *cp++ = ptr; 928 ptr += host.h_length; 929 } 930 *cp = NULL; 931 932 return (&host); 933 } 934 935 /*ARGSUSED*/ 936 int 937 _gethtbyaddr(rv, cb_data, ap) 938 void *rv; 939 void *cb_data; 940 va_list ap; 941 { 942 struct hostent *p; 943 const unsigned char *addr; 944 int len, af; 945 946 _DIAGASSERT(rv != NULL); 947 948 addr = va_arg(ap, unsigned char *); 949 len = va_arg(ap, int); 950 af = va_arg(ap, int); 951 952 host.h_length = len; 953 host.h_addrtype = af; 954 955 _sethtent(0); 956 while ((p = _gethtent()) != NULL) 957 if (p->h_addrtype == af && !memcmp(p->h_addr, addr, 958 (size_t)len)) 959 break; 960 _endhtent(); 961 *((struct hostent **)rv) = p; 962 if (p==NULL) { 963 h_errno = HOST_NOT_FOUND; 964 return NS_NOTFOUND; 965 } 966 return NS_SUCCESS; 967 } 968 969 static void 970 map_v4v6_address(src, dst) 971 const char *src; 972 char *dst; 973 { 974 u_char *p = (u_char *)dst; 975 char tmp[INADDRSZ]; 976 int i; 977 978 _DIAGASSERT(src != NULL); 979 _DIAGASSERT(dst != NULL); 980 981 /* Stash a temporary copy so our caller can update in place. */ 982 (void)memcpy(tmp, src, INADDRSZ); 983 /* Mark this ipv6 addr as a mapped ipv4. */ 984 for (i = 0; i < 10; i++) 985 *p++ = 0x00; 986 *p++ = 0xff; 987 *p++ = 0xff; 988 /* Retrieve the saved copy and we're done. */ 989 (void)memcpy((void *)p, tmp, INADDRSZ); 990 } 991 992 static void 993 map_v4v6_hostent(hp, bpp, lenp) 994 struct hostent *hp; 995 char **bpp; 996 int *lenp; 997 { 998 char **ap; 999 1000 _DIAGASSERT(hp != NULL); 1001 _DIAGASSERT(bpp != NULL); 1002 _DIAGASSERT(lenp != NULL); 1003 1004 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 1005 return; 1006 hp->h_addrtype = AF_INET6; 1007 hp->h_length = IN6ADDRSZ; 1008 for (ap = hp->h_addr_list; *ap; ap++) { 1009 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align)); 1010 1011 if (*lenp < (i + IN6ADDRSZ)) { 1012 /* Out of memory. Truncate address list here. XXX */ 1013 *ap = NULL; 1014 return; 1015 } 1016 *bpp += i; 1017 *lenp -= i; 1018 map_v4v6_address(*ap, *bpp); 1019 *ap = *bpp; 1020 *bpp += IN6ADDRSZ; 1021 *lenp -= IN6ADDRSZ; 1022 } 1023 } 1024 1025 #ifdef RESOLVSORT 1026 static void 1027 addrsort(ap, num) 1028 char **ap; 1029 int num; 1030 { 1031 int i, j; 1032 char **p; 1033 short aval[MAXADDRS]; 1034 int needsort = 0; 1035 1036 _DIAGASSERT(ap != NULL); 1037 1038 p = ap; 1039 for (i = 0; i < num; i++, p++) { 1040 for (j = 0 ; (unsigned)j < _res.nsort; j++) 1041 if (_res.sort_list[j].addr.s_addr == 1042 (((struct in_addr *)(void *)(*p))->s_addr & 1043 _res.sort_list[j].mask)) 1044 break; 1045 aval[i] = j; 1046 if (needsort == 0 && i > 0 && j < aval[i-1]) 1047 needsort = i; 1048 } 1049 if (!needsort) 1050 return; 1051 1052 while (needsort < num) { 1053 for (j = needsort - 1; j >= 0; j--) { 1054 if (aval[j] > aval[j+1]) { 1055 char *hp; 1056 1057 i = aval[j]; 1058 aval[j] = aval[j+1]; 1059 aval[j+1] = i; 1060 1061 hp = ap[j]; 1062 ap[j] = ap[j+1]; 1063 ap[j+1] = hp; 1064 1065 } else 1066 break; 1067 } 1068 needsort++; 1069 } 1070 } 1071 #endif 1072 1073 #if defined(BSD43_BSD43_NFS) || defined(sun) 1074 /* XXX: should we remove this cruft? - lukem */ 1075 /* some libc's out there are bound internally to these names (UMIPS) */ 1076 void 1077 ht_sethostent(stayopen) 1078 int stayopen; 1079 { 1080 _sethtent(stayopen); 1081 } 1082 1083 void 1084 ht_endhostent() 1085 { 1086 _endhtent(); 1087 } 1088 1089 struct hostent * 1090 ht_gethostbyname(name) 1091 char *name; 1092 { 1093 return (_gethtbyname(name)); 1094 } 1095 1096 struct hostent * 1097 ht_gethostbyaddr(addr, len, af) 1098 const char *addr; 1099 int len, af; 1100 { 1101 return (_gethtbyaddr(addr, len, af)); 1102 } 1103 1104 struct hostent * 1105 gethostent() 1106 { 1107 return (_gethtent()); 1108 } 1109 1110 void 1111 dns_service() 1112 { 1113 return; 1114 } 1115 1116 int 1117 dn_skipname(comp_dn, eom) 1118 const u_char *comp_dn, *eom; 1119 { 1120 return (__dn_skipname(comp_dn, eom)); 1121 } 1122 #endif /*old-style libc with yp junk in it*/ 1123 1124 /*ARGSUSED*/ 1125 int 1126 _dns_gethtbyname(rv, cb_data, ap) 1127 void *rv; 1128 void *cb_data; 1129 va_list ap; 1130 { 1131 querybuf buf; 1132 int n, type; 1133 struct hostent *hp; 1134 const char *name; 1135 int af; 1136 1137 _DIAGASSERT(rv != NULL); 1138 1139 name = va_arg(ap, char *); 1140 /* NOSTRICT skip len */(void)va_arg(ap, int); 1141 af = va_arg(ap, int); 1142 1143 switch (af) { 1144 case AF_INET: 1145 type = T_A; 1146 break; 1147 case AF_INET6: 1148 type = T_AAAA; 1149 break; 1150 default: 1151 return NS_UNAVAIL; 1152 } 1153 if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) { 1154 dprintf("res_search failed (%d)\n", n); 1155 return NS_NOTFOUND; 1156 } 1157 hp = getanswer(&buf, n, name, type); 1158 if (hp == NULL) 1159 switch (h_errno) { 1160 case HOST_NOT_FOUND: 1161 return NS_NOTFOUND; 1162 case TRY_AGAIN: 1163 return NS_TRYAGAIN; 1164 default: 1165 return NS_UNAVAIL; 1166 } 1167 *((struct hostent **)rv) = hp; 1168 return NS_SUCCESS; 1169 } 1170 1171 /*ARGSUSED*/ 1172 int 1173 _dns_gethtbyaddr(rv, cb_data, ap) 1174 void *rv; 1175 void *cb_data; 1176 va_list ap; 1177 { 1178 char qbuf[MAXDNAME + 1], *qp; 1179 int n; 1180 querybuf buf; 1181 struct hostent *hp; 1182 const unsigned char *uaddr; 1183 int len, af; 1184 1185 _DIAGASSERT(rv != NULL); 1186 1187 uaddr = va_arg(ap, unsigned char *); 1188 len = va_arg(ap, int); 1189 af = va_arg(ap, int); 1190 1191 switch (af) { 1192 case AF_INET: 1193 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 1194 (uaddr[3] & 0xff), 1195 (uaddr[2] & 0xff), 1196 (uaddr[1] & 0xff), 1197 (uaddr[0] & 0xff)); 1198 break; 1199 1200 case AF_INET6: 1201 qp = qbuf; 1202 for (n = IN6ADDRSZ - 1; n >= 0; n--) { 1203 qp += sprintf(qp, "%x.%x.", 1204 uaddr[n] & 0xf, 1205 ((unsigned int)uaddr[n] >> 4) & 0xf); 1206 } 1207 strcpy(qp, "ip6.int"); 1208 break; 1209 default: 1210 abort(); 1211 } 1212 1213 n = res_query(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, sizeof(buf)); 1214 if (n < 0) { 1215 dprintf("res_query failed (%d)\n", n); 1216 return NS_NOTFOUND; 1217 } 1218 hp = getanswer(&buf, n, qbuf, T_PTR); 1219 if (hp == NULL) 1220 switch (h_errno) { 1221 case HOST_NOT_FOUND: 1222 return NS_NOTFOUND; 1223 case TRY_AGAIN: 1224 return NS_TRYAGAIN; 1225 default: 1226 return NS_UNAVAIL; 1227 } 1228 hp->h_addrtype = af; 1229 hp->h_length = len; 1230 (void)memcpy(host_addr, uaddr, (size_t)len); 1231 h_addr_ptrs[0] = (char *)(void *)host_addr; 1232 h_addr_ptrs[1] = NULL; 1233 if (af == AF_INET && (_res.options & RES_USE_INET6)) { 1234 map_v4v6_address((char *)(void *)host_addr, 1235 (char *)(void *)host_addr); 1236 hp->h_addrtype = AF_INET6; 1237 hp->h_length = IN6ADDRSZ; 1238 } 1239 1240 *((struct hostent **)rv) = hp; 1241 h_errno = NETDB_SUCCESS; 1242 return NS_SUCCESS; 1243 } 1244 1245 #ifdef YP 1246 /*ARGSUSED*/ 1247 struct hostent * 1248 _yphostent(line, af) 1249 char *line; 1250 int af; 1251 { 1252 static struct in_addr host_addrs[MAXADDRS]; 1253 static struct in6_addr host6_addrs[MAXADDRS]; 1254 char *p = line; 1255 char *cp, **q; 1256 char **hap; 1257 int addrok; 1258 int more; 1259 int naddrs; 1260 1261 _DIAGASSERT(line != NULL); 1262 1263 host.h_name = NULL; 1264 host.h_addr_list = h_addr_ptrs; 1265 host.h_addrtype = af; 1266 switch (af) { 1267 case AF_INET: 1268 host.h_length = INADDRSZ; 1269 break; 1270 case AF_INET6: 1271 host.h_length = IN6ADDRSZ; 1272 break; 1273 default: 1274 return (NULL); 1275 } 1276 hap = h_addr_ptrs; 1277 q = host.h_aliases = host_aliases; 1278 naddrs = 0; 1279 1280 nextline: 1281 /* check for host_addrs overflow */ 1282 if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0])) 1283 goto done; 1284 if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0])) 1285 goto done; 1286 1287 more = 0; 1288 cp = strpbrk(p, " \t"); 1289 if (cp == NULL) 1290 goto done; 1291 *cp++ = '\0'; 1292 1293 /* p has should have an address */ 1294 switch (af) { 1295 case AF_INET: 1296 addrok = inet_aton(p, &host_addrs[naddrs]); 1297 break; 1298 case AF_INET6: 1299 addrok = inet_pton(af, p, &host6_addrs[naddrs]); 1300 break; 1301 } 1302 if (addrok != 1) { 1303 /* skip to the next line */ 1304 while (cp && *cp) { 1305 if (*cp == '\n') { 1306 cp++; 1307 goto nextline; 1308 } 1309 cp++; 1310 } 1311 1312 goto done; 1313 } 1314 1315 switch (af) { 1316 case AF_INET: 1317 *hap++ = (char *)(void *)&host_addrs[naddrs++]; 1318 break; 1319 case AF_INET6: 1320 *hap++ = (char *)(void *)&host6_addrs[naddrs++]; 1321 break; 1322 } 1323 1324 while (*cp == ' ' || *cp == '\t') 1325 cp++; 1326 p = cp; 1327 cp = strpbrk(p, " \t\n"); 1328 if (cp != NULL) { 1329 if (*cp == '\n') 1330 more = 1; 1331 *cp++ = '\0'; 1332 } 1333 if (!host.h_name) 1334 host.h_name = p; 1335 else if (strcmp(host.h_name, p)==0) 1336 ; 1337 else if (q < &host_aliases[MAXALIASES - 1]) 1338 *q++ = p; 1339 p = cp; 1340 if (more) 1341 goto nextline; 1342 1343 while (cp && *cp) { 1344 if (*cp == ' ' || *cp == '\t') { 1345 cp++; 1346 continue; 1347 } 1348 if (*cp == '\n') { 1349 cp++; 1350 goto nextline; 1351 } 1352 if (q < &host_aliases[MAXALIASES - 1]) 1353 *q++ = cp; 1354 cp = strpbrk(cp, " \t"); 1355 if (cp != NULL) 1356 *cp++ = '\0'; 1357 } 1358 1359 done: 1360 if (host.h_name == NULL) 1361 return (NULL); 1362 *q = NULL; 1363 *hap = NULL; 1364 return (&host); 1365 } 1366 1367 /*ARGSUSED*/ 1368 int 1369 _yp_gethtbyaddr(rv, cb_data, ap) 1370 void *rv; 1371 void *cb_data; 1372 va_list ap; 1373 { 1374 struct hostent *hp = (struct hostent *)NULL; 1375 static char *__ypcurrent; 1376 int __ypcurrentlen, r; 1377 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1378 const unsigned char *uaddr; 1379 int af; 1380 const char *map; 1381 1382 _DIAGASSERT(rv != NULL); 1383 1384 uaddr = va_arg(ap, unsigned char *); 1385 /* NOSTRICT skip len */(void)va_arg(ap, int); 1386 af = va_arg(ap, int); 1387 1388 if (!__ypdomain) { 1389 if (_yp_check(&__ypdomain) == 0) 1390 return NS_UNAVAIL; 1391 } 1392 /* 1393 * XXX unfortunately, we cannot support IPv6 extended scoped address 1394 * notation here. gethostbyaddr() is not scope-aware. too bad. 1395 */ 1396 if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL) 1397 return NS_UNAVAIL; 1398 if (__ypcurrent) 1399 free(__ypcurrent); 1400 __ypcurrent = NULL; 1401 switch (af) { 1402 case AF_INET: 1403 map = "hosts.byaddr"; 1404 break; 1405 default: 1406 map = "ipnodes.byaddr"; 1407 break; 1408 } 1409 r = yp_match(__ypdomain, map, name, 1410 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1411 if (r==0) 1412 hp = _yphostent(__ypcurrent, af); 1413 if (hp==NULL) { 1414 h_errno = HOST_NOT_FOUND; 1415 return NS_NOTFOUND; 1416 } 1417 *((struct hostent **)rv) = hp; 1418 return NS_SUCCESS; 1419 } 1420 1421 /*ARGSUSED*/ 1422 int 1423 _yp_gethtbyname(rv, cb_data, ap) 1424 void *rv; 1425 void *cb_data; 1426 va_list ap; 1427 { 1428 struct hostent *hp = (struct hostent *)NULL; 1429 static char *__ypcurrent; 1430 int __ypcurrentlen, r; 1431 const char *name; 1432 int af; 1433 const char *map; 1434 1435 _DIAGASSERT(rv != NULL); 1436 1437 name = va_arg(ap, char *); 1438 /* NOSTRICT skip len */(void)va_arg(ap, int); 1439 af = va_arg(ap, int); 1440 1441 if (!__ypdomain) { 1442 if (_yp_check(&__ypdomain) == 0) 1443 return NS_UNAVAIL; 1444 } 1445 if (__ypcurrent) 1446 free(__ypcurrent); 1447 __ypcurrent = NULL; 1448 switch (af) { 1449 case AF_INET: 1450 map = "hosts.byname"; 1451 break; 1452 default: 1453 map = "ipnodes.byname"; 1454 break; 1455 } 1456 r = yp_match(__ypdomain, map, name, 1457 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1458 if (r==0) 1459 hp = _yphostent(__ypcurrent, af); 1460 if (hp==NULL) { 1461 h_errno = HOST_NOT_FOUND; 1462 return NS_NOTFOUND; 1463 } 1464 *((struct hostent **)rv) = hp; 1465 return NS_SUCCESS; 1466 } 1467 #endif 1468