1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 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 #if defined(LIBC_SCCS) && !defined(lint) 55 static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; 56 static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $"; 57 #endif /* LIBC_SCCS and not lint */ 58 #include <sys/cdefs.h> 59 __FBSDID("$FreeBSD$"); 60 61 #include <sys/param.h> 62 #include <sys/socket.h> 63 #include <netinet/in.h> 64 #include <arpa/inet.h> 65 #include <arpa/nameser.h> 66 67 #include <stdio.h> 68 #include <stdlib.h> 69 #include <unistd.h> 70 #include <string.h> 71 #include <netdb.h> 72 #include <resolv.h> 73 #include <ctype.h> 74 #include <errno.h> 75 #include <syslog.h> 76 #include <stdarg.h> 77 #include <nsswitch.h> 78 79 #include "netdb_private.h" 80 #include "res_config.h" 81 82 #define SPRINTF(x) ((size_t)sprintf x) 83 84 static const char AskedForGot[] = 85 "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; 86 87 #ifdef RESOLVSORT 88 static void addrsort(char **, int, res_state); 89 #endif 90 91 #ifdef DEBUG 92 static void dbg_printf(char *, int, res_state) __printflike(1, 0); 93 #endif 94 95 #define MAXPACKET (64*1024) 96 97 typedef union { 98 HEADER hdr; 99 u_char buf[MAXPACKET]; 100 } querybuf; 101 102 typedef union { 103 int32_t al; 104 char ac; 105 } align; 106 107 int _dns_ttl_; 108 109 #ifdef DEBUG 110 static void 111 dbg_printf(char *msg, int num, res_state res) 112 { 113 if (res->options & RES_DEBUG) { 114 int save = errno; 115 116 printf(msg, num); 117 errno = save; 118 } 119 } 120 #else 121 # define dbg_printf(msg, num, res) /*nada*/ 122 #endif 123 124 #define BOUNDED_INCR(x) \ 125 do { \ 126 cp += x; \ 127 if (cp > eom) { \ 128 RES_SET_H_ERRNO(statp, NO_RECOVERY); \ 129 return (-1); \ 130 } \ 131 } while (0) 132 133 #define BOUNDS_CHECK(ptr, count) \ 134 do { \ 135 if ((ptr) + (count) > eom) { \ 136 RES_SET_H_ERRNO(statp, NO_RECOVERY); \ 137 return (-1); \ 138 } \ 139 } while (0) 140 141 static int 142 gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype, 143 struct hostent *he, struct hostent_data *hed, res_state statp) 144 { 145 const HEADER *hp; 146 const u_char *cp; 147 int n; 148 const u_char *eom, *erdata; 149 char *bp, *ep, **ap, **hap; 150 int type, class, ancount, qdcount; 151 int haveanswer, had_error; 152 int toobig = 0; 153 char tbuf[MAXDNAME]; 154 const char *tname; 155 int (*name_ok)(const char *); 156 157 tname = qname; 158 he->h_name = NULL; 159 eom = answer->buf + anslen; 160 switch (qtype) { 161 case T_A: 162 case T_AAAA: 163 name_ok = res_hnok; 164 break; 165 case T_PTR: 166 name_ok = res_dnok; 167 break; 168 default: 169 RES_SET_H_ERRNO(statp, NO_RECOVERY); 170 return (-1); /* XXX should be abort(); */ 171 } 172 /* 173 * find first satisfactory answer 174 */ 175 hp = &answer->hdr; 176 ancount = ntohs(hp->ancount); 177 qdcount = ntohs(hp->qdcount); 178 bp = hed->hostbuf; 179 ep = hed->hostbuf + sizeof hed->hostbuf; 180 cp = answer->buf; 181 BOUNDED_INCR(HFIXEDSZ); 182 if (qdcount != 1) { 183 RES_SET_H_ERRNO(statp, NO_RECOVERY); 184 return (-1); 185 } 186 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 187 if ((n < 0) || !(*name_ok)(bp)) { 188 RES_SET_H_ERRNO(statp, NO_RECOVERY); 189 return (-1); 190 } 191 BOUNDED_INCR(n + QFIXEDSZ); 192 if (qtype == T_A || qtype == T_AAAA) { 193 /* res_send() has already verified that the query name is the 194 * same as the one we sent; this just gets the expanded name 195 * (i.e., with the succeeding search-domain tacked on). 196 */ 197 n = strlen(bp) + 1; /* for the \0 */ 198 if (n >= MAXHOSTNAMELEN) { 199 RES_SET_H_ERRNO(statp, NO_RECOVERY); 200 return (-1); 201 } 202 he->h_name = bp; 203 bp += n; 204 /* The qname can be abbreviated, but h_name is now absolute. */ 205 qname = he->h_name; 206 } 207 ap = hed->host_aliases; 208 *ap = NULL; 209 he->h_aliases = hed->host_aliases; 210 hap = hed->h_addr_ptrs; 211 *hap = NULL; 212 he->h_addr_list = hed->h_addr_ptrs; 213 haveanswer = 0; 214 had_error = 0; 215 _dns_ttl_ = -1; 216 while (ancount-- > 0 && cp < eom && !had_error) { 217 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 218 if ((n < 0) || !(*name_ok)(bp)) { 219 had_error++; 220 continue; 221 } 222 cp += n; /* name */ 223 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 224 type = _getshort(cp); 225 cp += INT16SZ; /* type */ 226 class = _getshort(cp); 227 cp += INT16SZ; /* class */ 228 if (qtype == T_A && type == T_A) 229 _dns_ttl_ = _getlong(cp); 230 cp += INT32SZ; /* TTL */ 231 n = _getshort(cp); 232 cp += INT16SZ; /* len */ 233 BOUNDS_CHECK(cp, n); 234 erdata = cp + n; 235 if (class != C_IN) { 236 /* XXX - debug? syslog? */ 237 cp += n; 238 continue; /* XXX - had_error++ ? */ 239 } 240 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 241 if (ap >= &hed->host_aliases[_MAXALIASES-1]) 242 continue; 243 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 244 if ((n < 0) || !(*name_ok)(tbuf)) { 245 had_error++; 246 continue; 247 } 248 cp += n; 249 if (cp != erdata) { 250 RES_SET_H_ERRNO(statp, NO_RECOVERY); 251 return (-1); 252 } 253 /* Store alias. */ 254 *ap++ = bp; 255 n = strlen(bp) + 1; /* for the \0 */ 256 if (n >= MAXHOSTNAMELEN) { 257 had_error++; 258 continue; 259 } 260 bp += n; 261 /* Get canonical name. */ 262 n = strlen(tbuf) + 1; /* for the \0 */ 263 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 264 had_error++; 265 continue; 266 } 267 strcpy(bp, tbuf); 268 he->h_name = bp; 269 bp += n; 270 continue; 271 } 272 if (qtype == T_PTR && type == T_CNAME) { 273 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 274 if (n < 0 || !res_dnok(tbuf)) { 275 had_error++; 276 continue; 277 } 278 cp += n; 279 if (cp != erdata) { 280 RES_SET_H_ERRNO(statp, NO_RECOVERY); 281 return (-1); 282 } 283 /* Get canonical name. */ 284 n = strlen(tbuf) + 1; /* for the \0 */ 285 if (n > ep - bp || n >= MAXHOSTNAMELEN) { 286 had_error++; 287 continue; 288 } 289 strcpy(bp, tbuf); 290 tname = bp; 291 bp += n; 292 continue; 293 } 294 if (type != qtype) { 295 #ifdef DEBUG 296 if (type != T_KEY && type != T_SIG && 297 type != T_DNAME && type != T_RRSIG) 298 syslog(LOG_NOTICE|LOG_AUTH, 299 "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"", 300 qname, p_class(C_IN), p_type(qtype), 301 p_type(type)); 302 #endif 303 cp += n; 304 continue; /* XXX - had_error++ ? */ 305 } 306 switch (type) { 307 case T_PTR: 308 if (strcasecmp(tname, bp) != 0) { 309 syslog(LOG_NOTICE|LOG_AUTH, 310 AskedForGot, qname, bp); 311 cp += n; 312 continue; /* XXX - had_error++ ? */ 313 } 314 n = dn_expand(answer->buf, eom, cp, bp, ep - bp); 315 if ((n < 0) || !res_hnok(bp)) { 316 had_error++; 317 break; 318 } 319 #if MULTI_PTRS_ARE_ALIASES 320 cp += n; 321 if (cp != erdata) { 322 RES_SET_H_ERRNO(statp, NO_RECOVERY); 323 return (-1); 324 } 325 if (!haveanswer) 326 he->h_name = bp; 327 else if (ap < &hed->host_aliases[_MAXALIASES-1]) 328 *ap++ = bp; 329 else 330 n = -1; 331 if (n != -1) { 332 n = strlen(bp) + 1; /* for the \0 */ 333 if (n >= MAXHOSTNAMELEN) { 334 had_error++; 335 break; 336 } 337 bp += n; 338 } 339 break; 340 #else 341 he->h_name = bp; 342 if (statp->options & RES_USE_INET6) { 343 n = strlen(bp) + 1; /* for the \0 */ 344 if (n >= MAXHOSTNAMELEN) { 345 had_error++; 346 break; 347 } 348 bp += n; 349 _map_v4v6_hostent(he, &bp, ep); 350 } 351 RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 352 return (0); 353 #endif 354 case T_A: 355 case T_AAAA: 356 if (strcasecmp(he->h_name, bp) != 0) { 357 syslog(LOG_NOTICE|LOG_AUTH, 358 AskedForGot, he->h_name, bp); 359 cp += n; 360 continue; /* XXX - had_error++ ? */ 361 } 362 if (n != he->h_length) { 363 cp += n; 364 continue; 365 } 366 if (!haveanswer) { 367 int nn; 368 369 he->h_name = bp; 370 nn = strlen(bp) + 1; /* for the \0 */ 371 bp += nn; 372 } 373 374 bp += sizeof(align) - ((u_long)bp % sizeof(align)); 375 376 if (bp + n >= ep) { 377 dbg_printf("size (%d) too big\n", n, statp); 378 had_error++; 379 continue; 380 } 381 if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) { 382 if (!toobig++) 383 dbg_printf("Too many addresses (%d)\n", 384 _MAXADDRS, statp); 385 cp += n; 386 continue; 387 } 388 memcpy(*hap++ = bp, cp, n); 389 bp += n; 390 cp += n; 391 if (cp != erdata) { 392 RES_SET_H_ERRNO(statp, NO_RECOVERY); 393 return (-1); 394 } 395 break; 396 default: 397 dbg_printf("Impossible condition (type=%d)\n", type, 398 statp); 399 RES_SET_H_ERRNO(statp, NO_RECOVERY); 400 return (-1); 401 /* BIND has abort() here, too risky on bad data */ 402 } 403 if (!had_error) 404 haveanswer++; 405 } 406 if (haveanswer) { 407 *ap = NULL; 408 *hap = NULL; 409 # if defined(RESOLVSORT) 410 /* 411 * Note: we sort even if host can take only one address 412 * in its return structures - should give it the "best" 413 * address in that case, not some random one 414 */ 415 if (statp->nsort && haveanswer > 1 && qtype == T_A) 416 addrsort(hed->h_addr_ptrs, haveanswer, statp); 417 # endif /*RESOLVSORT*/ 418 if (!he->h_name) { 419 n = strlen(qname) + 1; /* for the \0 */ 420 if (n > ep - bp || n >= MAXHOSTNAMELEN) 421 goto no_recovery; 422 strcpy(bp, qname); 423 he->h_name = bp; 424 bp += n; 425 } 426 if (statp->options & RES_USE_INET6) 427 _map_v4v6_hostent(he, &bp, ep); 428 RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 429 return (0); 430 } 431 no_recovery: 432 RES_SET_H_ERRNO(statp, NO_RECOVERY); 433 return (-1); 434 } 435 436 /* XXX: for async DNS resolver in ypserv */ 437 struct hostent * 438 __dns_getanswer(const char *answer, int anslen, const char *qname, int qtype) 439 { 440 struct hostent *he; 441 struct hostent_data *hed; 442 int error; 443 res_state statp; 444 445 statp = __res_state(); 446 if ((he = __hostent_init()) == NULL || 447 (hed = __hostent_data_init()) == NULL) { 448 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 449 return (NULL); 450 } 451 switch (qtype) { 452 case T_AAAA: 453 he->h_addrtype = AF_INET6; 454 he->h_length = NS_IN6ADDRSZ; 455 break; 456 case T_A: 457 default: 458 he->h_addrtype = AF_INET; 459 he->h_length = NS_INADDRSZ; 460 break; 461 } 462 463 error = gethostanswer((const querybuf *)answer, anslen, qname, qtype, 464 he, hed, statp); 465 return (error == 0) ? he : NULL; 466 } 467 468 int 469 _dns_gethostbyname(void *rval, void *cb_data, va_list ap) 470 { 471 const char *name; 472 int af; 473 char *buffer; 474 size_t buflen; 475 int *errnop, *h_errnop; 476 struct hostent *hptr, he; 477 struct hostent_data *hed; 478 querybuf *buf; 479 int n, type, error; 480 res_state statp; 481 482 name = va_arg(ap, const char *); 483 af = va_arg(ap, int); 484 hptr = va_arg(ap, struct hostent *); 485 buffer = va_arg(ap, char *); 486 buflen = va_arg(ap, size_t); 487 errnop = va_arg(ap, int *); 488 h_errnop = va_arg(ap, int *); 489 490 *((struct hostent **)rval) = NULL; 491 492 statp = __res_state(); 493 if ((hed = __hostent_data_init()) == NULL) { 494 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 495 *h_errnop = statp->res_h_errno; 496 return (NS_NOTFOUND); 497 } 498 499 he.h_addrtype = af; 500 switch (af) { 501 case AF_INET: 502 he.h_length = NS_INADDRSZ; 503 type = T_A; 504 break; 505 case AF_INET6: 506 he.h_length = NS_IN6ADDRSZ; 507 type = T_AAAA; 508 break; 509 default: 510 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 511 *h_errnop = statp->res_h_errno; 512 errno = EAFNOSUPPORT; 513 return (NS_UNAVAIL); 514 } 515 516 if ((buf = malloc(sizeof(*buf))) == NULL) { 517 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 518 *h_errnop = statp->res_h_errno; 519 return (NS_NOTFOUND); 520 } 521 n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf)); 522 if (n < 0) { 523 free(buf); 524 dbg_printf("res_nsearch failed (%d)\n", n, statp); 525 *h_errnop = statp->res_h_errno; 526 return (NS_NOTFOUND); 527 } else if (n > sizeof(buf->buf)) { 528 free(buf); 529 dbg_printf("static buffer is too small (%d)\n", n, statp); 530 *h_errnop = statp->res_h_errno; 531 return (NS_UNAVAIL); 532 } 533 error = gethostanswer(buf, n, name, type, &he, hed, statp); 534 free(buf); 535 if (error != 0) { 536 *h_errnop = statp->res_h_errno; 537 switch (statp->res_h_errno) { 538 case HOST_NOT_FOUND: 539 return (NS_NOTFOUND); 540 case TRY_AGAIN: 541 return (NS_TRYAGAIN); 542 default: 543 return (NS_UNAVAIL); 544 } 545 /*NOTREACHED*/ 546 } 547 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 548 *errnop = errno; 549 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 550 *h_errnop = statp->res_h_errno; 551 return (NS_RETURN); 552 } 553 RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 554 *((struct hostent **)rval) = hptr; 555 return (NS_SUCCESS); 556 } 557 558 int 559 _dns_gethostbyaddr(void *rval, void *cb_data, va_list ap) 560 { 561 const void *addr; 562 socklen_t len; 563 int af; 564 char *buffer; 565 size_t buflen; 566 int *errnop, *h_errnop; 567 const u_char *uaddr; 568 struct hostent *hptr, he; 569 struct hostent_data *hed; 570 int n; 571 querybuf *buf; 572 char qbuf[MAXDNAME+1], *qp; 573 res_state statp; 574 #ifdef SUNSECURITY 575 struct hostdata rhd; 576 struct hostent *rhe; 577 char **haddr; 578 u_long old_options; 579 char hname2[MAXDNAME+1], numaddr[46]; 580 int ret_h_error; 581 #endif /*SUNSECURITY*/ 582 583 addr = va_arg(ap, const void *); 584 len = va_arg(ap, socklen_t); 585 af = va_arg(ap, int); 586 hptr = va_arg(ap, struct hostent *); 587 buffer = va_arg(ap, char *); 588 buflen = va_arg(ap, size_t); 589 errnop = va_arg(ap, int *); 590 h_errnop = va_arg(ap, int *); 591 uaddr = (const u_char *)addr; 592 593 *((struct hostent **)rval) = NULL; 594 595 statp = __res_state(); 596 if ((hed = __hostent_data_init()) == NULL) { 597 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 598 *h_errnop = statp->res_h_errno; 599 return (NS_NOTFOUND); 600 } 601 602 switch (af) { 603 case AF_INET: 604 (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", 605 (uaddr[3] & 0xff), 606 (uaddr[2] & 0xff), 607 (uaddr[1] & 0xff), 608 (uaddr[0] & 0xff)); 609 break; 610 case AF_INET6: 611 qp = qbuf; 612 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) { 613 qp += SPRINTF((qp, "%x.%x.", 614 uaddr[n] & 0xf, 615 (uaddr[n] >> 4) & 0xf)); 616 } 617 strlcat(qbuf, "ip6.arpa", sizeof(qbuf)); 618 break; 619 default: 620 abort(); 621 } 622 if ((buf = malloc(sizeof(*buf))) == NULL) { 623 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 624 *h_errnop = statp->res_h_errno; 625 return NS_NOTFOUND; 626 } 627 n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf, 628 sizeof buf->buf); 629 if (n < 0) { 630 free(buf); 631 dbg_printf("res_nquery failed (%d)\n", n, statp); 632 *h_errnop = statp->res_h_errno; 633 return (NS_UNAVAIL); 634 } 635 if (n > sizeof buf->buf) { 636 free(buf); 637 dbg_printf("static buffer is too small (%d)\n", n, statp); 638 *h_errnop = statp->res_h_errno; 639 return (NS_UNAVAIL); 640 } 641 if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) { 642 free(buf); 643 *h_errnop = statp->res_h_errno; 644 switch (statp->res_h_errno) { 645 case HOST_NOT_FOUND: 646 return (NS_NOTFOUND); 647 case TRY_AGAIN: 648 return (NS_TRYAGAIN); 649 default: 650 return (NS_UNAVAIL); 651 } 652 /*NOTREACHED*/ 653 } 654 free(buf); 655 #ifdef SUNSECURITY 656 if (af == AF_INET) { 657 /* 658 * turn off search as the name should be absolute, 659 * 'localhost' should be matched by defnames 660 */ 661 strncpy(hname2, he.h_name, MAXDNAME); 662 hname2[MAXDNAME] = '\0'; 663 old_options = statp->options; 664 statp->options &= ~RES_DNSRCH; 665 statp->options |= RES_DEFNAMES; 666 memset(&rhd, 0, sizeof rhd); 667 rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data, 668 sizeof(rhd.data), &ret_h_error); 669 if (rhe == NULL) { 670 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 671 strlcpy(numaddr, "UNKNOWN", sizeof(numaddr)); 672 syslog(LOG_NOTICE|LOG_AUTH, 673 "gethostbyaddr: No A record for %s (verifying [%s])", 674 hname2, numaddr); 675 statp->options = old_options; 676 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 677 *h_errnop = statp->res_h_errno; 678 return (NS_NOTFOUND); 679 } 680 statp->options = old_options; 681 for (haddr = rhe->h_addr_list; *haddr; haddr++) 682 if (!memcmp(*haddr, addr, NS_INADDRSZ)) 683 break; 684 if (!*haddr) { 685 if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL) 686 strlcpy(numaddr, "UNKNOWN", sizeof(numaddr)); 687 syslog(LOG_NOTICE|LOG_AUTH, 688 "gethostbyaddr: A record of %s != PTR record [%s]", 689 hname2, numaddr); 690 RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 691 *h_errnop = statp->res_h_errno; 692 return (NS_NOTFOUND); 693 } 694 } 695 #endif /*SUNSECURITY*/ 696 he.h_addrtype = af; 697 he.h_length = len; 698 memcpy(hed->host_addr, uaddr, len); 699 hed->h_addr_ptrs[0] = (char *)hed->host_addr; 700 hed->h_addr_ptrs[1] = NULL; 701 if (af == AF_INET && (statp->options & RES_USE_INET6)) { 702 _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr); 703 he.h_addrtype = AF_INET6; 704 he.h_length = NS_IN6ADDRSZ; 705 } 706 if (__copy_hostent(&he, hptr, buffer, buflen) != 0) { 707 *errnop = errno; 708 RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 709 *h_errnop = statp->res_h_errno; 710 return (NS_RETURN); 711 } 712 RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 713 *((struct hostent **)rval) = hptr; 714 return (NS_SUCCESS); 715 } 716 717 #ifdef RESOLVSORT 718 static void 719 addrsort(char **ap, int num, res_state res) 720 { 721 int i, j; 722 char **p; 723 short aval[_MAXADDRS]; 724 int needsort = 0; 725 726 p = ap; 727 for (i = 0; i < num; i++, p++) { 728 for (j = 0 ; (unsigned)j < res->nsort; j++) 729 if (res->sort_list[j].addr.s_addr == 730 (((struct in_addr *)(*p))->s_addr & res->sort_list[j].mask)) 731 break; 732 aval[i] = j; 733 if (needsort == 0 && i > 0 && j < aval[i-1]) 734 needsort = i; 735 } 736 if (!needsort) 737 return; 738 739 while (needsort < num) { 740 for (j = needsort - 1; j >= 0; j--) { 741 if (aval[j] > aval[j+1]) { 742 char *hp; 743 744 i = aval[j]; 745 aval[j] = aval[j+1]; 746 aval[j+1] = i; 747 748 hp = ap[j]; 749 ap[j] = ap[j+1]; 750 ap[j+1] = hp; 751 752 } else 753 break; 754 } 755 needsort++; 756 } 757 } 758 #endif 759 760 void 761 _sethostdnsent(int stayopen) 762 { 763 res_state statp; 764 765 statp = __res_state(); 766 if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) 767 return; 768 if (stayopen) 769 statp->options |= RES_STAYOPEN | RES_USEVC; 770 } 771 772 void 773 _endhostdnsent(void) 774 { 775 res_state statp; 776 777 statp = __res_state(); 778 statp->options &= ~(RES_STAYOPEN | RES_USEVC); 779 res_nclose(statp); 780 } 781