1 /* $NetBSD: gethnamaddr.c,v 1.4 1998/01/06 05:01:16 perry 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.4 1998/01/06 05:01:16 perry Exp $"); 65 #endif 66 #endif /* LIBC_SCCS and not lint */ 67 68 #include "namespace.h" 69 #include <sys/types.h> 70 #include <sys/param.h> 71 #include <sys/socket.h> 72 #include <netinet/in.h> 73 #include <arpa/inet.h> 74 #include <arpa/nameser.h> 75 76 #include <stdio.h> 77 #include <netdb.h> 78 #include <resolv.h> 79 #include <ctype.h> 80 #include <errno.h> 81 #include <syslog.h> 82 83 #ifndef LOG_AUTH 84 # define LOG_AUTH 0 85 #endif 86 87 #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ 88 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 #define MAXALIASES 35 99 #define MAXADDRS 35 100 101 static const char AskedForGot[] = 102 "gethostby*.getanswer: asked for \"%s\", got \"%s\""; 103 104 static char *h_addr_ptrs[MAXADDRS + 1]; 105 106 #ifdef YP 107 static char *__ypdomain; 108 #endif 109 110 static struct hostent host; 111 static char *host_aliases[MAXALIASES]; 112 static char hostbuf[8*1024]; 113 static u_char host_addr[16]; /* IPv4 or IPv6 */ 114 static FILE *hostf = NULL; 115 static int stayopen = 0; 116 117 118 #if PACKETSZ > 1024 119 #define MAXPACKET PACKETSZ 120 #else 121 #define MAXPACKET 1024 122 #endif 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 extern int h_errno; 135 136 #ifdef DEBUG 137 static void dprintf __P((char *, int)); 138 #endif 139 static struct hostent *getanswer __P((const querybuf *, int, 140 const char *, int)); 141 static void map_v4v6_address __P((const char *, char *)); 142 static void map_v4v6_hostent __P((struct hostent *, char **, int *)); 143 #ifdef RESOLVSORT 144 static void addrsort __P((char **, int)); 145 #endif 146 147 struct hostent *gethostbyname __P((const char *)); 148 struct hostent *gethostbyname2 __P((const char *, int)); 149 struct hostent *gethostbyaddr __P((const char *, int, int )); 150 void _sethtent __P((int)); 151 void _endhtent __P((void)); 152 struct hostent *_gethtent __P((void)); 153 struct hostent *_gethtbyname __P((const char *)); 154 struct hostent *_gethtbyname2 __P((const char *, int)); 155 struct hostent *_gethtbyaddr __P((const char *, int, int )); 156 void ht_sethostent __P((int)); 157 void ht_endhostent __P((void)); 158 struct hostent *ht_gethostbyname __P((char *)); 159 struct hostent *ht_gethostbyaddr __P((const char *, int, int )); 160 struct hostent *gethostent __P((void)); 161 void dns_service __P((void)); 162 int dn_skipname __P((const u_char *, const u_char *)); 163 #ifdef YP 164 struct hostent *_yphostent __P((char *)); 165 struct hostent *_yp_gethtbyaddr __P((const char *, int, int )); 166 struct hostent *_yp_gethtbyname __P((const char *)); 167 #endif 168 169 170 #ifdef DEBUG 171 static void 172 dprintf(msg, num) 173 char *msg; 174 int num; 175 { 176 if (_res.options & RES_DEBUG) { 177 int save = errno; 178 179 printf(msg, num); 180 errno = save; 181 } 182 } 183 #else 184 # define dprintf(msg, num) /*nada*/ 185 #endif 186 187 static struct hostent * 188 getanswer(answer, anslen, qname, qtype) 189 const querybuf *answer; 190 int anslen; 191 const char *qname; 192 int qtype; 193 { 194 register const HEADER *hp; 195 register const u_char *cp; 196 register int n; 197 const u_char *eom; 198 char *bp, **ap, **hap; 199 int type, class, buflen, ancount, qdcount; 200 int haveanswer, had_error; 201 int toobig = 0; 202 char tbuf[MAXDNAME]; 203 const char *tname; 204 int (*name_ok) __P((const char *)); 205 206 tname = qname; 207 host.h_name = NULL; 208 eom = answer->buf + anslen; 209 switch (qtype) { 210 case T_A: 211 case T_AAAA: 212 name_ok = res_hnok; 213 break; 214 case T_PTR: 215 name_ok = res_dnok; 216 break; 217 default: 218 return (NULL); /* XXX should be abort(); */ 219 } 220 /* 221 * find first satisfactory answer 222 */ 223 hp = &answer->hdr; 224 ancount = ntohs(hp->ancount); 225 qdcount = ntohs(hp->qdcount); 226 bp = hostbuf; 227 buflen = sizeof hostbuf; 228 cp = answer->buf + HFIXEDSZ; 229 if (qdcount != 1) { 230 h_errno = NO_RECOVERY; 231 return (NULL); 232 } 233 n = dn_expand(answer->buf, eom, cp, bp, buflen); 234 if ((n < 0) || !(*name_ok)(bp)) { 235 h_errno = NO_RECOVERY; 236 return (NULL); 237 } 238 cp += n + QFIXEDSZ; 239 if (qtype == T_A || qtype == T_AAAA) { 240 /* res_send() has already verified that the query name is the 241 * same as the one we sent; this just gets the expanded name 242 * (i.e., with the succeeding search-domain tacked on). 243 */ 244 n = strlen(bp) + 1; /* for the \0 */ 245 if (n >= MAXHOSTNAMELEN) { 246 h_errno = NO_RECOVERY; 247 return (NULL); 248 } 249 host.h_name = bp; 250 bp += n; 251 buflen -= n; 252 /* The qname can be abbreviated, but h_name is now absolute. */ 253 qname = host.h_name; 254 } 255 ap = host_aliases; 256 *ap = NULL; 257 host.h_aliases = host_aliases; 258 hap = h_addr_ptrs; 259 *hap = NULL; 260 host.h_addr_list = h_addr_ptrs; 261 haveanswer = 0; 262 had_error = 0; 263 while (ancount-- > 0 && cp < eom && !had_error) { 264 n = dn_expand(answer->buf, eom, cp, bp, buflen); 265 if ((n < 0) || !(*name_ok)(bp)) { 266 had_error++; 267 continue; 268 } 269 cp += n; /* name */ 270 type = _getshort(cp); 271 cp += INT16SZ; /* type */ 272 class = _getshort(cp); 273 cp += INT16SZ + INT32SZ; /* class, TTL */ 274 n = _getshort(cp); 275 cp += INT16SZ; /* len */ 276 if (class != C_IN) { 277 /* XXX - debug? syslog? */ 278 cp += n; 279 continue; /* XXX - had_error++ ? */ 280 } 281 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 282 if (ap >= &host_aliases[MAXALIASES-1]) 283 continue; 284 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 285 if ((n < 0) || !(*name_ok)(tbuf)) { 286 had_error++; 287 continue; 288 } 289 cp += n; 290 /* Store alias. */ 291 *ap++ = bp; 292 n = strlen(bp) + 1; /* for the \0 */ 293 if (n >= MAXHOSTNAMELEN) { 294 had_error++; 295 continue; 296 } 297 bp += n; 298 buflen -= n; 299 /* Get canonical name. */ 300 n = strlen(tbuf) + 1; /* for the \0 */ 301 if (n > buflen || n >= MAXHOSTNAMELEN) { 302 had_error++; 303 continue; 304 } 305 strcpy(bp, tbuf); 306 host.h_name = bp; 307 bp += n; 308 buflen -= n; 309 continue; 310 } 311 if (qtype == T_PTR && type == T_CNAME) { 312 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 313 if (n < 0 || !res_dnok(tbuf)) { 314 had_error++; 315 continue; 316 } 317 cp += n; 318 /* Get canonical name. */ 319 n = strlen(tbuf) + 1; /* for the \0 */ 320 if (n > buflen || n >= MAXHOSTNAMELEN) { 321 had_error++; 322 continue; 323 } 324 strcpy(bp, tbuf); 325 tname = bp; 326 bp += n; 327 buflen -= n; 328 continue; 329 } 330 if (type != qtype) { 331 syslog(LOG_NOTICE|LOG_AUTH, 332 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", 333 qname, p_class(C_IN), p_type(qtype), 334 p_type(type)); 335 cp += n; 336 continue; /* XXX - had_error++ ? */ 337 } 338 switch (type) { 339 case T_PTR: 340 if (strcasecmp(tname, bp) != 0) { 341 syslog(LOG_NOTICE|LOG_AUTH, 342 AskedForGot, qname, bp); 343 cp += n; 344 continue; /* XXX - had_error++ ? */ 345 } 346 n = dn_expand(answer->buf, eom, cp, bp, buflen); 347 if ((n < 0) || !res_hnok(bp)) { 348 had_error++; 349 break; 350 } 351 #if MULTI_PTRS_ARE_ALIASES 352 cp += n; 353 if (!haveanswer) 354 host.h_name = bp; 355 else if (ap < &host_aliases[MAXALIASES-1]) 356 *ap++ = bp; 357 else 358 n = -1; 359 if (n != -1) { 360 n = strlen(bp) + 1; /* for the \0 */ 361 if (n >= MAXHOSTNAMELEN) { 362 had_error++; 363 break; 364 } 365 bp += n; 366 buflen -= n; 367 } 368 break; 369 #else 370 host.h_name = bp; 371 if (_res.options & RES_USE_INET6) { 372 n = strlen(bp) + 1; /* for the \0 */ 373 if (n >= MAXHOSTNAMELEN) { 374 had_error++; 375 break; 376 } 377 bp += n; 378 buflen -= n; 379 map_v4v6_hostent(&host, &bp, &buflen); 380 } 381 h_errno = NETDB_SUCCESS; 382 return (&host); 383 #endif 384 case T_A: 385 case T_AAAA: 386 if (strcasecmp(host.h_name, bp) != 0) { 387 syslog(LOG_NOTICE|LOG_AUTH, 388 AskedForGot, host.h_name, bp); 389 cp += n; 390 continue; /* XXX - had_error++ ? */ 391 } 392 if (n != host.h_length) { 393 cp += n; 394 continue; 395 } 396 if (!haveanswer) { 397 register int nn; 398 399 host.h_name = bp; 400 nn = strlen(bp) + 1; /* for the \0 */ 401 bp += nn; 402 buflen -= nn; 403 } 404 405 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 406 407 if (bp + n >= &hostbuf[sizeof hostbuf]) { 408 dprintf("size (%d) too big\n", n); 409 had_error++; 410 continue; 411 } 412 if (hap >= &h_addr_ptrs[MAXADDRS-1]) { 413 if (!toobig++) 414 dprintf("Too many addresses (%d)\n", 415 MAXADDRS); 416 cp += n; 417 continue; 418 } 419 bcopy(cp, *hap++ = bp, n); 420 bp += n; 421 buflen -= n; 422 cp += n; 423 break; 424 default: 425 abort(); 426 } 427 if (!had_error) 428 haveanswer++; 429 } 430 if (haveanswer) { 431 *ap = NULL; 432 *hap = NULL; 433 # if defined(RESOLVSORT) 434 /* 435 * Note: we sort even if host can take only one address 436 * in its return structures - should give it the "best" 437 * address in that case, not some random one 438 */ 439 if (_res.nsort && haveanswer > 1 && qtype == T_A) 440 addrsort(h_addr_ptrs, haveanswer); 441 # endif /*RESOLVSORT*/ 442 if (!host.h_name) { 443 n = strlen(qname) + 1; /* for the \0 */ 444 if (n > buflen || n >= MAXHOSTNAMELEN) 445 goto no_recovery; 446 strcpy(bp, qname); 447 host.h_name = bp; 448 bp += n; 449 buflen -= n; 450 } 451 if (_res.options & RES_USE_INET6) 452 map_v4v6_hostent(&host, &bp, &buflen); 453 h_errno = NETDB_SUCCESS; 454 return (&host); 455 } 456 no_recovery: 457 h_errno = NO_RECOVERY; 458 return (NULL); 459 } 460 461 struct hostent * 462 gethostbyname(name) 463 const char *name; 464 { 465 struct hostent *hp; 466 467 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 468 h_errno = NETDB_INTERNAL; 469 return (NULL); 470 } 471 if (_res.options & RES_USE_INET6) { 472 hp = gethostbyname2(name, AF_INET6); 473 if (hp) 474 return (hp); 475 } 476 return (gethostbyname2(name, AF_INET)); 477 } 478 479 struct hostent * 480 gethostbyname2(name, af) 481 const char *name; 482 int af; 483 { 484 querybuf buf; 485 const char *cp; 486 char *bp; 487 int n, size, type, len, i; 488 char lookups[MAXDNSLUS]; 489 struct hostent *hp; 490 491 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 492 return (_gethtbyname(name)); 493 494 switch (af) { 495 case AF_INET: 496 size = INADDRSZ; 497 type = T_A; 498 break; 499 case AF_INET6: 500 size = IN6ADDRSZ; 501 type = T_AAAA; 502 break; 503 default: 504 h_errno = NETDB_INTERNAL; 505 errno = EAFNOSUPPORT; 506 return (NULL); 507 } 508 509 host.h_addrtype = af; 510 host.h_length = size; 511 512 /* 513 * if there aren't any dots, it could be a user-level alias. 514 * this is also done in res_query() since we are not the only 515 * function that looks up host names. 516 */ 517 if (!strchr(name, '.') && (cp = __hostalias(name))) 518 name = cp; 519 520 /* 521 * disallow names consisting only of digits/dots, unless 522 * they end in a dot. 523 */ 524 if (isdigit(name[0])) 525 for (cp = name;; ++cp) { 526 if (!*cp) { 527 if (*--cp == '.') 528 break; 529 /* 530 * All-numeric, no dot at the end. 531 * Fake up a hostent as if we'd actually 532 * done a lookup. 533 */ 534 if (inet_pton(af, name, host_addr) <= 0) { 535 h_errno = HOST_NOT_FOUND; 536 return (NULL); 537 } 538 strncpy(hostbuf, name, MAXDNAME); 539 hostbuf[MAXDNAME] = '\0'; 540 bp = hostbuf + MAXDNAME; 541 len = sizeof hostbuf - MAXDNAME; 542 host.h_name = hostbuf; 543 host.h_aliases = host_aliases; 544 host_aliases[0] = NULL; 545 h_addr_ptrs[0] = (char *)host_addr; 546 h_addr_ptrs[1] = NULL; 547 host.h_addr_list = h_addr_ptrs; 548 if (_res.options & RES_USE_INET6) 549 map_v4v6_hostent(&host, &bp, &len); 550 h_errno = NETDB_SUCCESS; 551 return (&host); 552 } 553 if (!isdigit(*cp) && *cp != '.') 554 break; 555 } 556 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) || 557 name[0] == ':') 558 for (cp = name;; ++cp) { 559 if (!*cp) { 560 if (*--cp == '.') 561 break; 562 /* 563 * All-IPv6-legal, no dot at the end. 564 * Fake up a hostent as if we'd actually 565 * done a lookup. 566 */ 567 if (inet_pton(af, name, host_addr) <= 0) { 568 h_errno = HOST_NOT_FOUND; 569 return (NULL); 570 } 571 strncpy(hostbuf, name, MAXDNAME); 572 hostbuf[MAXDNAME] = '\0'; 573 bp = hostbuf + MAXDNAME; 574 len = sizeof hostbuf - MAXDNAME; 575 host.h_name = hostbuf; 576 host.h_aliases = host_aliases; 577 host_aliases[0] = NULL; 578 h_addr_ptrs[0] = (char *)host_addr; 579 h_addr_ptrs[1] = NULL; 580 host.h_addr_list = h_addr_ptrs; 581 h_errno = NETDB_SUCCESS; 582 return (&host); 583 } 584 if (!isxdigit(*cp) && *cp != ':' && *cp != '.') 585 break; 586 } 587 588 bcopy(_res.lookups, lookups, sizeof lookups); 589 if (lookups[0] == '\0') 590 strncpy(lookups, "bf", sizeof lookups); 591 592 hp = (struct hostent *)NULL; 593 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 594 switch (lookups[i]) { 595 #ifdef YP 596 case 'y': 597 hp = _yp_gethtbyname(name); 598 break; 599 #endif 600 case 'b': 601 if ((n = res_search(name, C_IN, T_A, buf.buf, 602 sizeof(buf))) < 0) { 603 dprintf("res_search failed (%d)\n", n); 604 break; 605 } 606 hp = getanswer(&buf, n, name, type); 607 break; 608 case 'f': 609 hp = _gethtbyname(name); 610 break; 611 } 612 } 613 return (hp); 614 } 615 616 struct hostent * 617 gethostbyaddr(addr, len, af) 618 const char *addr; /* XXX should have been def'd as u_char! */ 619 int len, af; 620 { 621 const u_char *uaddr = (const u_char *)addr; 622 static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; 623 static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; 624 int n, size, i; 625 querybuf buf; 626 struct hostent *hp; 627 char qbuf[MAXDNAME+1], *qp; 628 char lookups[MAXDNSLUS]; 629 630 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 631 return (_gethtbyaddr(addr, len, af)); 632 633 if (af == AF_INET6 && len == IN6ADDRSZ && 634 (!bcmp(uaddr, mapped, sizeof mapped) || 635 !bcmp(uaddr, tunnelled, sizeof tunnelled))) { 636 /* Unmap. */ 637 addr += sizeof mapped; 638 uaddr += sizeof mapped; 639 af = AF_INET; 640 len = INADDRSZ; 641 } 642 switch (af) { 643 case AF_INET: 644 size = INADDRSZ; 645 break; 646 case AF_INET6: 647 size = IN6ADDRSZ; 648 break; 649 default: 650 errno = EAFNOSUPPORT; 651 h_errno = NETDB_INTERNAL; 652 return (NULL); 653 } 654 if (size != len) { 655 errno = EINVAL; 656 h_errno = NETDB_INTERNAL; 657 return (NULL); 658 } 659 switch (af) { 660 case AF_INET: 661 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 662 (uaddr[3] & 0xff), 663 (uaddr[2] & 0xff), 664 (uaddr[1] & 0xff), 665 (uaddr[0] & 0xff)); 666 break; 667 case AF_INET6: 668 qp = qbuf; 669 for (n = IN6ADDRSZ - 1; n >= 0; n--) { 670 qp += sprintf(qp, "%x.%x.", 671 uaddr[n] & 0xf, 672 (uaddr[n] >> 4) & 0xf); 673 } 674 strcpy(qp, "ip6.int"); 675 break; 676 default: 677 abort(); 678 } 679 680 bcopy(_res.lookups, lookups, sizeof lookups); 681 if (lookups[0] == '\0') 682 strncpy(lookups, "bf", sizeof lookups); 683 684 hp = (struct hostent *)NULL; 685 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) { 686 switch (lookups[i]) { 687 #ifdef YP 688 case 'y': 689 hp = _yp_gethtbyaddr(addr, len, af); 690 break; 691 #endif 692 case 'b': 693 n = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, 694 sizeof(buf)); 695 if (n < 0) { 696 dprintf("res_query failed (%d)\n", n); 697 break; 698 } 699 hp = getanswer(&buf, n, qbuf, T_PTR); 700 if (hp == NULL) 701 break; 702 hp->h_addrtype = af; 703 hp->h_length = len; 704 bcopy(addr, host_addr, len); 705 h_addr_ptrs[0] = (char *)&host_addr; 706 h_addr_ptrs[1] = (char *)0; 707 if (af == AF_INET && (_res.options & RES_USE_INET6)) { 708 map_v4v6_address((char*)host_addr, 709 (char*)host_addr); 710 hp->h_addrtype = AF_INET6; 711 hp->h_length = IN6ADDRSZ; 712 } 713 h_errno = NETDB_SUCCESS; 714 break; 715 case 'f': 716 hp = _gethtbyaddr(addr, len, af); 717 break; 718 } 719 } 720 return (hp); 721 } 722 723 void 724 _sethtent(f) 725 int f; 726 { 727 if (!hostf) 728 hostf = fopen(_PATH_HOSTS, "r" ); 729 else 730 rewind(hostf); 731 stayopen = f; 732 } 733 734 void 735 _endhtent() 736 { 737 if (hostf && !stayopen) { 738 (void) fclose(hostf); 739 hostf = NULL; 740 } 741 } 742 743 struct hostent * 744 _gethtent() 745 { 746 char *p; 747 register char *cp, **q; 748 int af, len; 749 750 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { 751 h_errno = NETDB_INTERNAL; 752 return (NULL); 753 } 754 again: 755 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { 756 h_errno = HOST_NOT_FOUND; 757 return (NULL); 758 } 759 if (*p == '#') 760 goto again; 761 if (!(cp = strpbrk(p, "#\n"))) 762 goto again; 763 *cp = '\0'; 764 if (!(cp = strpbrk(p, " \t"))) 765 goto again; 766 *cp++ = '\0'; 767 if (inet_pton(AF_INET6, p, host_addr) > 0) { 768 af = AF_INET6; 769 len = IN6ADDRSZ; 770 } else if (inet_pton(AF_INET, p, host_addr) > 0) { 771 if (_res.options & RES_USE_INET6) { 772 map_v4v6_address((char*)host_addr, (char*)host_addr); 773 af = AF_INET6; 774 len = IN6ADDRSZ; 775 } else { 776 af = AF_INET; 777 len = INADDRSZ; 778 } 779 } else { 780 goto again; 781 } 782 h_addr_ptrs[0] = (char *)host_addr; 783 h_addr_ptrs[1] = NULL; 784 host.h_addr_list = h_addr_ptrs; 785 host.h_length = len; 786 host.h_addrtype = af; 787 while (*cp == ' ' || *cp == '\t') 788 cp++; 789 host.h_name = cp; 790 q = host.h_aliases = host_aliases; 791 if ((cp = strpbrk(cp, " \t")) != NULL) 792 *cp++ = '\0'; 793 while (cp && *cp) { 794 if (*cp == ' ' || *cp == '\t') { 795 cp++; 796 continue; 797 } 798 if (q < &host_aliases[MAXALIASES - 1]) 799 *q++ = cp; 800 if ((cp = strpbrk(cp, " \t")) != NULL) 801 *cp++ = '\0'; 802 } 803 *q = NULL; 804 h_errno = NETDB_SUCCESS; 805 return (&host); 806 } 807 808 struct hostent * 809 _gethtbyname(name) 810 const char *name; 811 { 812 struct hostent *hp; 813 814 if (_res.options & RES_USE_INET6) { 815 hp = _gethtbyname2(name, AF_INET6); 816 if (hp) 817 return (hp); 818 } 819 return (_gethtbyname2(name, AF_INET)); 820 } 821 822 struct hostent * 823 _gethtbyname2(name, af) 824 const char *name; 825 int af; 826 { 827 register struct hostent *p; 828 register char **cp; 829 830 _sethtent(0); 831 while ((p = _gethtent()) != NULL) { 832 if (p->h_addrtype != af) 833 continue; 834 if (strcasecmp(p->h_name, name) == 0) 835 break; 836 for (cp = p->h_aliases; *cp != 0; cp++) 837 if (strcasecmp(*cp, name) == 0) 838 goto found; 839 } 840 found: 841 _endhtent(); 842 return (p); 843 } 844 845 struct hostent * 846 _gethtbyaddr(addr, len, af) 847 const char *addr; 848 int len, af; 849 { 850 register struct hostent *p; 851 852 _sethtent(0); 853 while ((p = _gethtent()) != NULL) 854 if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) 855 break; 856 _endhtent(); 857 return (p); 858 } 859 860 static void 861 map_v4v6_address(src, dst) 862 const char *src; 863 char *dst; 864 { 865 u_char *p = (u_char *)dst; 866 char tmp[INADDRSZ]; 867 int i; 868 869 /* Stash a temporary copy so our caller can update in place. */ 870 bcopy(src, tmp, INADDRSZ); 871 /* Mark this ipv6 addr as a mapped ipv4. */ 872 for (i = 0; i < 10; i++) 873 *p++ = 0x00; 874 *p++ = 0xff; 875 *p++ = 0xff; 876 /* Retrieve the saved copy and we're done. */ 877 bcopy(tmp, (void*)p, INADDRSZ); 878 } 879 880 static void 881 map_v4v6_hostent(hp, bpp, lenp) 882 struct hostent *hp; 883 char **bpp; 884 int *lenp; 885 { 886 char **ap; 887 888 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) 889 return; 890 hp->h_addrtype = AF_INET6; 891 hp->h_length = IN6ADDRSZ; 892 for (ap = hp->h_addr_list; *ap; ap++) { 893 int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); 894 895 if (*lenp < (i + IN6ADDRSZ)) { 896 /* Out of memory. Truncate address list here. XXX */ 897 *ap = NULL; 898 return; 899 } 900 *bpp += i; 901 *lenp -= i; 902 map_v4v6_address(*ap, *bpp); 903 *ap = *bpp; 904 *bpp += IN6ADDRSZ; 905 *lenp -= IN6ADDRSZ; 906 } 907 } 908 909 #ifdef RESOLVSORT 910 static void 911 addrsort(ap, num) 912 char **ap; 913 int num; 914 { 915 int i, j; 916 char **p; 917 short aval[MAXADDRS]; 918 int needsort = 0; 919 920 p = ap; 921 for (i = 0; i < num; i++, p++) { 922 for (j = 0 ; (unsigned)j < _res.nsort; j++) 923 if (_res.sort_list[j].addr.s_addr == 924 (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) 925 break; 926 aval[i] = j; 927 if (needsort == 0 && i > 0 && j < aval[i-1]) 928 needsort = i; 929 } 930 if (!needsort) 931 return; 932 933 while (needsort < num) { 934 for (j = needsort - 1; j >= 0; j--) { 935 if (aval[j] > aval[j+1]) { 936 char *hp; 937 938 i = aval[j]; 939 aval[j] = aval[j+1]; 940 aval[j+1] = i; 941 942 hp = ap[j]; 943 ap[j] = ap[j+1]; 944 ap[j+1] = hp; 945 946 } else 947 break; 948 } 949 needsort++; 950 } 951 } 952 #endif 953 954 #if defined(BSD43_BSD43_NFS) || defined(sun) 955 /* some libc's out there are bound internally to these names (UMIPS) */ 956 void 957 ht_sethostent(stayopen) 958 int stayopen; 959 { 960 _sethtent(stayopen); 961 } 962 963 void 964 ht_endhostent() 965 { 966 _endhtent(); 967 } 968 969 struct hostent * 970 ht_gethostbyname(name) 971 char *name; 972 { 973 return (_gethtbyname(name)); 974 } 975 976 struct hostent * 977 ht_gethostbyaddr(addr, len, af) 978 const char *addr; 979 int len, af; 980 { 981 return (_gethtbyaddr(addr, len, af)); 982 } 983 984 struct hostent * 985 gethostent() 986 { 987 return (_gethtent()); 988 } 989 990 void 991 dns_service() 992 { 993 return; 994 } 995 996 #undef dn_skipname 997 dn_skipname(comp_dn, eom) 998 const u_char *comp_dn, *eom; 999 { 1000 return (__dn_skipname(comp_dn, eom)); 1001 } 1002 #endif /*old-style libc with yp junk in it*/ 1003 1004 #ifdef YP 1005 struct hostent * 1006 _yphostent(line) 1007 char *line; 1008 { 1009 static struct in_addr host_addrs[MAXADDRS]; 1010 char *p = line; 1011 char *cp, **q; 1012 char **hap; 1013 struct in_addr *buf; 1014 int more; 1015 1016 host.h_name = NULL; 1017 host.h_addr_list = h_addr_ptrs; 1018 host.h_length = sizeof(u_int32_t); 1019 host.h_addrtype = AF_INET; 1020 hap = h_addr_ptrs; 1021 buf = host_addrs; 1022 q = host.h_aliases = host_aliases; 1023 1024 nextline: 1025 more = 0; 1026 cp = strpbrk(p, " \t"); 1027 if (cp == NULL) { 1028 if (host.h_name == NULL) 1029 return (NULL); 1030 else 1031 goto done; 1032 } 1033 *cp++ = '\0'; 1034 1035 *hap++ = (char *)buf; 1036 (void) inet_aton(p, buf++); 1037 1038 while (*cp == ' ' || *cp == '\t') 1039 cp++; 1040 p = cp; 1041 cp = strpbrk(p, " \t\n"); 1042 if (cp != NULL) { 1043 if (*cp == '\n') 1044 more = 1; 1045 *cp++ = '\0'; 1046 } 1047 if (!host.h_name) 1048 host.h_name = p; 1049 else if (strcmp(host.h_name, p)==0) 1050 ; 1051 else if (q < &host_aliases[MAXALIASES - 1]) 1052 *q++ = p; 1053 p = cp; 1054 if (more) 1055 goto nextline; 1056 1057 while (cp && *cp) { 1058 if (*cp == ' ' || *cp == '\t') { 1059 cp++; 1060 continue; 1061 } 1062 if (*cp == '\n') { 1063 cp++; 1064 goto nextline; 1065 } 1066 if (q < &host_aliases[MAXALIASES - 1]) 1067 *q++ = cp; 1068 cp = strpbrk(cp, " \t"); 1069 if (cp != NULL) 1070 *cp++ = '\0'; 1071 } 1072 done: 1073 *q = NULL; 1074 *hap = NULL; 1075 return (&host); 1076 } 1077 1078 struct hostent * 1079 _yp_gethtbyaddr(addr, len, type) 1080 const char *addr; 1081 int len, type; 1082 { 1083 struct hostent *hp = (struct hostent *)NULL; 1084 static char *__ypcurrent; 1085 int __ypcurrentlen, r; 1086 char name[sizeof("xxx.xxx.xxx.xxx") + 1]; 1087 1088 if (!__ypdomain) { 1089 if (_yp_check(&__ypdomain) == 0) 1090 return (hp); 1091 } 1092 (void)snprintf(name, sizeof name, "%u.%u.%u.%u", 1093 ((unsigned)addr[0] & 0xff), 1094 ((unsigned)addr[1] & 0xff), 1095 ((unsigned)addr[2] & 0xff), 1096 ((unsigned)addr[3] & 0xff)); 1097 if (__ypcurrent) 1098 free(__ypcurrent); 1099 __ypcurrent = NULL; 1100 r = yp_match(__ypdomain, "hosts.byaddr", name, 1101 strlen(name), &__ypcurrent, &__ypcurrentlen); 1102 if (r==0) 1103 hp = _yphostent(__ypcurrent); 1104 if (hp==NULL) 1105 h_errno = HOST_NOT_FOUND; 1106 return (hp); 1107 } 1108 1109 struct hostent * 1110 _yp_gethtbyname(name) 1111 const char *name; 1112 { 1113 struct hostent *hp = (struct hostent *)NULL; 1114 static char *__ypcurrent; 1115 int __ypcurrentlen, r; 1116 1117 if (!__ypdomain) { 1118 if (_yp_check(&__ypdomain) == 0) 1119 return (hp); 1120 } 1121 if (__ypcurrent) 1122 free(__ypcurrent); 1123 __ypcurrent = NULL; 1124 r = yp_match(__ypdomain, "hosts.byname", name, 1125 strlen(name), &__ypcurrent, &__ypcurrentlen); 1126 if (r==0) 1127 hp = _yphostent(__ypcurrent); 1128 if (hp==NULL) 1129 h_errno = HOST_NOT_FOUND; 1130 return (hp); 1131 } 1132 #endif 1133