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