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