1 /* $NetBSD: gethnamaddr.c,v 1.42 2002/05/18 00:07:28 itojun 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.42 2002/05/18 00:07:28 itojun 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_LINKLOCAL((const struct in6_addr *)(const void *)uaddr) || 686 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)(const void *)uaddr))) { 687 h_errno = HOST_NOT_FOUND; 688 return (NULL); 689 } 690 if (af == AF_INET6 && len == IN6ADDRSZ && 691 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)(const void *)uaddr) || 692 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)(const void *)uaddr))) { 693 /* Unmap. */ 694 addr += IN6ADDRSZ - INADDRSZ; 695 uaddr += IN6ADDRSZ - INADDRSZ; 696 af = AF_INET; 697 len = INADDRSZ; 698 } 699 switch (af) { 700 case AF_INET: 701 size = INADDRSZ; 702 break; 703 case AF_INET6: 704 size = IN6ADDRSZ; 705 break; 706 default: 707 errno = EAFNOSUPPORT; 708 h_errno = NETDB_INTERNAL; 709 return (NULL); 710 } 711 if (size != len) { 712 errno = EINVAL; 713 h_errno = NETDB_INTERNAL; 714 return (NULL); 715 } 716 hp = (struct hostent *)NULL; 717 h_errno = NETDB_INTERNAL; 718 if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr", 719 default_dns_files, uaddr, len, af) != NS_SUCCESS) 720 return (struct hostent *)NULL; 721 h_errno = NETDB_SUCCESS; 722 return (hp); 723 } 724 725 void 726 _sethtent(f) 727 int f; 728 { 729 if (!hostf) 730 hostf = fopen(_PATH_HOSTS, "r" ); 731 else 732 rewind(hostf); 733 stayopen = f; 734 } 735 736 void 737 _endhtent() 738 { 739 if (hostf && !stayopen) { 740 (void) fclose(hostf); 741 hostf = NULL; 742 } 743 } 744 745 struct hostent * 746 _gethtent() 747 { 748 char *p; 749 char *cp, **q; 750 int af, len; 751 752 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { 753 h_errno = NETDB_INTERNAL; 754 return (NULL); 755 } 756 again: 757 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { 758 h_errno = HOST_NOT_FOUND; 759 return (NULL); 760 } 761 if (*p == '#') 762 goto again; 763 if (!(cp = strpbrk(p, "#\n"))) 764 goto again; 765 *cp = '\0'; 766 if (!(cp = strpbrk(p, " \t"))) 767 goto again; 768 *cp++ = '\0'; 769 if (inet_pton(AF_INET6, p, (char *)(void *)host_addr) > 0) { 770 af = AF_INET6; 771 len = IN6ADDRSZ; 772 } else if (inet_pton(AF_INET, p, (char *)(void *)host_addr) > 0) { 773 if (_res.options & RES_USE_INET6) { 774 map_v4v6_address((char *)(void *)host_addr, 775 (char *)(void *)host_addr); 776 af = AF_INET6; 777 len = IN6ADDRSZ; 778 } else { 779 af = AF_INET; 780 len = INADDRSZ; 781 } 782 } else { 783 goto again; 784 } 785 /* if this is not something we're looking for, skip it. */ 786 if (host.h_addrtype != af) 787 goto again; 788 if (host.h_length != len) 789 goto again; 790 h_addr_ptrs[0] = (char *)(void *)host_addr; 791 h_addr_ptrs[1] = NULL; 792 host.h_addr_list = h_addr_ptrs; 793 host.h_length = len; 794 host.h_addrtype = af; 795 while (*cp == ' ' || *cp == '\t') 796 cp++; 797 host.h_name = cp; 798 q = host.h_aliases = host_aliases; 799 if ((cp = strpbrk(cp, " \t")) != NULL) 800 *cp++ = '\0'; 801 while (cp && *cp) { 802 if (*cp == ' ' || *cp == '\t') { 803 cp++; 804 continue; 805 } 806 if (q < &host_aliases[MAXALIASES - 1]) 807 *q++ = cp; 808 if ((cp = strpbrk(cp, " \t")) != NULL) 809 *cp++ = '\0'; 810 } 811 *q = NULL; 812 h_errno = NETDB_SUCCESS; 813 return (&host); 814 } 815 816 /*ARGSUSED*/ 817 int 818 _gethtbyname(rv, cb_data, ap) 819 void *rv; 820 void *cb_data; 821 va_list ap; 822 { 823 struct hostent *hp; 824 const char *name; 825 int af; 826 827 _DIAGASSERT(rv != NULL); 828 829 name = va_arg(ap, char *); 830 /* NOSTRICT skip len */(void)va_arg(ap, int); 831 af = va_arg(ap, int); 832 833 hp = NULL; 834 #if 0 835 if (_res.options & RES_USE_INET6) 836 hp = _gethtbyname2(name, AF_INET6); 837 if (hp==NULL) 838 hp = _gethtbyname2(name, AF_INET); 839 #else 840 hp = _gethtbyname2(name, af); 841 #endif 842 *((struct hostent **)rv) = hp; 843 if (hp == NULL) { 844 h_errno = HOST_NOT_FOUND; 845 return NS_NOTFOUND; 846 } 847 return NS_SUCCESS; 848 } 849 850 struct hostent * 851 _gethtbyname2(name, af) 852 const char *name; 853 int af; 854 { 855 struct hostent *p; 856 char *tmpbuf, *ptr, **cp; 857 int num; 858 size_t len; 859 860 _DIAGASSERT(name != NULL); 861 862 _sethtent(0); 863 ptr = tmpbuf = NULL; 864 num = 0; 865 while ((p = _gethtent()) != NULL && num < MAXADDRS) { 866 if (p->h_addrtype != af) 867 continue; 868 if (strcasecmp(p->h_name, name) != 0) { 869 for (cp = p->h_aliases; *cp != NULL; cp++) 870 if (strcasecmp(*cp, name) == 0) 871 break; 872 if (*cp == NULL) continue; 873 } 874 875 if (num == 0) { 876 size_t bufsize; 877 char *src; 878 879 bufsize = strlen(p->h_name) + 2 + 880 MAXADDRS * p->h_length + 881 ALIGNBYTES; 882 for (cp = p->h_aliases; *cp != NULL; cp++) 883 bufsize += strlen(*cp) + 1; 884 885 if ((tmpbuf = malloc(bufsize)) == NULL) { 886 h_errno = NETDB_INTERNAL; 887 return NULL; 888 } 889 890 ptr = tmpbuf; 891 src = p->h_name; 892 while ((*ptr++ = *src++) != '\0'); 893 for (cp = p->h_aliases; *cp != NULL; cp++) { 894 src = *cp; 895 while ((*ptr++ = *src++) != '\0'); 896 } 897 *ptr++ = '\0'; 898 899 ptr = (char *)(void *)ALIGN(ptr); 900 } 901 902 (void)memcpy(ptr, p->h_addr_list[0], (size_t)p->h_length); 903 ptr += p->h_length; 904 num++; 905 } 906 _endhtent(); 907 if (num == 0) return NULL; 908 909 len = ptr - tmpbuf; 910 if (len > (sizeof(hostbuf) - ALIGNBYTES)) { 911 free(tmpbuf); 912 errno = ENOSPC; 913 h_errno = NETDB_INTERNAL; 914 return NULL; 915 } 916 ptr = memcpy((void *)ALIGN(hostbuf), tmpbuf, len); 917 free(tmpbuf); 918 919 host.h_name = ptr; 920 while (*ptr++); 921 922 cp = host_aliases; 923 while (*ptr) { 924 *cp++ = ptr; 925 while (*ptr++); 926 } 927 ptr++; 928 *cp = NULL; 929 930 ptr = (char *)(void *)ALIGN(ptr); 931 cp = h_addr_ptrs; 932 while (num--) { 933 *cp++ = ptr; 934 ptr += host.h_length; 935 } 936 *cp = NULL; 937 938 return (&host); 939 } 940 941 /*ARGSUSED*/ 942 int 943 _gethtbyaddr(rv, cb_data, ap) 944 void *rv; 945 void *cb_data; 946 va_list ap; 947 { 948 struct hostent *p; 949 const unsigned char *addr; 950 int len, af; 951 952 _DIAGASSERT(rv != NULL); 953 954 addr = va_arg(ap, unsigned char *); 955 len = va_arg(ap, int); 956 af = va_arg(ap, int); 957 958 host.h_length = len; 959 host.h_addrtype = af; 960 961 _sethtent(0); 962 while ((p = _gethtent()) != NULL) 963 if (p->h_addrtype == af && !memcmp(p->h_addr, addr, 964 (size_t)len)) 965 break; 966 _endhtent(); 967 *((struct hostent **)rv) = p; 968 if (p==NULL) { 969 h_errno = HOST_NOT_FOUND; 970 return NS_NOTFOUND; 971 } 972 return NS_SUCCESS; 973 } 974 975 static void 976 map_v4v6_address(src, dst) 977 const char *src; 978 char *dst; 979 { 980 u_char *p = (u_char *)dst; 981 char tmp[INADDRSZ]; 982 int i; 983 984 _DIAGASSERT(src != NULL); 985 _DIAGASSERT(dst != NULL); 986 987 /* Stash a temporary copy so our caller can update in place. */ 988 (void)memcpy(tmp, src, INADDRSZ); 989 /* Mark this ipv6 addr as a mapped ipv4. */ 990 for (i = 0; i < 10; i++) 991 *p++ = 0x00; 992 *p++ = 0xff; 993 *p++ = 0xff; 994 /* Retrieve the saved copy and we're done. */ 995 (void)memcpy((void *)p, tmp, INADDRSZ); 996 } 997 998 static void 999 map_v4v6_hostent(hp, bpp, lenp) 1000 struct hostent *hp; 1001 char **bpp; 1002 int *lenp; 1003 { 1004 char **ap; 1005 1006 _DIAGASSERT(hp != NULL); 1007 _DIAGASSERT(bpp != NULL); 1008 _DIAGASSERT(lenp != NULL); 1009 1010 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 1011 return; 1012 hp->h_addrtype = AF_INET6; 1013 hp->h_length = IN6ADDRSZ; 1014 for (ap = hp->h_addr_list; *ap; ap++) { 1015 int i = sizeof(align) - (size_t)((u_long)*bpp % sizeof(align)); 1016 1017 if (*lenp < (i + IN6ADDRSZ)) { 1018 /* Out of memory. Truncate address list here. XXX */ 1019 *ap = NULL; 1020 return; 1021 } 1022 *bpp += i; 1023 *lenp -= i; 1024 map_v4v6_address(*ap, *bpp); 1025 *ap = *bpp; 1026 *bpp += IN6ADDRSZ; 1027 *lenp -= IN6ADDRSZ; 1028 } 1029 } 1030 1031 #ifdef RESOLVSORT 1032 static void 1033 addrsort(ap, num) 1034 char **ap; 1035 int num; 1036 { 1037 int i, j; 1038 char **p; 1039 short aval[MAXADDRS]; 1040 int needsort = 0; 1041 1042 _DIAGASSERT(ap != NULL); 1043 1044 p = ap; 1045 for (i = 0; i < num; i++, p++) { 1046 for (j = 0 ; (unsigned)j < _res.nsort; j++) 1047 if (_res.sort_list[j].addr.s_addr == 1048 (((struct in_addr *)(void *)(*p))->s_addr & 1049 _res.sort_list[j].mask)) 1050 break; 1051 aval[i] = j; 1052 if (needsort == 0 && i > 0 && j < aval[i-1]) 1053 needsort = i; 1054 } 1055 if (!needsort) 1056 return; 1057 1058 while (needsort < num) { 1059 for (j = needsort - 1; j >= 0; j--) { 1060 if (aval[j] > aval[j+1]) { 1061 char *hp; 1062 1063 i = aval[j]; 1064 aval[j] = aval[j+1]; 1065 aval[j+1] = i; 1066 1067 hp = ap[j]; 1068 ap[j] = ap[j+1]; 1069 ap[j+1] = hp; 1070 1071 } else 1072 break; 1073 } 1074 needsort++; 1075 } 1076 } 1077 #endif 1078 1079 #if defined(BSD43_BSD43_NFS) || defined(sun) 1080 /* XXX: should we remove this cruft? - lukem */ 1081 /* some libc's out there are bound internally to these names (UMIPS) */ 1082 void 1083 ht_sethostent(stayopen) 1084 int stayopen; 1085 { 1086 _sethtent(stayopen); 1087 } 1088 1089 void 1090 ht_endhostent() 1091 { 1092 _endhtent(); 1093 } 1094 1095 struct hostent * 1096 ht_gethostbyname(name) 1097 char *name; 1098 { 1099 return (_gethtbyname(name)); 1100 } 1101 1102 struct hostent * 1103 ht_gethostbyaddr(addr, len, af) 1104 const char *addr; 1105 int len, af; 1106 { 1107 return (_gethtbyaddr(addr, len, af)); 1108 } 1109 1110 struct hostent * 1111 gethostent() 1112 { 1113 return (_gethtent()); 1114 } 1115 1116 void 1117 dns_service() 1118 { 1119 return; 1120 } 1121 1122 int 1123 dn_skipname(comp_dn, eom) 1124 const u_char *comp_dn, *eom; 1125 { 1126 return (__dn_skipname(comp_dn, eom)); 1127 } 1128 #endif /*old-style libc with yp junk in it*/ 1129 1130 /*ARGSUSED*/ 1131 int 1132 _dns_gethtbyname(rv, cb_data, ap) 1133 void *rv; 1134 void *cb_data; 1135 va_list ap; 1136 { 1137 querybuf buf; 1138 int n, type; 1139 struct hostent *hp; 1140 const char *name; 1141 int af; 1142 1143 _DIAGASSERT(rv != NULL); 1144 1145 name = va_arg(ap, char *); 1146 /* NOSTRICT skip len */(void)va_arg(ap, int); 1147 af = va_arg(ap, int); 1148 1149 switch (af) { 1150 case AF_INET: 1151 type = T_A; 1152 break; 1153 case AF_INET6: 1154 type = T_AAAA; 1155 break; 1156 default: 1157 return NS_UNAVAIL; 1158 } 1159 if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) { 1160 dprintf("res_search failed (%d)\n", n); 1161 return NS_NOTFOUND; 1162 } 1163 hp = getanswer(&buf, n, name, type); 1164 if (hp == NULL) 1165 switch (h_errno) { 1166 case HOST_NOT_FOUND: 1167 return NS_NOTFOUND; 1168 case TRY_AGAIN: 1169 return NS_TRYAGAIN; 1170 default: 1171 return NS_UNAVAIL; 1172 } 1173 *((struct hostent **)rv) = hp; 1174 return NS_SUCCESS; 1175 } 1176 1177 /*ARGSUSED*/ 1178 int 1179 _dns_gethtbyaddr(rv, cb_data, ap) 1180 void *rv; 1181 void *cb_data; 1182 va_list ap; 1183 { 1184 char qbuf[MAXDNAME + 1], *qp; 1185 int n; 1186 querybuf buf; 1187 struct hostent *hp; 1188 const unsigned char *uaddr; 1189 int len, af; 1190 1191 _DIAGASSERT(rv != NULL); 1192 1193 uaddr = va_arg(ap, unsigned char *); 1194 len = va_arg(ap, int); 1195 af = va_arg(ap, int); 1196 1197 switch (af) { 1198 case AF_INET: 1199 (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 1200 (uaddr[3] & 0xff), 1201 (uaddr[2] & 0xff), 1202 (uaddr[1] & 0xff), 1203 (uaddr[0] & 0xff)); 1204 break; 1205 1206 case AF_INET6: 1207 qp = qbuf; 1208 for (n = IN6ADDRSZ - 1; n >= 0; n--) { 1209 qp += sprintf(qp, "%x.%x.", 1210 uaddr[n] & 0xf, 1211 ((unsigned int)uaddr[n] >> 4) & 0xf); 1212 } 1213 strcpy(qp, "ip6.int"); 1214 break; 1215 default: 1216 abort(); 1217 } 1218 1219 n = res_query(qbuf, C_IN, T_PTR, (u_char *)(void *)&buf, sizeof(buf)); 1220 if (n < 0) { 1221 dprintf("res_query failed (%d)\n", n); 1222 return NS_NOTFOUND; 1223 } 1224 hp = getanswer(&buf, n, qbuf, T_PTR); 1225 if (hp == NULL) 1226 switch (h_errno) { 1227 case HOST_NOT_FOUND: 1228 return NS_NOTFOUND; 1229 case TRY_AGAIN: 1230 return NS_TRYAGAIN; 1231 default: 1232 return NS_UNAVAIL; 1233 } 1234 hp->h_addrtype = af; 1235 hp->h_length = len; 1236 (void)memcpy(host_addr, uaddr, (size_t)len); 1237 h_addr_ptrs[0] = (char *)(void *)host_addr; 1238 h_addr_ptrs[1] = NULL; 1239 if (af == AF_INET && (_res.options & RES_USE_INET6)) { 1240 map_v4v6_address((char *)(void *)host_addr, 1241 (char *)(void *)host_addr); 1242 hp->h_addrtype = AF_INET6; 1243 hp->h_length = IN6ADDRSZ; 1244 } 1245 1246 *((struct hostent **)rv) = hp; 1247 h_errno = NETDB_SUCCESS; 1248 return NS_SUCCESS; 1249 } 1250 1251 #ifdef YP 1252 /*ARGSUSED*/ 1253 struct hostent * 1254 _yphostent(line, af) 1255 char *line; 1256 int af; 1257 { 1258 static struct in_addr host_addrs[MAXADDRS]; 1259 static struct in6_addr host6_addrs[MAXADDRS]; 1260 char *p = line; 1261 char *cp, **q; 1262 char **hap; 1263 int addrok; 1264 int more; 1265 int naddrs; 1266 1267 _DIAGASSERT(line != NULL); 1268 1269 host.h_name = NULL; 1270 host.h_addr_list = h_addr_ptrs; 1271 host.h_addrtype = af; 1272 switch (af) { 1273 case AF_INET: 1274 host.h_length = INADDRSZ; 1275 break; 1276 case AF_INET6: 1277 host.h_length = IN6ADDRSZ; 1278 break; 1279 default: 1280 return (NULL); 1281 } 1282 hap = h_addr_ptrs; 1283 q = host.h_aliases = host_aliases; 1284 naddrs = 0; 1285 1286 nextline: 1287 /* check for host_addrs overflow */ 1288 if (naddrs >= sizeof(host_addrs) / sizeof(host_addrs[0])) 1289 goto done; 1290 if (naddrs >= sizeof(host6_addrs) / sizeof(host6_addrs[0])) 1291 goto done; 1292 1293 more = 0; 1294 cp = strpbrk(p, " \t"); 1295 if (cp == NULL) 1296 goto done; 1297 *cp++ = '\0'; 1298 1299 /* p has should have an address */ 1300 switch (af) { 1301 case AF_INET: 1302 addrok = inet_aton(p, &host_addrs[naddrs]); 1303 break; 1304 case AF_INET6: 1305 addrok = inet_pton(af, p, &host6_addrs[naddrs]); 1306 break; 1307 } 1308 if (addrok != 1) { 1309 /* skip to the next line */ 1310 while (cp && *cp) { 1311 if (*cp == '\n') { 1312 cp++; 1313 goto nextline; 1314 } 1315 cp++; 1316 } 1317 1318 goto done; 1319 } 1320 1321 switch (af) { 1322 case AF_INET: 1323 *hap++ = (char *)(void *)&host_addrs[naddrs++]; 1324 break; 1325 case AF_INET6: 1326 *hap++ = (char *)(void *)&host6_addrs[naddrs++]; 1327 break; 1328 } 1329 1330 while (*cp == ' ' || *cp == '\t') 1331 cp++; 1332 p = cp; 1333 cp = strpbrk(p, " \t\n"); 1334 if (cp != NULL) { 1335 if (*cp == '\n') 1336 more = 1; 1337 *cp++ = '\0'; 1338 } 1339 if (!host.h_name) 1340 host.h_name = p; 1341 else if (strcmp(host.h_name, p)==0) 1342 ; 1343 else if (q < &host_aliases[MAXALIASES - 1]) 1344 *q++ = p; 1345 p = cp; 1346 if (more) 1347 goto nextline; 1348 1349 while (cp && *cp) { 1350 if (*cp == ' ' || *cp == '\t') { 1351 cp++; 1352 continue; 1353 } 1354 if (*cp == '\n') { 1355 cp++; 1356 goto nextline; 1357 } 1358 if (q < &host_aliases[MAXALIASES - 1]) 1359 *q++ = cp; 1360 cp = strpbrk(cp, " \t"); 1361 if (cp != NULL) 1362 *cp++ = '\0'; 1363 } 1364 1365 done: 1366 if (host.h_name == NULL) 1367 return (NULL); 1368 *q = NULL; 1369 *hap = NULL; 1370 return (&host); 1371 } 1372 1373 /*ARGSUSED*/ 1374 int 1375 _yp_gethtbyaddr(rv, cb_data, ap) 1376 void *rv; 1377 void *cb_data; 1378 va_list ap; 1379 { 1380 struct hostent *hp = (struct hostent *)NULL; 1381 static char *__ypcurrent; 1382 int __ypcurrentlen, r; 1383 char name[INET6_ADDRSTRLEN]; /* XXX enough? */ 1384 const unsigned char *uaddr; 1385 int af; 1386 const char *map; 1387 1388 _DIAGASSERT(rv != NULL); 1389 1390 uaddr = va_arg(ap, unsigned char *); 1391 /* NOSTRICT skip len */(void)va_arg(ap, int); 1392 af = va_arg(ap, int); 1393 1394 if (!__ypdomain) { 1395 if (_yp_check(&__ypdomain) == 0) 1396 return NS_UNAVAIL; 1397 } 1398 /* 1399 * XXX unfortunately, we cannot support IPv6 extended scoped address 1400 * notation here. gethostbyaddr() is not scope-aware. too bad. 1401 */ 1402 if (inet_ntop(af, uaddr, name, sizeof(name)) == NULL) 1403 return NS_UNAVAIL; 1404 if (__ypcurrent) 1405 free(__ypcurrent); 1406 __ypcurrent = NULL; 1407 switch (af) { 1408 case AF_INET: 1409 map = "hosts.byaddr"; 1410 break; 1411 default: 1412 map = "ipnodes.byaddr"; 1413 break; 1414 } 1415 r = yp_match(__ypdomain, map, name, 1416 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1417 if (r==0) 1418 hp = _yphostent(__ypcurrent, af); 1419 if (hp==NULL) { 1420 h_errno = HOST_NOT_FOUND; 1421 return NS_NOTFOUND; 1422 } 1423 *((struct hostent **)rv) = hp; 1424 return NS_SUCCESS; 1425 } 1426 1427 /*ARGSUSED*/ 1428 int 1429 _yp_gethtbyname(rv, cb_data, ap) 1430 void *rv; 1431 void *cb_data; 1432 va_list ap; 1433 { 1434 struct hostent *hp = (struct hostent *)NULL; 1435 static char *__ypcurrent; 1436 int __ypcurrentlen, r; 1437 const char *name; 1438 int af; 1439 const char *map; 1440 1441 _DIAGASSERT(rv != NULL); 1442 1443 name = va_arg(ap, char *); 1444 /* NOSTRICT skip len */(void)va_arg(ap, int); 1445 af = va_arg(ap, int); 1446 1447 if (!__ypdomain) { 1448 if (_yp_check(&__ypdomain) == 0) 1449 return NS_UNAVAIL; 1450 } 1451 if (__ypcurrent) 1452 free(__ypcurrent); 1453 __ypcurrent = NULL; 1454 switch (af) { 1455 case AF_INET: 1456 map = "hosts.byname"; 1457 break; 1458 default: 1459 map = "ipnodes.byname"; 1460 break; 1461 } 1462 r = yp_match(__ypdomain, map, name, 1463 (int)strlen(name), &__ypcurrent, &__ypcurrentlen); 1464 if (r==0) 1465 hp = _yphostent(__ypcurrent, af); 1466 if (hp==NULL) { 1467 h_errno = HOST_NOT_FOUND; 1468 return NS_NOTFOUND; 1469 } 1470 *((struct hostent **)rv) = hp; 1471 return NS_SUCCESS; 1472 } 1473 #endif 1474