1 /* $FreeBSD: src/lib/libc/net/name6.c,v 1.6.2.9 2002/11/02 18:54:57 ume Exp $ */ 2 /* $DragonFly: src/lib/libc/net/name6.c,v 1.5 2005/01/31 22:29:33 dillon Exp $ */ 3 /* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */ 4 5 /* 6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 7 * 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 project 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 PROJECT 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 PROJECT 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 /* 34 * ++Copyright++ 1985, 1988, 1993 35 * - 36 * Copyright (c) 1985, 1988, 1993 37 * The Regents of the University of California. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgement: 49 * This product includes software developed by the University of 50 * California, Berkeley and its contributors. 51 * 4. Neither the name of the University nor the names of its contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 * - 67 * Portions Copyright (c) 1993 by Digital Equipment Corporation. 68 * 69 * Permission to use, copy, modify, and distribute this software for any 70 * purpose with or without fee is hereby granted, provided that the above 71 * copyright notice and this permission notice appear in all copies, and that 72 * the name of Digital Equipment Corporation not be used in advertising or 73 * publicity pertaining to distribution of the document or software without 74 * specific, written prior permission. 75 * 76 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL 77 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES 78 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT 79 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 80 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 81 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 82 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 83 * SOFTWARE. 84 * - 85 * --Copyright-- 86 */ 87 88 /* 89 * Atsushi Onoe <onoe@sm.sony.co.jp> 90 */ 91 92 /* 93 * TODO for thread safe 94 * use mutex for _hostconf, _hostconf_init. 95 * rewrite resolvers to be thread safe 96 */ 97 98 #include "namespace.h" 99 #include <sys/param.h> 100 #include <sys/socket.h> 101 #include <sys/time.h> 102 #include <sys/queue.h> 103 #include <netinet/in.h> 104 105 #include <arpa/inet.h> 106 #include <arpa/nameser.h> 107 108 #include <errno.h> 109 #include <netdb.h> 110 #include <resolv.h> 111 #include <stdio.h> 112 #include <stdlib.h> 113 #include <string.h> 114 #include <unistd.h> 115 #include "un-namespace.h" 116 117 #ifndef _PATH_HOSTS 118 #define _PATH_HOSTS "/etc/hosts" 119 #endif 120 121 #ifndef MAXALIASES 122 #define MAXALIASES 10 123 #endif 124 #ifndef MAXADDRS 125 #define MAXADDRS 20 126 #endif 127 #ifndef MAXDNAME 128 #define MAXDNAME 1025 129 #endif 130 131 #ifdef INET6 132 #define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \ 133 sizeof(struct in_addr)) 134 #else 135 #define ADDRLEN(af) sizeof(struct in_addr) 136 #endif 137 138 #define MAPADDR(ab, ina) \ 139 do { \ 140 memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \ 141 memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \ 142 memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \ 143 } while (0) 144 #define MAPADDRENABLED(flags) \ 145 (((flags) & AI_V4MAPPED) || \ 146 (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled())) 147 148 union inx_addr { 149 struct in_addr in_addr; 150 #ifdef INET6 151 struct in6_addr in6_addr; 152 #endif 153 struct { 154 u_char mau_zero[10]; 155 u_char mau_one[2]; 156 struct in_addr mau_inaddr; 157 } map_addr_un; 158 #define map_zero map_addr_un.mau_zero 159 #define map_one map_addr_un.mau_one 160 #define map_inaddr map_addr_un.mau_inaddr 161 }; 162 163 static struct hostent *_hpcopy(struct hostent *hp, int *errp); 164 static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp); 165 static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp); 166 #ifdef INET6 167 static struct hostent *_hpmapv6(struct hostent *hp, int *errp); 168 #endif 169 static struct hostent *_hpsort(struct hostent *hp); 170 static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp); 171 static char *_hgetword(char **pp); 172 static int _mapped_addr_enabled(void); 173 174 static FILE *_files_open(int *errp); 175 static struct hostent *_files_ghbyname(const char *name, int af, int *errp); 176 static struct hostent *_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 177 static void _files_shent(int stayopen); 178 static void _files_ehent(void); 179 #ifdef YP 180 static struct hostent *_nis_ghbyname(const char *name, int af, int *errp); 181 static struct hostent *_nis_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 182 #endif 183 static struct hostent *_dns_ghbyname(const char *name, int af, int *errp); 184 static struct hostent *_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 185 static void _dns_shent(int stayopen); 186 static void _dns_ehent(void); 187 #ifdef ICMPNL 188 static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 189 #endif /* ICMPNL */ 190 191 /* Make getipnodeby*() thread-safe in libc for use with kernel threads. */ 192 #include "libc_private.h" 193 #include "spinlock.h" 194 /* 195 * XXX: Our res_*() is not thread-safe. So, we share lock between 196 * getaddrinfo() and getipnodeby*(). Still, we cannot use 197 * getaddrinfo() and getipnodeby*() in conjunction with other 198 * functions which call res_*(). 199 */ 200 extern spinlock_t __getaddrinfo_thread_lock; 201 #define THREAD_LOCK() \ 202 if (__isthreaded) _SPINLOCK(&__getaddrinfo_thread_lock); 203 #define THREAD_UNLOCK() \ 204 if (__isthreaded) _SPINUNLOCK(&__getaddrinfo_thread_lock); 205 206 /* 207 * Select order host function. 208 */ 209 #define MAXHOSTCONF 4 210 211 #ifndef HOSTCONF 212 # define HOSTCONF "/etc/host.conf" 213 #endif /* !HOSTCONF */ 214 215 struct _hostconf { 216 struct hostent *(*byname)(const char *name, int af, int *errp); 217 struct hostent *(*byaddr)(const void *addr, int addrlen, int af, int *errp); 218 }; 219 220 /* default order */ 221 static struct _hostconf _hostconf[MAXHOSTCONF] = { 222 { _dns_ghbyname, _dns_ghbyaddr }, 223 { _files_ghbyname, _files_ghbyaddr }, 224 #ifdef ICMPNL 225 { NULL, _icmp_ghbyaddr }, 226 #endif /* ICMPNL */ 227 }; 228 229 static int _hostconf_init_done; 230 static void _hostconf_init(void); 231 232 /* 233 * Initialize hostconf structure. 234 */ 235 236 static void 237 _hostconf_init(void) 238 { 239 FILE *fp; 240 int n; 241 char *p, *line; 242 char buf[BUFSIZ]; 243 244 _hostconf_init_done = 1; 245 n = 0; 246 p = HOSTCONF; 247 if ((fp = fopen(p, "r")) == NULL) 248 return; 249 while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) { 250 line = buf; 251 if ((p = _hgetword(&line)) == NULL) 252 continue; 253 do { 254 if (strcmp(p, "hosts") == 0 255 || strcmp(p, "local") == 0 256 || strcmp(p, "file") == 0 257 || strcmp(p, "files") == 0) { 258 _hostconf[n].byname = _files_ghbyname; 259 _hostconf[n].byaddr = _files_ghbyaddr; 260 n++; 261 } 262 else if (strcmp(p, "dns") == 0 263 || strcmp(p, "bind") == 0) { 264 _hostconf[n].byname = _dns_ghbyname; 265 _hostconf[n].byaddr = _dns_ghbyaddr; 266 n++; 267 } 268 #ifdef YP 269 else if (strcmp(p, "nis") == 0) { 270 _hostconf[n].byname = _nis_ghbyname; 271 _hostconf[n].byaddr = _nis_ghbyaddr; 272 n++; 273 } 274 #endif 275 #ifdef ICMPNL 276 else if (strcmp(p, "icmp") == 0) { 277 _hostconf[n].byname = NULL; 278 _hostconf[n].byaddr = _icmp_ghbyaddr; 279 n++; 280 } 281 #endif /* ICMPNL */ 282 } while ((p = _hgetword(&line)) != NULL); 283 } 284 fclose(fp); 285 if (n < 0) { 286 /* no keyword found. do not change default configuration */ 287 return; 288 } 289 for (; n < MAXHOSTCONF; n++) { 290 _hostconf[n].byname = NULL; 291 _hostconf[n].byaddr = NULL; 292 } 293 } 294 295 /* 296 * Check if kernel supports mapped address. 297 * implementation dependent 298 */ 299 #ifdef __KAME__ 300 #include <sys/sysctl.h> 301 #endif /* __KAME__ */ 302 303 static int 304 _mapped_addr_enabled(void) 305 { 306 /* implementation dependent check */ 307 #if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR) 308 int mib[4]; 309 size_t len; 310 int val; 311 312 mib[0] = CTL_NET; 313 mib[1] = PF_INET6; 314 mib[2] = IPPROTO_IPV6; 315 mib[3] = IPV6CTL_MAPPED_ADDR; 316 len = sizeof(val); 317 if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0) 318 return 1; 319 #endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */ 320 return 0; 321 } 322 323 /* 324 * Functions defined in RFC2553 325 * getipnodebyname, getipnodebyaddr, freehostent 326 */ 327 328 static struct hostent * 329 _ghbyname(const char *name, int af, int flags, int *errp) 330 { 331 struct hostent *hp; 332 int i; 333 334 if (flags & AI_ADDRCONFIG) { 335 int s; 336 337 /* 338 * TODO: 339 * Note that implementation dependent test for address 340 * configuration should be done everytime called 341 * (or apropriate interval), 342 * because addresses will be dynamically assigned or deleted. 343 */ 344 if (af == AF_UNSPEC) { 345 if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0) 346 af = AF_INET; 347 else { 348 _close(s); 349 if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0) 350 af = AF_INET6; 351 else 352 _close(s); 353 } 354 355 } 356 if (af != AF_UNSPEC) { 357 if ((s = _socket(af, SOCK_DGRAM, 0)) < 0) 358 return NULL; 359 _close(s); 360 } 361 } 362 363 THREAD_LOCK(); 364 for (i = 0; i < MAXHOSTCONF; i++) { 365 if (_hostconf[i].byname 366 && (hp = (*_hostconf[i].byname)(name, af, errp)) != NULL) { 367 THREAD_UNLOCK(); 368 return hp; 369 } 370 } 371 THREAD_UNLOCK(); 372 373 return NULL; 374 } 375 376 /* getipnodebyname() internal routine for multiple query(PF_UNSPEC) support. */ 377 struct hostent * 378 _getipnodebyname_multi(const char *name, int af, int flags, int *errp) 379 { 380 struct hostent *hp; 381 union inx_addr addrbuf; 382 383 /* XXX: PF_UNSPEC is only supposed to be passed from getaddrinfo() */ 384 if (af != AF_INET 385 #ifdef INET6 386 && af != AF_INET6 387 #endif 388 && af != PF_UNSPEC 389 ) 390 { 391 *errp = NO_RECOVERY; 392 return NULL; 393 } 394 395 #ifdef INET6 396 /* special case for literal address */ 397 if (inet_pton(AF_INET6, name, &addrbuf) == 1) { 398 if (af != AF_INET6) { 399 *errp = HOST_NOT_FOUND; 400 return NULL; 401 } 402 return _hpaddr(af, name, &addrbuf, errp); 403 } 404 #endif 405 if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) { 406 if (af != AF_INET) { 407 if (MAPADDRENABLED(flags)) { 408 MAPADDR(&addrbuf, &addrbuf.in_addr); 409 } else { 410 *errp = HOST_NOT_FOUND; 411 return NULL; 412 } 413 } 414 return _hpaddr(af, name, &addrbuf, errp); 415 } 416 417 if (!_hostconf_init_done) 418 _hostconf_init(); 419 420 *errp = HOST_NOT_FOUND; 421 hp = _ghbyname(name, af, flags, errp); 422 423 #ifdef INET6 424 if (af == AF_INET6 425 && ((flags & AI_ALL) || hp == NULL) 426 && (MAPADDRENABLED(flags))) { 427 struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); 428 if (hp == NULL) 429 hp = _hpmapv6(hp2, errp); 430 else { 431 if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { 432 freehostent(hp2); 433 hp2 = NULL; 434 } 435 hp = _hpmerge(hp, hp2, errp); 436 } 437 } 438 #endif 439 return _hpsort(hp); 440 } 441 442 struct hostent * 443 getipnodebyname(const char *name, int af, int flags, int *errp) 444 { 445 if (af != AF_INET 446 #ifdef INET6 447 && af != AF_INET6 448 #endif 449 ) 450 { 451 *errp = NO_RECOVERY; 452 return NULL; 453 } 454 return(_getipnodebyname_multi(name, af ,flags, errp)); 455 } 456 457 struct hostent * 458 getipnodebyaddr(const void *src, size_t len, int af, int *errp) 459 { 460 struct hostent *hp; 461 int i; 462 #ifdef INET6 463 struct in6_addr addrbuf; 464 #else 465 struct in_addr addrbuf; 466 #endif 467 468 *errp = HOST_NOT_FOUND; 469 470 switch (af) { 471 case AF_INET: 472 if (len != sizeof(struct in_addr)) { 473 *errp = NO_RECOVERY; 474 return NULL; 475 } 476 if ((long)src & ~(sizeof(struct in_addr) - 1)) { 477 memcpy(&addrbuf, src, len); 478 src = &addrbuf; 479 } 480 if (((struct in_addr *)src)->s_addr == 0) 481 return NULL; 482 break; 483 #ifdef INET6 484 case AF_INET6: 485 if (len != sizeof(struct in6_addr)) { 486 *errp = NO_RECOVERY; 487 return NULL; 488 } 489 if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/ 490 memcpy(&addrbuf, src, len); 491 src = &addrbuf; 492 } 493 if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src)) 494 return NULL; 495 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) 496 || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { 497 src = (char *)src + 498 (sizeof(struct in6_addr) - sizeof(struct in_addr)); 499 af = AF_INET; 500 len = sizeof(struct in_addr); 501 } 502 break; 503 #endif 504 default: 505 *errp = NO_RECOVERY; 506 return NULL; 507 } 508 509 if (!_hostconf_init_done) 510 _hostconf_init(); 511 THREAD_LOCK(); 512 for (i = 0; i < MAXHOSTCONF; i++) { 513 if (_hostconf[i].byaddr 514 && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL) { 515 THREAD_UNLOCK(); 516 return hp; 517 } 518 } 519 THREAD_UNLOCK(); 520 521 return NULL; 522 } 523 524 void 525 freehostent(struct hostent *ptr) 526 { 527 free(ptr); 528 } 529 530 #if 0 531 532 /* XXX: should be deprecated */ 533 struct hostent * 534 getnodebyname(const char *name, int af, int flags) 535 { 536 return getipnodebyname(name, af, flags, &h_errno); 537 } 538 539 #ifdef __warn_references 540 __warn_references(getnodebyname, 541 "warning: getnodebyname() deprecated, " 542 "should use getaddrinfo() or getipnodebyname()"); 543 #endif 544 545 struct hostent * 546 getnodebyaddr(const void *src, size_t len, int af) 547 { 548 return getipnodebyaddr(src, len, af, &h_errno); 549 } 550 551 #ifdef __warn_references 552 __warn_references(getnodebyaddr, 553 "warning: getnodebyaddr() deprecated, " 554 "should use getnameinfo() or getipnodebyaddr()"); 555 #endif 556 557 #endif 558 559 /* 560 * Private utility functions 561 */ 562 563 /* 564 * _hpcopy: allocate and copy hostent structure 565 */ 566 static struct hostent * 567 _hpcopy(struct hostent *hp, int *errp) 568 { 569 struct hostent *nhp; 570 char *cp, **pp; 571 int size, addrsize; 572 int nalias = 0, naddr = 0; 573 int al_off; 574 int i; 575 576 if (hp == NULL) 577 return hp; 578 579 /* count size to be allocated */ 580 size = sizeof(struct hostent); 581 if (hp->h_name != NULL) 582 size += strlen(hp->h_name) + 1; 583 if ((pp = hp->h_aliases) != NULL) { 584 for (i = 0; *pp != NULL; i++, pp++) { 585 if (**pp != '\0') { 586 size += strlen(*pp) + 1; 587 nalias++; 588 } 589 } 590 } 591 /* adjust alignment */ 592 size = ALIGN(size); 593 al_off = size; 594 size += sizeof(char *) * (nalias + 1); 595 addrsize = ALIGN(hp->h_length); 596 if ((pp = hp->h_addr_list) != NULL) { 597 while (*pp++ != NULL) 598 naddr++; 599 } 600 size += addrsize * naddr; 601 size += sizeof(char *) * (naddr + 1); 602 603 /* copy */ 604 if ((nhp = (struct hostent *)malloc(size)) == NULL) { 605 *errp = TRY_AGAIN; 606 return NULL; 607 } 608 cp = (char *)&nhp[1]; 609 if (hp->h_name != NULL) { 610 nhp->h_name = cp; 611 strcpy(cp, hp->h_name); 612 cp += strlen(cp) + 1; 613 } else 614 nhp->h_name = NULL; 615 nhp->h_aliases = (char **)((char *)nhp + al_off); 616 if ((pp = hp->h_aliases) != NULL) { 617 for (i = 0; *pp != NULL; pp++) { 618 if (**pp != '\0') { 619 nhp->h_aliases[i++] = cp; 620 strcpy(cp, *pp); 621 cp += strlen(cp) + 1; 622 } 623 } 624 } 625 nhp->h_aliases[nalias] = NULL; 626 cp = (char *)&nhp->h_aliases[nalias + 1]; 627 nhp->h_addrtype = hp->h_addrtype; 628 nhp->h_length = hp->h_length; 629 nhp->h_addr_list = (char **)cp; 630 if ((pp = hp->h_addr_list) != NULL) { 631 cp = (char *)&nhp->h_addr_list[naddr + 1]; 632 for (i = 0; *pp != NULL; pp++) { 633 nhp->h_addr_list[i++] = cp; 634 memcpy(cp, *pp, hp->h_length); 635 cp += addrsize; 636 } 637 } 638 nhp->h_addr_list[naddr] = NULL; 639 return nhp; 640 } 641 642 /* 643 * _hpaddr: construct hostent structure with one address 644 */ 645 static struct hostent * 646 _hpaddr(int af, const char *name, void *addr, int *errp) 647 { 648 struct hostent *hp, hpbuf; 649 char *addrs[2]; 650 651 hp = &hpbuf; 652 hp->h_name = (char *)name; 653 hp->h_aliases = NULL; 654 hp->h_addrtype = af; 655 hp->h_length = ADDRLEN(af); 656 hp->h_addr_list = addrs; 657 addrs[0] = (char *)addr; 658 addrs[1] = NULL; 659 return _hpcopy(hp, errp); 660 } 661 662 /* 663 * _hpmerge: merge 2 hostent structure, arguments will be freed 664 */ 665 static struct hostent * 666 _hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) 667 { 668 int i, j; 669 int naddr, nalias; 670 char **pp; 671 struct hostent *hp, hpbuf; 672 char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; 673 union inx_addr addrbuf[MAXADDRS]; 674 675 if (hp1 == NULL) 676 return hp2; 677 if (hp2 == NULL) 678 return hp1; 679 680 #define HP(i) (i == 1 ? hp1 : hp2) 681 hp = &hpbuf; 682 hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); 683 hp->h_aliases = aliases; 684 nalias = 0; 685 for (i = 1; i <= 2; i++) { 686 if ((pp = HP(i)->h_aliases) == NULL) 687 continue; 688 for (; nalias < MAXALIASES && *pp != NULL; pp++) { 689 /* check duplicates */ 690 for (j = 0; j < nalias; j++) 691 if (strcasecmp(*pp, aliases[j]) == 0) 692 break; 693 if (j == nalias) 694 aliases[nalias++] = *pp; 695 } 696 } 697 aliases[nalias] = NULL; 698 #ifdef INET6 699 if (hp1->h_length != hp2->h_length) { 700 hp->h_addrtype = AF_INET6; 701 hp->h_length = sizeof(struct in6_addr); 702 } else { 703 #endif 704 hp->h_addrtype = hp1->h_addrtype; 705 hp->h_length = hp1->h_length; 706 #ifdef INET6 707 } 708 #endif 709 hp->h_addr_list = addrs; 710 naddr = 0; 711 for (i = 1; i <= 2; i++) { 712 if ((pp = HP(i)->h_addr_list) == NULL) 713 continue; 714 if (HP(i)->h_length == hp->h_length) { 715 while (naddr < MAXADDRS && *pp != NULL) 716 addrs[naddr++] = *pp++; 717 } else { 718 /* copy IPv4 addr as mapped IPv6 addr */ 719 while (naddr < MAXADDRS && *pp != NULL) { 720 MAPADDR(&addrbuf[naddr], *pp++); 721 addrs[naddr] = (char *)&addrbuf[naddr]; 722 naddr++; 723 } 724 } 725 } 726 addrs[naddr] = NULL; 727 hp = _hpcopy(hp, errp); 728 freehostent(hp1); 729 freehostent(hp2); 730 return hp; 731 } 732 733 /* 734 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses 735 */ 736 #ifdef INET6 737 static struct hostent * 738 _hpmapv6(struct hostent *hp, int *errp) 739 { 740 struct hostent *hp6; 741 742 if (hp == NULL) 743 return NULL; 744 if (hp->h_addrtype == AF_INET6) 745 return hp; 746 747 /* make dummy hostent to convert IPv6 address */ 748 if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { 749 *errp = TRY_AGAIN; 750 return NULL; 751 } 752 hp6->h_name = NULL; 753 hp6->h_aliases = NULL; 754 hp6->h_addrtype = AF_INET6; 755 hp6->h_length = sizeof(struct in6_addr); 756 hp6->h_addr_list = NULL; 757 return _hpmerge(hp6, hp, errp); 758 } 759 #endif 760 761 /* 762 * _hpsort: sort address by sortlist 763 */ 764 static struct hostent * 765 _hpsort(struct hostent *hp) 766 { 767 int i, j, n; 768 u_char *ap, *sp, *mp, **pp; 769 char t; 770 char order[MAXADDRS]; 771 int nsort = _res.nsort; 772 773 if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) 774 return hp; 775 for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { 776 for (j = 0; j < nsort; j++) { 777 #ifdef INET6 778 if (_res_ext.sort_list[j].af != hp->h_addrtype) 779 continue; 780 sp = (u_char *)&_res_ext.sort_list[j].addr; 781 mp = (u_char *)&_res_ext.sort_list[j].mask; 782 #else 783 sp = (u_char *)&_res.sort_list[j].addr; 784 mp = (u_char *)&_res.sort_list[j].mask; 785 #endif 786 for (n = 0; n < hp->h_length; n++) { 787 if ((ap[n] & mp[n]) != sp[n]) 788 break; 789 } 790 if (n == hp->h_length) 791 break; 792 } 793 order[i] = j; 794 } 795 n = i; 796 pp = (u_char **)hp->h_addr_list; 797 for (i = 0; i < n - 1; i++) { 798 for (j = i + 1; j < n; j++) { 799 if (order[i] > order[j]) { 800 ap = pp[i]; 801 pp[i] = pp[j]; 802 pp[j] = ap; 803 t = order[i]; 804 order[i] = order[j]; 805 order[j] = t; 806 } 807 } 808 } 809 return hp; 810 } 811 812 static char * 813 _hgetword(char **pp) 814 { 815 char c, *p, *ret; 816 const char *sp; 817 static const char sep[] = "# \t\n"; 818 819 ret = NULL; 820 for (p = *pp; (c = *p) != '\0'; p++) { 821 for (sp = sep; *sp != '\0'; sp++) { 822 if (c == *sp) 823 break; 824 } 825 if (c == '#') 826 p[1] = '\0'; /* ignore rest of line */ 827 if (ret == NULL) { 828 if (*sp == '\0') 829 ret = p; 830 } else { 831 if (*sp != '\0') { 832 *p++ = '\0'; 833 break; 834 } 835 } 836 } 837 *pp = p; 838 if (ret == NULL || *ret == '\0') 839 return NULL; 840 return ret; 841 } 842 843 /* 844 * FILES (/etc/hosts) 845 */ 846 847 static FILE * 848 _files_open(int *errp) 849 { 850 FILE *fp; 851 fp = fopen(_PATH_HOSTS, "r"); 852 if (fp == NULL) 853 *errp = NO_RECOVERY; 854 return fp; 855 } 856 857 static struct hostent * 858 _files_ghbyname(const char *name, int af, int *errp) 859 { 860 int match, nalias; 861 char *p, *line, *addrstr, *cname; 862 FILE *fp; 863 struct hostent *rethp, *hp, hpbuf; 864 char *aliases[MAXALIASES + 1], *addrs[2]; 865 union inx_addr addrbuf; 866 char buf[BUFSIZ]; 867 int af0 = af; 868 869 if ((fp = _files_open(errp)) == NULL) 870 return NULL; 871 rethp = hp = NULL; 872 873 while (fgets(buf, sizeof(buf), fp)) { 874 line = buf; 875 if ((addrstr = _hgetword(&line)) == NULL 876 || (cname = _hgetword(&line)) == NULL) 877 continue; 878 match = (strcasecmp(cname, name) == 0); 879 nalias = 0; 880 while ((p = _hgetword(&line)) != NULL) { 881 if (!match) 882 match = (strcasecmp(p, name) == 0); 883 if (nalias < MAXALIASES) 884 aliases[nalias++] = p; 885 } 886 if (!match) 887 continue; 888 switch (af0) { 889 case AF_INET: 890 if (inet_aton(addrstr, (struct in_addr *)&addrbuf) 891 != 1) { 892 *errp = NO_DATA; /* name found */ 893 continue; 894 } 895 af = af0; 896 break; 897 #ifdef INET6 898 case AF_INET6: 899 if (inet_pton(af, addrstr, &addrbuf) != 1) { 900 *errp = NO_DATA; /* name found */ 901 continue; 902 } 903 af = af0; 904 break; 905 #endif 906 case AF_UNSPEC: 907 if (inet_aton(addrstr, (struct in_addr *)&addrbuf) 908 == 1) { 909 af = AF_INET; 910 break; 911 } 912 #ifdef INET6 913 if (inet_pton(AF_INET6, addrstr, &addrbuf) == 1) { 914 af = AF_INET6; 915 break; 916 } 917 #endif 918 *errp = NO_DATA; /* name found */ 919 continue; 920 /* NOTREACHED */ 921 } 922 hp = &hpbuf; 923 hp->h_name = cname; 924 hp->h_aliases = aliases; 925 aliases[nalias] = NULL; 926 hp->h_addrtype = af; 927 hp->h_length = ADDRLEN(af); 928 hp->h_addr_list = addrs; 929 addrs[0] = (char *)&addrbuf; 930 addrs[1] = NULL; 931 hp = _hpcopy(hp, errp); 932 rethp = _hpmerge(rethp, hp, errp); 933 } 934 fclose(fp); 935 return rethp; 936 } 937 938 static struct hostent * 939 _files_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 940 { 941 int nalias; 942 char *p, *line; 943 FILE *fp; 944 struct hostent *hp, hpbuf; 945 char *aliases[MAXALIASES + 1], *addrs[2]; 946 union inx_addr addrbuf; 947 char buf[BUFSIZ]; 948 949 if ((fp = _files_open(errp)) == NULL) 950 return NULL; 951 hp = NULL; 952 while (fgets(buf, sizeof(buf), fp)) { 953 line = buf; 954 if ((p = _hgetword(&line)) == NULL 955 || (af == AF_INET 956 ? inet_aton(p, (struct in_addr *)&addrbuf) 957 : inet_pton(af, p, &addrbuf)) != 1 958 || memcmp(addr, &addrbuf, addrlen) != 0 959 || (p = _hgetword(&line)) == NULL) 960 continue; 961 hp = &hpbuf; 962 hp->h_name = p; 963 hp->h_aliases = aliases; 964 nalias = 0; 965 while ((p = _hgetword(&line)) != NULL) { 966 if (nalias < MAXALIASES) 967 aliases[nalias++] = p; 968 } 969 aliases[nalias] = NULL; 970 hp->h_addrtype = af; 971 hp->h_length = addrlen; 972 hp->h_addr_list = addrs; 973 addrs[0] = (char *)&addrbuf; 974 addrs[1] = NULL; 975 hp = _hpcopy(hp, errp); 976 break; 977 } 978 fclose(fp); 979 return hp; 980 } 981 982 #ifdef YP 983 /* 984 * NIS 985 * 986 * XXX actually a hack, these are INET4 specific. 987 */ 988 static struct hostent * 989 _nis_ghbyname(const char *name, int af, int *errp) 990 { 991 struct hostent *hp = NULL; 992 993 if (af == AF_UNSPEC) 994 af = AF_INET; 995 if (af == AF_INET) { 996 hp = _gethostbynisname(name, af); 997 if (hp != NULL) 998 hp = _hpcopy(hp, errp); 999 } 1000 return (hp); 1001 1002 } 1003 1004 static struct hostent * 1005 _nis_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 1006 { 1007 struct hostent *hp = NULL; 1008 1009 if (af == AF_INET) { 1010 hp = _gethostbynisaddr(addr, addrlen, af); 1011 if (hp != NULL) 1012 hp = _hpcopy(hp, errp); 1013 } 1014 return (hp); 1015 } 1016 #endif 1017 1018 struct __res_type_list { 1019 SLIST_ENTRY(__res_type_list) rtl_entry; 1020 int rtl_type; 1021 }; 1022 1023 #define MAXPACKET (64*1024) 1024 1025 typedef union { 1026 HEADER hdr; 1027 u_char buf[MAXPACKET]; 1028 } querybuf; 1029 1030 static struct hostent *getanswer (const querybuf *, int, const char *, 1031 int, struct hostent *, int *); 1032 1033 /* 1034 * we don't need to take care about sorting, nor IPv4 mapped address here. 1035 */ 1036 static struct hostent * 1037 getanswer(answer, anslen, qname, qtype, template, errp) 1038 const querybuf *answer; 1039 int anslen; 1040 const char *qname; 1041 int qtype; 1042 struct hostent *template; 1043 int *errp; 1044 { 1045 const HEADER *hp; 1046 const u_char *cp; 1047 int n; 1048 const u_char *eom, *erdata; 1049 char *bp, **ap, **hap, *obp; 1050 int type, class, buflen, ancount, qdcount; 1051 int haveanswer, had_error; 1052 char tbuf[MAXDNAME]; 1053 const char *tname; 1054 int (*name_ok) (const char *); 1055 static char *h_addr_ptrs[MAXADDRS + 1]; 1056 static char *host_aliases[MAXALIASES]; 1057 static char hostbuf[8*1024]; 1058 1059 #define BOUNDED_INCR(x) \ 1060 do { \ 1061 cp += x; \ 1062 if (cp > eom) { \ 1063 *errp = NO_RECOVERY; \ 1064 return (NULL); \ 1065 } \ 1066 } while (0) 1067 1068 #define BOUNDS_CHECK(ptr, count) \ 1069 do { \ 1070 if ((ptr) + (count) > eom) { \ 1071 *errp = NO_RECOVERY; \ 1072 return (NULL); \ 1073 } \ 1074 } while (0) 1075 1076 /* XXX do {} while (0) cannot be put here */ 1077 #define DNS_ASSERT(x) \ 1078 { \ 1079 if (!(x)) { \ 1080 cp += n; \ 1081 continue; \ 1082 } \ 1083 } 1084 1085 /* XXX do {} while (0) cannot be put here */ 1086 #define DNS_FATAL(x) \ 1087 { \ 1088 if (!(x)) { \ 1089 had_error++; \ 1090 continue; \ 1091 } \ 1092 } 1093 1094 tname = qname; 1095 template->h_name = NULL; 1096 eom = answer->buf + anslen; 1097 switch (qtype) { 1098 case T_A: 1099 case T_AAAA: 1100 name_ok = res_hnok; 1101 break; 1102 case T_PTR: 1103 name_ok = res_dnok; 1104 break; 1105 default: 1106 return (NULL); /* XXX should be abort(); */ 1107 } 1108 /* 1109 * find first satisfactory answer 1110 */ 1111 hp = &answer->hdr; 1112 ancount = ntohs(hp->ancount); 1113 qdcount = ntohs(hp->qdcount); 1114 bp = hostbuf; 1115 buflen = sizeof hostbuf; 1116 cp = answer->buf; 1117 BOUNDED_INCR(HFIXEDSZ); 1118 if (qdcount != 1) { 1119 *errp = NO_RECOVERY; 1120 return (NULL); 1121 } 1122 n = dn_expand(answer->buf, eom, cp, bp, buflen); 1123 if ((n < 0) || !(*name_ok)(bp)) { 1124 *errp = NO_RECOVERY; 1125 return (NULL); 1126 } 1127 BOUNDED_INCR(n + QFIXEDSZ); 1128 if (qtype == T_A || qtype == T_AAAA) { 1129 /* res_send() has already verified that the query name is the 1130 * same as the one we sent; this just gets the expanded name 1131 * (i.e., with the succeeding search-domain tacked on). 1132 */ 1133 n = strlen(bp) + 1; /* for the \0 */ 1134 if (n >= MAXHOSTNAMELEN) { 1135 *errp = NO_RECOVERY; 1136 return (NULL); 1137 } 1138 template->h_name = bp; 1139 bp += n; 1140 buflen -= n; 1141 /* The qname can be abbreviated, but h_name is now absolute. */ 1142 qname = template->h_name; 1143 } 1144 ap = host_aliases; 1145 *ap = NULL; 1146 template->h_aliases = host_aliases; 1147 hap = h_addr_ptrs; 1148 *hap = NULL; 1149 template->h_addr_list = h_addr_ptrs; 1150 haveanswer = 0; 1151 had_error = 0; 1152 while (ancount-- > 0 && cp < eom && !had_error) { 1153 n = dn_expand(answer->buf, eom, cp, bp, buflen); 1154 DNS_FATAL(n >= 0); 1155 DNS_FATAL((*name_ok)(bp)); 1156 cp += n; /* name */ 1157 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); 1158 type = _getshort(cp); 1159 cp += INT16SZ; /* type */ 1160 class = _getshort(cp); 1161 cp += INT16SZ + INT32SZ; /* class, TTL */ 1162 n = _getshort(cp); 1163 cp += INT16SZ; /* len */ 1164 BOUNDS_CHECK(cp, n); 1165 erdata = cp + n; 1166 DNS_ASSERT(class == C_IN); 1167 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { 1168 if (ap >= &host_aliases[MAXALIASES-1]) 1169 continue; 1170 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 1171 DNS_FATAL(n >= 0); 1172 DNS_FATAL((*name_ok)(tbuf)); 1173 cp += n; 1174 if (cp != erdata) { 1175 *errp = NO_RECOVERY; 1176 return (NULL); 1177 } 1178 /* Store alias. */ 1179 *ap++ = bp; 1180 n = strlen(bp) + 1; /* for the \0 */ 1181 DNS_FATAL(n < MAXHOSTNAMELEN); 1182 bp += n; 1183 buflen -= n; 1184 /* Get canonical name. */ 1185 n = strlen(tbuf) + 1; /* for the \0 */ 1186 DNS_FATAL(n <= buflen); 1187 DNS_FATAL(n < MAXHOSTNAMELEN); 1188 strcpy(bp, tbuf); 1189 template->h_name = bp; 1190 bp += n; 1191 buflen -= n; 1192 continue; 1193 } 1194 if (qtype == T_PTR && type == T_CNAME) { 1195 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); 1196 if (n < 0 || !res_dnok(tbuf)) { 1197 had_error++; 1198 continue; 1199 } 1200 cp += n; 1201 if (cp != erdata) { 1202 *errp = NO_RECOVERY; 1203 return (NULL); 1204 } 1205 /* Get canonical name. */ 1206 n = strlen(tbuf) + 1; /* for the \0 */ 1207 if (n > buflen || n >= MAXHOSTNAMELEN) { 1208 had_error++; 1209 continue; 1210 } 1211 strcpy(bp, tbuf); 1212 tname = bp; 1213 bp += n; 1214 buflen -= n; 1215 continue; 1216 } 1217 DNS_ASSERT(type == qtype); 1218 switch (type) { 1219 case T_PTR: 1220 DNS_ASSERT(strcasecmp(tname, bp) == 0); 1221 n = dn_expand(answer->buf, eom, cp, bp, buflen); 1222 DNS_FATAL(n >= 0); 1223 DNS_FATAL(res_hnok(bp)); 1224 #if MULTI_PTRS_ARE_ALIASES 1225 cp += n; 1226 if (cp != erdata) { 1227 *errp = NO_RECOVERY; 1228 return (NULL); 1229 } 1230 if (!haveanswer) 1231 template->h_name = bp; 1232 else if (ap < &host_aliases[MAXALIASES-1]) 1233 *ap++ = bp; 1234 else 1235 n = -1; 1236 if (n != -1) { 1237 n = strlen(bp) + 1; /* for the \0 */ 1238 if (n >= MAXHOSTNAMELEN) { 1239 had_error++; 1240 break; 1241 } 1242 bp += n; 1243 buflen -= n; 1244 } 1245 break; 1246 #else 1247 template->h_name = bp; 1248 *errp = NETDB_SUCCESS; 1249 return (template); 1250 #endif 1251 case T_A: 1252 case T_AAAA: 1253 DNS_ASSERT(strcasecmp(template->h_name, bp) == 0); 1254 DNS_ASSERT(n == template->h_length); 1255 if (!haveanswer) { 1256 int nn; 1257 1258 template->h_name = bp; 1259 nn = strlen(bp) + 1; /* for the \0 */ 1260 bp += nn; 1261 buflen -= nn; 1262 } 1263 obp = bp; /* ALIGN rounds up */ 1264 bp = (char *)ALIGN(bp); 1265 buflen -= (bp - obp); 1266 1267 DNS_FATAL(bp + n < &hostbuf[sizeof hostbuf]); 1268 DNS_ASSERT(hap < &h_addr_ptrs[MAXADDRS-1]); 1269 #ifdef FILTER_V4MAPPED 1270 if (type == T_AAAA) { 1271 struct in6_addr in6; 1272 memcpy(&in6, cp, sizeof(in6)); 1273 DNS_ASSERT(IN6_IS_ADDR_V4MAPPED(&in6) == 0); 1274 } 1275 #endif 1276 bcopy(cp, *hap++ = bp, n); 1277 bp += n; 1278 buflen -= n; 1279 cp += n; 1280 if (cp != erdata) { 1281 *errp = NO_RECOVERY; 1282 return (NULL); 1283 } 1284 break; 1285 default: 1286 abort(); 1287 } 1288 if (!had_error) 1289 haveanswer++; 1290 } 1291 if (haveanswer) { 1292 *ap = NULL; 1293 *hap = NULL; 1294 if (!template->h_name) { 1295 n = strlen(qname) + 1; /* for the \0 */ 1296 if (n > buflen || n >= MAXHOSTNAMELEN) 1297 goto no_recovery; 1298 strcpy(bp, qname); 1299 template->h_name = bp; 1300 bp += n; 1301 buflen -= n; 1302 } 1303 *errp = NETDB_SUCCESS; 1304 return (template); 1305 } 1306 no_recovery: 1307 *errp = NO_RECOVERY; 1308 return (NULL); 1309 1310 #undef BOUNDED_INCR 1311 #undef BOUNDS_CHECK 1312 #undef DNS_ASSERT 1313 #undef DNS_FATAL 1314 } 1315 1316 /* res_search() variant with multiple query support. */ 1317 static struct hostent * 1318 _res_search_multi(name, rtl, errp) 1319 const char *name; /* domain name */ 1320 struct __res_type_list *rtl; /* list of query types */ 1321 int *errp; 1322 { 1323 const char *cp, * const *domain; 1324 struct hostent *hp0 = NULL, *hp; 1325 struct hostent hpbuf; 1326 u_int dots; 1327 int trailing_dot, ret, saved_herrno; 1328 int got_nodata = 0, got_servfail = 0, tried_as_is = 0; 1329 struct __res_type_list *rtl0 = rtl; 1330 querybuf *buf; 1331 1332 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 1333 *errp = NETDB_INTERNAL; 1334 return (NULL); 1335 } 1336 dots = 0; 1337 for (cp = name; *cp; cp++) 1338 dots += (*cp == '.'); 1339 trailing_dot = 0; 1340 if (cp > name && *--cp == '.') 1341 trailing_dot++; 1342 1343 buf = malloc(sizeof(*buf)); 1344 if (buf == NULL) { 1345 *errp = NETDB_INTERNAL; 1346 return NULL; 1347 } 1348 1349 /* If there aren't any dots, it could be a user-level alias */ 1350 if (!dots && (cp = hostalias(name)) != NULL) { 1351 for(rtl = rtl0; rtl != NULL; 1352 rtl = SLIST_NEXT(rtl, rtl_entry)) { 1353 ret = res_query(cp, C_IN, rtl->rtl_type, buf->buf, 1354 sizeof(buf->buf)); 1355 if (ret > 0 && ret < sizeof(buf->buf)) { 1356 hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) 1357 ? AF_INET6 : AF_INET; 1358 hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); 1359 hp = getanswer(buf, ret, name, rtl->rtl_type, 1360 &hpbuf, errp); 1361 if (!hp) 1362 continue; 1363 hp = _hpcopy(&hpbuf, errp); 1364 hp0 = _hpmerge(hp0, hp, errp); 1365 } 1366 } 1367 free(buf); 1368 return (hp0); 1369 } 1370 1371 /* 1372 * If there are dots in the name already, let's just give it a try 1373 * 'as is'. The threshold can be set with the "ndots" option. 1374 */ 1375 saved_herrno = -1; 1376 if (dots >= _res.ndots) { 1377 for(rtl = rtl0; rtl != NULL; 1378 rtl = SLIST_NEXT(rtl, rtl_entry)) { 1379 ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, 1380 buf->buf, sizeof(buf->buf)); 1381 if (ret > 0 && ret < sizeof(buf->buf)) { 1382 hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) 1383 ? AF_INET6 : AF_INET; 1384 hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); 1385 hp = getanswer(buf, ret, name, rtl->rtl_type, 1386 &hpbuf, errp); 1387 if (!hp) 1388 continue; 1389 hp = _hpcopy(&hpbuf, errp); 1390 hp0 = _hpmerge(hp0, hp, errp); 1391 } 1392 } 1393 if (hp0 != NULL) { 1394 free(buf); 1395 return (hp0); 1396 } 1397 saved_herrno = *errp; 1398 tried_as_is++; 1399 } 1400 1401 /* 1402 * We do at least one level of search if 1403 * - there is no dot and RES_DEFNAME is set, or 1404 * - there is at least one dot, there is no trailing dot, 1405 * and RES_DNSRCH is set. 1406 */ 1407 if ((!dots && (_res.options & RES_DEFNAMES)) || 1408 (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { 1409 int done = 0; 1410 1411 for (domain = (const char * const *)_res.dnsrch; 1412 *domain && !done; 1413 domain++) { 1414 1415 for(rtl = rtl0; rtl != NULL; 1416 rtl = SLIST_NEXT(rtl, rtl_entry)) { 1417 ret = res_querydomain(name, *domain, C_IN, 1418 rtl->rtl_type, 1419 buf->buf, sizeof(buf->buf)); 1420 if (ret > 0 && ret < sizeof(buf->buf)) { 1421 hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) 1422 ? AF_INET6 : AF_INET; 1423 hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); 1424 hp = getanswer(buf, ret, name, 1425 rtl->rtl_type, &hpbuf, errp); 1426 if (!hp) 1427 continue; 1428 hp = _hpcopy(&hpbuf, errp); 1429 hp0 = _hpmerge(hp0, hp, errp); 1430 } 1431 } 1432 if (hp0 != NULL) { 1433 free(buf); 1434 return (hp0); 1435 } 1436 1437 /* 1438 * If no server present, give up. 1439 * If name isn't found in this domain, 1440 * keep trying higher domains in the search list 1441 * (if that's enabled). 1442 * On a NO_DATA error, keep trying, otherwise 1443 * a wildcard entry of another type could keep us 1444 * from finding this entry higher in the domain. 1445 * If we get some other error (negative answer or 1446 * server failure), then stop searching up, 1447 * but try the input name below in case it's 1448 * fully-qualified. 1449 */ 1450 if (errno == ECONNREFUSED) { 1451 free(buf); 1452 *errp = TRY_AGAIN; 1453 return (NULL); 1454 } 1455 1456 switch (*errp) { 1457 case NO_DATA: 1458 got_nodata++; 1459 /* FALLTHROUGH */ 1460 case HOST_NOT_FOUND: 1461 /* keep trying */ 1462 break; 1463 case TRY_AGAIN: 1464 if (buf->hdr.rcode == SERVFAIL) { 1465 /* try next search element, if any */ 1466 got_servfail++; 1467 break; 1468 } 1469 /* FALLTHROUGH */ 1470 default: 1471 /* anything else implies that we're done */ 1472 done++; 1473 } 1474 1475 /* if we got here for some reason other than DNSRCH, 1476 * we only wanted one iteration of the loop, so stop. 1477 */ 1478 if (!(_res.options & RES_DNSRCH)) 1479 done++; 1480 } 1481 } 1482 1483 /* 1484 * If we have not already tried the name "as is", do that now. 1485 * note that we do this regardless of how many dots were in the 1486 * name or whether it ends with a dot unless NOTLDQUERY is set. 1487 */ 1488 if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) { 1489 for(rtl = rtl0; rtl != NULL; 1490 rtl = SLIST_NEXT(rtl, rtl_entry)) { 1491 ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type, 1492 buf->buf, sizeof(buf->buf)); 1493 if (ret > 0 && ret < sizeof(buf->buf)) { 1494 hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA) 1495 ? AF_INET6 : AF_INET; 1496 hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype); 1497 hp = getanswer(buf, ret, name, rtl->rtl_type, 1498 &hpbuf, errp); 1499 if (!hp) 1500 continue; 1501 hp = _hpcopy(&hpbuf, errp); 1502 hp0 = _hpmerge(hp0, hp, errp); 1503 } 1504 } 1505 if (hp0 != NULL) { 1506 free(buf); 1507 return (hp0); 1508 } 1509 } 1510 1511 free(buf); 1512 1513 /* if we got here, we didn't satisfy the search. 1514 * if we did an initial full query, return that query's h_errno 1515 * (note that we wouldn't be here if that query had succeeded). 1516 * else if we ever got a nodata, send that back as the reason. 1517 * else send back meaningless h_errno, that being the one from 1518 * the last DNSRCH we did. 1519 */ 1520 if (saved_herrno != -1) 1521 *errp = saved_herrno; 1522 else if (got_nodata) 1523 *errp = NO_DATA; 1524 else if (got_servfail) 1525 *errp = TRY_AGAIN; 1526 return (NULL); 1527 } 1528 1529 static struct hostent * 1530 _dns_ghbyname(const char *name, int af, int *errp) 1531 { 1532 struct __res_type_list *rtl, rtl4; 1533 #ifdef INET6 1534 struct __res_type_list rtl6; 1535 #endif 1536 1537 #ifdef INET6 1538 switch (af) { 1539 case AF_UNSPEC: 1540 SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; 1541 SLIST_NEXT(&rtl6, rtl_entry) = &rtl4; rtl6.rtl_type = T_AAAA; 1542 rtl = &rtl6; 1543 break; 1544 case AF_INET6: 1545 SLIST_NEXT(&rtl6, rtl_entry) = NULL; rtl6.rtl_type = T_AAAA; 1546 rtl = &rtl6; 1547 break; 1548 case AF_INET: 1549 SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; 1550 rtl = &rtl4; 1551 break; 1552 } 1553 #else 1554 SLIST_NEXT(&rtl4, rtl_entry) = NULL; rtl4.rtl_type = T_A; 1555 rtl = &rtl4; 1556 #endif 1557 return(_res_search_multi(name, rtl, errp)); 1558 } 1559 1560 static struct hostent * 1561 _dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 1562 { 1563 int n; 1564 struct hostent *hp; 1565 u_char c, *cp; 1566 char *bp; 1567 struct hostent hbuf; 1568 int na; 1569 #ifdef INET6 1570 static const char hex[] = "0123456789abcdef"; 1571 #endif 1572 querybuf *buf; 1573 char qbuf[MAXDNAME+1]; 1574 char *hlist[2]; 1575 char *tld6[] = { "ip6.arpa", "ip6.int", NULL }; 1576 char *tld4[] = { "in-addr.arpa", NULL }; 1577 char **tld; 1578 1579 #ifdef INET6 1580 /* XXX */ 1581 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) 1582 return NULL; 1583 #endif 1584 1585 switch (af) { 1586 #ifdef INET6 1587 case AF_INET6: 1588 tld = tld6; 1589 break; 1590 #endif 1591 case AF_INET: 1592 tld = tld4; 1593 break; 1594 default: 1595 return NULL; 1596 } 1597 1598 if ((_res.options & RES_INIT) == 0) { 1599 if (res_init() < 0) { 1600 *errp = h_errno; 1601 return NULL; 1602 } 1603 } 1604 memset(&hbuf, 0, sizeof(hbuf)); 1605 hbuf.h_name = NULL; 1606 hbuf.h_addrtype = af; 1607 hbuf.h_length = addrlen; 1608 na = 0; 1609 1610 buf = malloc(sizeof(*buf)); 1611 if (buf == NULL) { 1612 *errp = NETDB_INTERNAL; 1613 return NULL; 1614 } 1615 for (/* nothing */; *tld; tld++) { 1616 /* 1617 * XXX assumes that MAXDNAME is big enough - error checks 1618 * has been made by callers 1619 */ 1620 n = 0; 1621 bp = qbuf; 1622 cp = (u_char *)addr+addrlen-1; 1623 switch (af) { 1624 #ifdef INET6 1625 case AF_INET6: 1626 for (; n < addrlen; n++, cp--) { 1627 c = *cp; 1628 *bp++ = hex[c & 0xf]; 1629 *bp++ = '.'; 1630 *bp++ = hex[c >> 4]; 1631 *bp++ = '.'; 1632 } 1633 strcpy(bp, *tld); 1634 break; 1635 #endif 1636 case AF_INET: 1637 for (; n < addrlen; n++, cp--) { 1638 c = *cp; 1639 if (c >= 100) 1640 *bp++ = '0' + c / 100; 1641 if (c >= 10) 1642 *bp++ = '0' + (c % 100) / 10; 1643 *bp++ = '0' + c % 10; 1644 *bp++ = '.'; 1645 } 1646 strcpy(bp, *tld); 1647 break; 1648 } 1649 1650 n = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf); 1651 if (n < 0) { 1652 *errp = h_errno; 1653 continue; 1654 } else if (n > sizeof(buf->buf)) { 1655 *errp = NETDB_INTERNAL; 1656 #if 0 1657 errno = ERANGE; /* XXX is it OK to set errno here? */ 1658 #endif 1659 continue; 1660 } 1661 hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp); 1662 if (!hp) 1663 continue; 1664 free(buf); 1665 hbuf.h_addrtype = af; 1666 hbuf.h_length = addrlen; 1667 hbuf.h_addr_list = hlist; 1668 hlist[0] = (char *)addr; 1669 hlist[1] = NULL; 1670 return _hpcopy(&hbuf, errp); 1671 } 1672 free(buf); 1673 return NULL; 1674 } 1675 1676 static void 1677 _dns_shent(int stayopen) 1678 { 1679 if ((_res.options & RES_INIT) == 0) { 1680 if (res_init() < 0) 1681 return; 1682 } 1683 if (stayopen) 1684 _res.options |= RES_STAYOPEN | RES_USEVC; 1685 } 1686 1687 static void 1688 _dns_ehent(void) 1689 { 1690 _res.options &= ~(RES_STAYOPEN | RES_USEVC); 1691 res_close(); 1692 } 1693 1694 #ifdef ICMPNL 1695 1696 /* 1697 * experimental: 1698 * draft-ietf-ipngwg-icmp-namelookups-02.txt 1699 * ifindex is assumed to be encoded in addr. 1700 */ 1701 #include <sys/uio.h> 1702 #include <netinet/ip6.h> 1703 #include <netinet/icmp6.h> 1704 1705 struct _icmp_host_cache { 1706 struct _icmp_host_cache *hc_next; 1707 int hc_ifindex; 1708 struct in6_addr hc_addr; 1709 char *hc_name; 1710 }; 1711 1712 static char * 1713 _icmp_fqdn_query(const struct in6_addr *addr, int ifindex) 1714 { 1715 int s; 1716 struct icmp6_filter filter; 1717 struct msghdr msg; 1718 struct cmsghdr *cmsg; 1719 struct in6_pktinfo *pkt; 1720 char cbuf[256]; 1721 char buf[1024]; 1722 int cc; 1723 struct icmp6_fqdn_query *fq; 1724 struct icmp6_fqdn_reply *fr; 1725 struct _icmp_host_cache *hc; 1726 struct sockaddr_in6 sin6; 1727 struct iovec iov; 1728 fd_set s_fds, fds; 1729 struct timeval tout; 1730 int len; 1731 char *name; 1732 static int pid; 1733 static struct _icmp_host_cache *hc_head; 1734 1735 for (hc = hc_head; hc; hc = hc->hc_next) { 1736 if (hc->hc_ifindex == ifindex 1737 && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) 1738 return hc->hc_name; 1739 } 1740 1741 if (pid == 0) 1742 pid = getpid(); 1743 1744 ICMP6_FILTER_SETBLOCKALL(&filter); 1745 ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); 1746 1747 FD_ZERO(&s_fds); 1748 tout.tv_sec = 0; 1749 tout.tv_usec = 200000; /*XXX: 200ms*/ 1750 1751 fq = (struct icmp6_fqdn_query *)buf; 1752 fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; 1753 fq->icmp6_fqdn_code = 0; 1754 fq->icmp6_fqdn_cksum = 0; 1755 fq->icmp6_fqdn_id = (u_short)pid; 1756 fq->icmp6_fqdn_unused = 0; 1757 fq->icmp6_fqdn_cookie[0] = 0; 1758 fq->icmp6_fqdn_cookie[1] = 0; 1759 1760 memset(&sin6, 0, sizeof(sin6)); 1761 sin6.sin6_family = AF_INET6; 1762 sin6.sin6_addr = *addr; 1763 1764 memset(&msg, 0, sizeof(msg)); 1765 msg.msg_name = (caddr_t)&sin6; 1766 msg.msg_namelen = sizeof(sin6); 1767 msg.msg_iov = &iov; 1768 msg.msg_iovlen = 1; 1769 msg.msg_control = NULL; 1770 msg.msg_controllen = 0; 1771 iov.iov_base = (caddr_t)buf; 1772 iov.iov_len = sizeof(struct icmp6_fqdn_query); 1773 1774 if (ifindex) { 1775 msg.msg_control = cbuf; 1776 msg.msg_controllen = sizeof(cbuf); 1777 cmsg = CMSG_FIRSTHDR(&msg); 1778 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1779 cmsg->cmsg_level = IPPROTO_IPV6; 1780 cmsg->cmsg_type = IPV6_PKTINFO; 1781 pkt = (struct in6_pktinfo *)&cmsg[1]; 1782 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); 1783 pkt->ipi6_ifindex = ifindex; 1784 cmsg = CMSG_NXTHDR(&msg, cmsg); 1785 msg.msg_controllen = (char *)cmsg - cbuf; 1786 } 1787 1788 if ((s = _socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) 1789 return NULL; 1790 (void)_setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, 1791 (char *)&filter, sizeof(filter)); 1792 cc = _sendmsg(s, &msg, 0); 1793 if (cc < 0) { 1794 _close(s); 1795 return NULL; 1796 } 1797 FD_SET(s, &s_fds); 1798 for (;;) { 1799 fds = s_fds; 1800 if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) { 1801 _close(s); 1802 return NULL; 1803 } 1804 len = sizeof(sin6); 1805 cc = _recvfrom(s, buf, sizeof(buf), 0, 1806 (struct sockaddr *)&sin6, &len); 1807 if (cc <= 0) { 1808 _close(s); 1809 return NULL; 1810 } 1811 if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) 1812 continue; 1813 if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr)) 1814 continue; 1815 fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr)); 1816 if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY) 1817 break; 1818 } 1819 _close(s); 1820 if (fr->icmp6_fqdn_cookie[1] != 0) { 1821 /* rfc1788 type */ 1822 name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4; 1823 len = (buf + cc) - name; 1824 } else { 1825 len = fr->icmp6_fqdn_namelen; 1826 name = fr->icmp6_fqdn_name; 1827 } 1828 if (len <= 0) 1829 return NULL; 1830 name[len] = 0; 1831 1832 if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL) 1833 return NULL; 1834 /* XXX: limit number of cached entries */ 1835 hc->hc_ifindex = ifindex; 1836 hc->hc_addr = *addr; 1837 hc->hc_name = strdup(name); 1838 hc->hc_next = hc_head; 1839 hc_head = hc; 1840 return hc->hc_name; 1841 } 1842 1843 static struct hostent * 1844 _icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 1845 { 1846 char *hname; 1847 int ifindex; 1848 struct in6_addr addr6; 1849 1850 if (af != AF_INET6) { 1851 /* 1852 * Note: rfc1788 defines Who Are You for IPv4, 1853 * but no one implements it. 1854 */ 1855 return NULL; 1856 } 1857 1858 memcpy(&addr6, addr, addrlen); 1859 ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3]; 1860 addr6.s6_addr[2] = addr6.s6_addr[3] = 0; 1861 1862 if (!IN6_IS_ADDR_LINKLOCAL(&addr6)) 1863 return NULL; /*XXX*/ 1864 1865 if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL) 1866 return NULL; 1867 return _hpaddr(af, hname, &addr6, errp); 1868 } 1869 #endif /* ICMPNL */ 1870