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