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