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