name6.c revision 55163
1/* 2 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/lib/libc/net/name6.c 55163 1999-12-28 02:37:14Z shin $ 30 */ 31/* $Id: name6.c,v 1.9 1999/10/29 03:04:26 itojun Exp $ */ 32/* 33 * Atsushi Onoe <onoe@sm.sony.co.jp> 34 */ 35 36/* 37 * TODO for thread safe 38 * use mutex for _hostconf, _hostconf_init. 39 * rewrite resolvers to be thread safe 40 */ 41 42#include <sys/param.h> 43#include <sys/socket.h> 44#include <sys/time.h> 45#include <netinet/in.h> 46 47#include <arpa/inet.h> 48#include <arpa/nameser.h> 49 50#include <netdb.h> 51#include <resolv.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <string.h> 55#include <unistd.h> 56 57#ifndef _PATH_HOSTS 58#define _PATH_HOSTS "/etc/hosts" 59#endif 60 61#ifndef MAXALIASES 62#define MAXALIASES 10 63#endif 64#ifndef MAXADDRS 65#define MAXADDRS 20 66#endif 67#ifndef MAXDNAME 68#define MAXDNAME 1025 69#endif 70 71#ifdef INET6 72#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \ 73 sizeof(struct in_addr)) 74#else 75#define ADDRLEN(af) sizeof(struct in_addr) 76#endif 77 78#define MAPADDR(ab, ina) \ 79do { \ 80 memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \ 81 memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \ 82 memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \ 83} while (0) 84#define MAPADDRENABLED(flags) \ 85 (((flags) & AI_V4MAPPED) || \ 86 (((flags) & AI_V4MAPPED_CFG) && _mapped_addr_enabled())) 87 88union inx_addr { 89 struct in_addr in_addr; 90#ifdef INET6 91 struct in6_addr in6_addr; 92#endif 93 struct { 94 u_char mau_zero[10]; 95 u_char mau_one[2]; 96 struct in_addr mau_inaddr; 97 } map_addr_un; 98#define map_zero map_addr_un.mau_zero 99#define map_one map_addr_un.mau_one 100#define map_inaddr map_addr_un.mau_inaddr 101}; 102 103static struct hostent *_hpcopy(struct hostent *hp, int *errp); 104static struct hostent *_hpaddr(int af, const char *name, void *addr, int *errp); 105static struct hostent *_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp); 106#ifdef INET6 107static struct hostent *_hpmapv6(struct hostent *hp, int *errp); 108#endif 109static struct hostent *_hpsort(struct hostent *hp); 110static struct hostent *_ghbyname(const char *name, int af, int flags, int *errp); 111static char *_hgetword(char **pp); 112static int _mapped_addr_enabled(void); 113 114static FILE *_files_open(int *errp); 115static struct hostent *_files_ghbyname(const char *name, int af, int *errp); 116static struct hostent *_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 117static void _files_shent(int stayopen); 118static void _files_ehent(void); 119static struct hostent *_dns_ghbyname(const char *name, int af, int *errp); 120static struct hostent *_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 121static void _dns_shent(int stayopen); 122static void _dns_ehent(void); 123#ifdef ICMPNL 124static struct hostent *_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp); 125#endif /* ICMPNL */ 126 127/* 128 * Select order host function. 129 */ 130#define MAXHOSTCONF 4 131 132#ifndef HOSTCONF 133# define HOSTCONF "/etc/host.conf" 134#endif /* !HOSTCONF */ 135 136struct _hostconf { 137 struct hostent *(*byname)(const char *name, int af, int *errp); 138 struct hostent *(*byaddr)(const void *addr, int addrlen, int af, int *errp); 139}; 140 141/* default order */ 142static struct _hostconf _hostconf[MAXHOSTCONF] = { 143 { _dns_ghbyname, _dns_ghbyaddr }, 144 { _files_ghbyname, _files_ghbyaddr }, 145#ifdef ICMPNL 146 { NULL, _icmp_ghbyaddr }, 147#endif /* ICMPNL */ 148}; 149 150static int _hostconf_init_done; 151static void _hostconf_init(void); 152 153/* 154 * Initialize hostconf structure. 155 */ 156 157static void 158_hostconf_init(void) 159{ 160 FILE *fp; 161 int n; 162 char *p, *line; 163 char buf[BUFSIZ]; 164 165 _hostconf_init_done = 1; 166 n = 0; 167 p = HOSTCONF; 168 if ((fp = fopen(p, "r")) == NULL) 169 return; 170 while (n < MAXHOSTCONF && fgets(buf, sizeof(buf), fp)) { 171 line = buf; 172 if ((p = _hgetword(&line)) == NULL) 173 continue; 174 do { 175 if (strcmp(p, "hosts") == 0 176 || strcmp(p, "local") == 0 177 || strcmp(p, "file") == 0 178 || strcmp(p, "files") == 0) { 179 _hostconf[n].byname = _files_ghbyname; 180 _hostconf[n].byaddr = _files_ghbyaddr; 181 n++; 182 } 183 else if (strcmp(p, "dns") == 0 184 || strcmp(p, "bind") == 0) { 185 _hostconf[n].byname = _dns_ghbyname; 186 _hostconf[n].byaddr = _dns_ghbyaddr; 187 n++; 188 } 189#ifdef ICMPNL 190 else if (strcmp(p, "icmp") == 0) { 191 _hostconf[n].byname = NULL; 192 _hostconf[n].byaddr = _icmp_ghbyaddr; 193 n++; 194 } 195#endif /* ICMPNL */ 196 } while ((p = _hgetword(&line)) != NULL); 197 } 198 fclose(fp); 199 if (n < 0) { 200 /* no keyword found. do not change default configuration */ 201 return; 202 } 203 for (; n < MAXHOSTCONF; n++) { 204 _hostconf[n].byname = NULL; 205 _hostconf[n].byaddr = NULL; 206 } 207} 208 209/* 210 * Check if kernel supports mapped address. 211 * implementation dependent 212 */ 213#ifdef __KAME__ 214#include <sys/sysctl.h> 215#endif /* __KAME__ */ 216 217static int 218_mapped_addr_enabled(void) 219{ 220 /* implementation dependent check */ 221#if defined(__KAME__) && defined(IPV6CTL_MAPPED_ADDR) 222 int mib[4]; 223 size_t len; 224 int val; 225 226 mib[0] = CTL_NET; 227 mib[1] = PF_INET6; 228 mib[2] = IPPROTO_IPV6; 229 mib[3] = IPV6CTL_MAPPED_ADDR; 230 len = sizeof(val); 231 if (sysctl(mib, 4, &val, &len, 0, 0) == 0 && val != 0) 232 return 1; 233#endif /* __KAME__ && IPV6CTL_MAPPED_ADDR */ 234 return 0; 235} 236 237/* 238 * Functions defined in RFC2553 239 * getipnodebyname, getipnodebyadr, freehostent 240 */ 241 242static struct hostent * 243_ghbyname(const char *name, int af, int flags, int *errp) 244{ 245 struct hostent *hp; 246 int i; 247 248 if (flags & AI_ADDRCONFIG) { 249 int s; 250 251 if ((s = socket(af, SOCK_DGRAM, 0)) < 0) 252 return NULL; 253 /* 254 * TODO: 255 * Note that implementation dependent test for address 256 * configuration should be done everytime called 257 * (or apropriate interval), 258 * because addresses will be dynamically assigned or deleted. 259 */ 260 close(s); 261 } 262 263 for (i = 0; i < MAXHOSTCONF; i++) { 264 if (_hostconf[i].byname 265 && (hp = (*_hostconf[i].byname)(name, af, errp)) 266 != NULL) 267 return hp; 268 } 269 270 return NULL; 271} 272 273struct hostent * 274getipnodebyname(const char *name, int af, int flags, int *errp) 275{ 276 struct hostent *hp; 277 union inx_addr addrbuf; 278 279 if (af != AF_INET 280#ifdef INET6 281 && af != AF_INET6 282#endif 283 ) 284 { 285 *errp = NO_RECOVERY; 286 return NULL; 287 } 288 289#ifdef INET6 290 /* special case for literal address */ 291 if (inet_pton(AF_INET6, name, &addrbuf) == 1) { 292 if (af != AF_INET6) { 293 *errp = HOST_NOT_FOUND; 294 return NULL; 295 } 296 return _hpaddr(af, name, &addrbuf, errp); 297 } 298#endif 299 if (inet_pton(AF_INET, name, &addrbuf) == 1) { 300 if (af != AF_INET) { 301 if (MAPADDRENABLED(flags)) { 302 MAPADDR(&addrbuf, &addrbuf.in_addr); 303 } else { 304 *errp = HOST_NOT_FOUND; 305 return NULL; 306 } 307 } 308 return _hpaddr(af, name, &addrbuf, errp); 309 } 310 311 if (!_hostconf_init_done) 312 _hostconf_init(); 313 314 *errp = HOST_NOT_FOUND; 315 hp = _ghbyname(name, af, flags, errp); 316 317#ifdef INET6 318 if (af == AF_INET6 319 && ((flags & AI_ALL) || hp == NULL) 320 && (MAPADDRENABLED(flags))) { 321 struct hostent *hp2 = _ghbyname(name, AF_INET, flags, errp); 322 if (hp == NULL) 323 hp = _hpmapv6(hp2, errp); 324 else { 325 if (hp2 && strcmp(hp->h_name, hp2->h_name) != 0) { 326 freehostent(hp2); 327 hp2 = NULL; 328 } 329 hp = _hpmerge(hp, hp2, errp); 330 } 331 } 332#endif 333 return _hpsort(hp); 334} 335 336struct hostent * 337getipnodebyaddr(const void *src, size_t len, int af, int *errp) 338{ 339 struct hostent *hp; 340 int i; 341#ifdef INET6 342 struct in6_addr addrbuf; 343#else 344 struct in_addr addrbuf; 345#endif 346 347 *errp = HOST_NOT_FOUND; 348 349 switch (af) { 350 case AF_INET: 351 if (len != sizeof(struct in_addr)) { 352 *errp = NO_RECOVERY; 353 return NULL; 354 } 355 if ((long)src & ~(sizeof(struct in_addr) - 1)) { 356 memcpy(&addrbuf, src, len); 357 src = &addrbuf; 358 } 359 if (((struct in_addr *)src)->s_addr == 0) 360 return NULL; 361 break; 362#ifdef INET6 363 case AF_INET6: 364 if (len != sizeof(struct in6_addr)) { 365 *errp = NO_RECOVERY; 366 return NULL; 367 } 368 if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/ 369 memcpy(&addrbuf, src, len); 370 src = &addrbuf; 371 } 372 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) 373 || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { 374 src = (char *)src + 375 (sizeof(struct in6_addr) - sizeof(struct in_addr)); 376 af = AF_INET; 377 len = sizeof(struct in_addr); 378 } 379 break; 380#endif 381 default: 382 *errp = NO_RECOVERY; 383 return NULL; 384 } 385 386 if (!_hostconf_init_done) 387 _hostconf_init(); 388 for (i = 0; i < MAXHOSTCONF; i++) { 389 if (_hostconf[i].byaddr 390 && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL) 391 return hp; 392 } 393 394 return NULL; 395} 396 397void 398freehostent(struct hostent *ptr) 399{ 400 free(ptr); 401} 402 403#if 0 404 405/* XXX: should be deprecated */ 406struct hostent * 407getnodebyname(const char *name, int af, int flags) 408{ 409 return getipnodebyname(name, af, flags, &h_errno); 410} 411 412#ifdef __warn_references 413__warn_references(getnodebyname, 414 "warning: getnodebyname() deprecated, " 415 "should use getaddrinfo() or getipnodebyname()"); 416#endif 417 418struct hostent * 419getnodebyaddr(const void *src, size_t len, int af) 420{ 421 return getipnodebyaddr(src, len, af, &h_errno); 422} 423 424#ifdef __warn_references 425__warn_references(getnodebyaddr, 426 "warning: getnodebyaddr() deprecated, " 427 "should use getnameinfo() or getipnodebyaddr()"); 428#endif 429 430#endif 431 432/* 433 * Private utility functions 434 */ 435 436/* 437 * _hpcopy: allocate and copy hostent structure 438 */ 439static struct hostent * 440_hpcopy(struct hostent *hp, int *errp) 441{ 442 struct hostent *nhp; 443 char *cp, **pp; 444 int size, addrsize; 445 int nalias = 0, naddr = 0; 446 int al_off; 447 int i; 448 449 if (hp == NULL) 450 return hp; 451 452 /* count size to be allocated */ 453 size = sizeof(struct hostent); 454 if (hp->h_name != NULL && *hp->h_name != '\0') 455 size += strlen(hp->h_name) + 1; 456 if ((pp = hp->h_aliases) != NULL) { 457 for (i = 0; *pp != NULL; i++, pp++) { 458 if (**pp != '\0') { 459 size += strlen(*pp) + 1; 460 nalias++; 461 } 462 } 463 } 464 /* adjust alignment */ 465 size = ALIGN(size); 466 al_off = size; 467 size += sizeof(char *) * (nalias + 1); 468 addrsize = ALIGN(hp->h_length); 469 if ((pp = hp->h_addr_list) != NULL) { 470 while (*pp++ != NULL) 471 naddr++; 472 } 473 size += addrsize * naddr; 474 size += sizeof(char *) * (naddr + 1); 475 476 /* copy */ 477 if ((nhp = (struct hostent *)malloc(size)) == NULL) { 478 *errp = TRY_AGAIN; 479 return NULL; 480 } 481 cp = (char *)&nhp[1]; 482 if (hp->h_name != NULL && *hp->h_name != '\0') { 483 nhp->h_name = cp; 484 strcpy(cp, hp->h_name); 485 cp += strlen(cp) + 1; 486 } else 487 nhp->h_name = NULL; 488 nhp->h_aliases = (char **)((char *)nhp + al_off); 489 if ((pp = hp->h_aliases) != NULL) { 490 for (i = 0; *pp != NULL; pp++) { 491 if (**pp != '\0') { 492 nhp->h_aliases[i++] = cp; 493 strcpy(cp, *pp); 494 cp += strlen(cp) + 1; 495 } 496 } 497 } 498 nhp->h_aliases[nalias] = NULL; 499 cp = (char *)&nhp->h_aliases[nalias + 1]; 500 nhp->h_addrtype = hp->h_addrtype; 501 nhp->h_length = hp->h_length; 502 nhp->h_addr_list = (char **)cp; 503 if ((pp = hp->h_addr_list) != NULL) { 504 cp = (char *)&nhp->h_addr_list[naddr + 1]; 505 for (i = 0; *pp != NULL; pp++) { 506 nhp->h_addr_list[i++] = cp; 507 memcpy(cp, *pp, hp->h_length); 508 cp += addrsize; 509 } 510 } 511 nhp->h_addr_list[naddr] = NULL; 512 return nhp; 513} 514 515/* 516 * _hpaddr: construct hostent structure with one address 517 */ 518static struct hostent * 519_hpaddr(int af, const char *name, void *addr, int *errp) 520{ 521 struct hostent *hp, hpbuf; 522 char *addrs[2]; 523 524 hp = &hpbuf; 525 hp->h_name = (char *)name; 526 hp->h_aliases = NULL; 527 hp->h_addrtype = af; 528 hp->h_length = ADDRLEN(af); 529 hp->h_addr_list = addrs; 530 addrs[0] = (char *)addr; 531 addrs[1] = NULL; 532 return _hpcopy(hp, errp); 533} 534 535/* 536 * _hpmerge: merge 2 hostent structure, arguments will be freed 537 */ 538static struct hostent * 539_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) 540{ 541 int i, j; 542 int naddr, nalias; 543 char **pp; 544 struct hostent *hp, hpbuf; 545 char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; 546 union inx_addr addrbuf[MAXADDRS]; 547 548 if (hp1 == NULL) 549 return hp2; 550 if (hp2 == NULL) 551 return hp1; 552 553#define HP(i) (i == 1 ? hp1 : hp2) 554 hp = &hpbuf; 555 hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); 556 hp->h_aliases = aliases; 557 nalias = 0; 558 for (i = 1; i <= 2; i++) { 559 if ((pp = HP(i)->h_aliases) == NULL) 560 continue; 561 for (; nalias < MAXALIASES && *pp != NULL; pp++) { 562 /* check duplicates */ 563 for (j = 0; j < nalias; j++) 564 if (strcasecmp(*pp, aliases[j]) == 0) 565 break; 566 if (j == nalias) 567 aliases[nalias++] = *pp; 568 } 569 } 570 aliases[nalias] = NULL; 571#ifdef INET6 572 if (hp1->h_length != hp2->h_length) { 573 hp->h_addrtype = AF_INET6; 574 hp->h_length = sizeof(struct in6_addr); 575 } else { 576#endif 577 hp->h_addrtype = hp1->h_addrtype; 578 hp->h_length = hp1->h_length; 579#ifdef INET6 580 } 581#endif 582 hp->h_addr_list = addrs; 583 naddr = 0; 584 for (i = 1; i <= 2; i++) { 585 if ((pp = HP(i)->h_addr_list) == NULL) 586 continue; 587 if (HP(i)->h_length == hp->h_length) { 588 while (naddr < MAXADDRS && *pp != NULL) 589 addrs[naddr++] = *pp++; 590 } else { 591 /* copy IPv4 addr as mapped IPv6 addr */ 592 while (naddr < MAXADDRS && *pp != NULL) { 593 MAPADDR(&addrbuf[naddr], *pp++); 594 addrs[naddr] = (char *)&addrbuf[naddr]; 595 naddr++; 596 } 597 } 598 } 599 addrs[naddr] = NULL; 600 hp = _hpcopy(hp, errp); 601 freehostent(hp1); 602 freehostent(hp2); 603 return hp; 604} 605 606/* 607 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses 608 */ 609#ifdef INET6 610static struct hostent * 611_hpmapv6(struct hostent *hp, int *errp) 612{ 613 struct hostent *hp6; 614 615 if (hp == NULL) 616 return NULL; 617 if (hp->h_addrtype == AF_INET6) 618 return hp; 619 620 /* make dummy hostent to convert IPv6 address */ 621 if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { 622 *errp = TRY_AGAIN; 623 return NULL; 624 } 625 hp6->h_name = NULL; 626 hp6->h_aliases = NULL; 627 hp6->h_addrtype = AF_INET6; 628 hp6->h_length = sizeof(struct in6_addr); 629 hp6->h_addr_list = NULL; 630 return _hpmerge(hp6, hp, errp); 631} 632#endif 633 634/* 635 * _hpsort: sort address by sortlist 636 */ 637static struct hostent * 638_hpsort(struct hostent *hp) 639{ 640 int i, j, n; 641 u_char *ap, *sp, *mp, **pp; 642 char t; 643 char order[MAXADDRS]; 644 int nsort = _res.nsort; 645 646 if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) 647 return hp; 648 for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { 649 for (j = 0; j < nsort; j++) { 650#ifdef INET6 651 if (_res_ext.sort_list[j].af != hp->h_addrtype) 652 continue; 653 sp = (u_char *)&_res_ext.sort_list[j].addr; 654 mp = (u_char *)&_res_ext.sort_list[j].mask; 655#else 656 sp = (u_char *)&_res.sort_list[j].addr; 657 mp = (u_char *)&_res.sort_list[j].mask; 658#endif 659 for (n = 0; n < hp->h_length; n++) { 660 if ((ap[n] & mp[n]) != sp[n]) 661 break; 662 } 663 if (n == hp->h_length) 664 break; 665 } 666 order[i] = j; 667 } 668 n = i; 669 pp = (u_char **)hp->h_addr_list; 670 for (i = 0; i < n - 1; i++) { 671 for (j = i + 1; j < n; j++) { 672 if (order[i] > order[j]) { 673 ap = pp[i]; 674 pp[i] = pp[j]; 675 pp[j] = ap; 676 t = order[i]; 677 order[i] = order[j]; 678 order[j] = t; 679 } 680 } 681 } 682 return hp; 683} 684 685static char * 686_hgetword(char **pp) 687{ 688 char c, *p, *ret; 689 const char *sp; 690 static const char sep[] = "# \t\n"; 691 692 ret = NULL; 693 for (p = *pp; (c = *p) != '\0'; p++) { 694 for (sp = sep; *sp != '\0'; sp++) { 695 if (c == *sp) 696 break; 697 } 698 if (c == '#') 699 p[1] = '\0'; /* ignore rest of line */ 700 if (ret == NULL) { 701 if (*sp == '\0') 702 ret = p; 703 } else { 704 if (*sp != '\0') { 705 *p++ = '\0'; 706 break; 707 } 708 } 709 } 710 *pp = p; 711 if (ret == NULL || *ret == '\0') 712 return NULL; 713 return ret; 714} 715 716/* 717 * FILES (/etc/hosts) 718 */ 719 720static FILE * 721_files_open(int *errp) 722{ 723 FILE *fp; 724 fp = fopen(_PATH_HOSTS, "r"); 725 if (fp == NULL) 726 *errp = NO_RECOVERY; 727 return fp; 728} 729 730static struct hostent * 731_files_ghbyname(const char *name, int af, int *errp) 732{ 733 int match, nalias; 734 char *p, *line, *addrstr, *cname; 735 FILE *fp; 736 struct hostent *rethp, *hp, hpbuf; 737 char *aliases[MAXALIASES + 1], *addrs[2]; 738 union inx_addr addrbuf; 739 char buf[BUFSIZ]; 740 741 if ((fp = _files_open(errp)) == NULL) 742 return NULL; 743 rethp = hp = NULL; 744 745 while (fgets(buf, sizeof(buf), fp)) { 746 line = buf; 747 if ((addrstr = _hgetword(&line)) == NULL 748 || (cname = _hgetword(&line)) == NULL) 749 continue; 750 match = (strcasecmp(cname, name) == 0); 751 nalias = 0; 752 while ((p = _hgetword(&line)) != NULL) { 753 if (!match) 754 match = (strcasecmp(p, name) == 0); 755 if (nalias < MAXALIASES) 756 aliases[nalias++] = p; 757 } 758 if (!match) 759 continue; 760 if (inet_pton(af, addrstr, &addrbuf) != 1) { 761 *errp = NO_DATA; /* name found */ 762 continue; 763 } 764 hp = &hpbuf; 765 hp->h_name = cname; 766 hp->h_aliases = aliases; 767 aliases[nalias] = NULL; 768 hp->h_addrtype = af; 769 hp->h_length = ADDRLEN(af); 770 hp->h_addr_list = addrs; 771 addrs[0] = (char *)&addrbuf; 772 addrs[1] = NULL; 773 hp = _hpcopy(hp, errp); 774 rethp = _hpmerge(rethp, hp, errp); 775 } 776 fclose(fp); 777 return rethp; 778} 779 780static struct hostent * 781_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 782{ 783 int nalias; 784 char *p, *line; 785 FILE *fp; 786 struct hostent *hp, hpbuf; 787 char *aliases[MAXALIASES + 1], *addrs[2]; 788 union inx_addr addrbuf; 789 char buf[BUFSIZ]; 790 791 if ((fp = _files_open(errp)) == NULL) 792 return NULL; 793 hp = NULL; 794 while (fgets(buf, sizeof(buf), fp)) { 795 line = buf; 796 if ((p = _hgetword(&line)) == NULL 797 || inet_pton(af, p, &addrbuf) != 1 798 || memcmp(addr, &addrbuf, addrlen) != 0 799 || (p = _hgetword(&line)) == NULL) 800 continue; 801 hp = &hpbuf; 802 hp->h_name = p; 803 hp->h_aliases = aliases; 804 nalias = 0; 805 while ((p = _hgetword(&line)) != NULL) { 806 if (nalias < MAXALIASES) 807 aliases[nalias++] = p; 808 } 809 aliases[nalias] = NULL; 810 hp->h_addrtype = af; 811 hp->h_length = addrlen; 812 hp->h_addr_list = addrs; 813 addrs[0] = (char *)&addrbuf; 814 addrs[1] = NULL; 815 hp = _hpcopy(hp, errp); 816 break; 817 } 818 fclose(fp); 819 return hp; 820} 821 822#ifdef DEBUG 823#define DNS_ASSERT(X) if (!(X)) { fprintf(stderr, "ASSFAIL: %s %d: %s\n", __FILE__, __LINE__, #X); goto badanswer; } 824#else 825#define DNS_ASSERT(X) if (!(X)) { goto badanswer; } 826#endif 827 828static struct hostent * 829_dns_ghbyname(const char *name, int af, int *errp) 830{ 831 int n; 832 u_char answer[BUFSIZ]; 833 char tbuf[MAXDNAME+1]; 834 HEADER *hp; 835 u_char *cp, *eom; 836 int qtype; 837 int type, class, ancount, qdcount; 838 u_long ttl; 839 char hostbuf[BUFSIZ]; 840 char *bp; 841 char *alist[MAXALIASES]; 842 char *hlist[MAXADDRS]; 843 struct hostent hbuf; 844 int buflen; 845 int na, nh; 846 847 if ((_res.options & RES_INIT) == 0) { 848 if (res_init() < 0) { 849 *errp = h_errno; 850 return NULL; 851 } 852 } 853 hbuf.h_aliases = alist; 854 hbuf.h_addrtype = af; 855 hbuf.h_length = ADDRLEN(af); 856 hbuf.h_addr_list = hlist; 857 na = nh = 0; 858 859#ifdef INET6 860 qtype = (af == AF_INET6 ? T_AAAA : T_A); 861#else 862 qtype = T_A; 863#endif 864 n = res_search(name, C_IN, qtype, answer, sizeof(answer)); 865 if (n < 0) { 866 *errp = h_errno; 867 return NULL; 868 } 869 hp = (HEADER *)answer; 870 eom = answer + n; 871 ancount = ntohs(hp->ancount); 872 qdcount = ntohs(hp->qdcount); 873 DNS_ASSERT(qdcount == 1); 874 cp = answer + sizeof(HEADER); 875 bp = hostbuf; 876 buflen = sizeof(hostbuf); 877 878 n = dn_expand(answer, eom, cp, bp, buflen); 879 DNS_ASSERT(n >= 0); 880 cp += n + QFIXEDSZ; 881 hbuf.h_name = bp; 882 n = strlen(bp) + 1; 883 bp += n; 884 buflen -= n; 885 while (ancount-- > 0 && cp < eom) { 886 n = dn_expand(answer, eom, cp, bp, buflen); 887 DNS_ASSERT(n >= 0); 888 cp += n; /* name */ 889 type = _getshort(cp); 890 cp += 2; /* type */ 891 class = _getshort(cp); 892 cp += 2; /* class */ 893 ttl = _getlong(cp); 894 cp += 4; /* ttl */ 895 n = _getshort(cp); 896 cp += 2; /* len */ 897 DNS_ASSERT(class == C_IN); 898 switch (type) { 899 case T_CNAME: 900 if (na >= MAXALIASES-1) { 901 cp += n; 902 break; 903 } 904 n = dn_expand(answer, eom, cp, tbuf, sizeof(tbuf)); 905 DNS_ASSERT(n >= 0); 906 cp += n; 907 /* alias */ 908 alist[na++] = bp; 909 n = strlen(bp) + 1; 910 bp += n; 911 buflen -= n; 912 /* canon */ 913 n = strlen(tbuf) + 1; 914 DNS_ASSERT(n < buflen); 915 strcpy(bp, tbuf); 916 hbuf.h_name = bp; 917 bp += n; 918 buflen -= n; 919 break; 920 case T_A: 921#ifdef INET6 922 case T_AAAA: 923#endif 924 DNS_ASSERT(type == qtype); 925 bp = (char *)ALIGN(bp); 926 DNS_ASSERT(n == hbuf.h_length); 927 DNS_ASSERT(n < buflen); 928 if (nh < MAXADDRS-1) { 929 hlist[nh++] = bp; 930 memcpy(bp, cp, n); 931 bp += n; 932 buflen -= n; 933 } 934 cp += n; 935 break; 936 default: 937 DNS_ASSERT(0); 938 cp += n; 939 break; 940 } 941 } 942 if (nh == 0) { 943 badanswer: 944 *errp = NO_RECOVERY; 945 return NULL; 946 } 947 alist[na] = NULL; 948 hlist[nh] = NULL; 949 return _hpcopy(&hbuf, errp); 950} 951 952static struct hostent * 953_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 954{ 955 int n; 956 u_char answer[BUFSIZ]; 957 HEADER *hp; 958 u_char c, *cp, *eom; 959 int type, class, ancount, qdcount; 960 u_long ttl; 961 char hostbuf[BUFSIZ]; 962 char *bp; 963 char *alist[MAXALIASES]; 964 char *hlist[2]; 965 struct hostent hbuf; 966 int buflen; 967 int na; 968#ifdef INET6 969 static const char hex[] = "0123456789abcdef"; 970#endif 971 972#ifdef INET6 973 /* XXX */ 974 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) 975 return NULL; 976#endif 977 978 if ((_res.options & RES_INIT) == 0) { 979 if (res_init() < 0) { 980 *errp = h_errno; 981 return NULL; 982 } 983 } 984 hbuf.h_name = NULL; 985 hbuf.h_aliases = alist; 986 hbuf.h_addrtype = af; 987 hbuf.h_length = addrlen; 988 hbuf.h_addr_list = hlist; 989 hlist[0] = (char *)addr; 990 hlist[1] = NULL; 991 na = 0; 992 993 n = 0; 994 bp = hostbuf; 995 cp = (u_char *)addr+addrlen-1; 996 switch (af) { 997#ifdef INET6 998 case AF_INET6: 999 for (; n < addrlen; n++, cp--) { 1000 c = *cp; 1001 *bp++ = hex[c & 0xf]; 1002 *bp++ = '.'; 1003 *bp++ = hex[c >> 4]; 1004 *bp++ = '.'; 1005 } 1006 strcpy(bp, "ip6.int"); 1007 break; 1008#endif 1009 default: 1010 for (; n < addrlen; n++, cp--) { 1011 c = *cp; 1012 if (c >= 100) 1013 *bp++ = '0' + c / 100; 1014 if (c >= 10) 1015 *bp++ = '0' + (c % 100) / 10; 1016 *bp++ = '0' + c % 10; 1017 *bp++ = '.'; 1018 } 1019 strcpy(bp, "in-addr.arpa"); 1020 break; 1021 } 1022 1023 n = res_query(hostbuf, C_IN, T_PTR, answer, sizeof(answer)); 1024 if (n < 0) { 1025 *errp = h_errno; 1026 return NULL; 1027 } 1028 hp = (HEADER *)answer; 1029 eom = answer + n; 1030 ancount = ntohs(hp->ancount); 1031 qdcount = ntohs(hp->qdcount); 1032 DNS_ASSERT(qdcount == 1); 1033 cp = answer + sizeof(HEADER); 1034 bp = hostbuf; 1035 buflen = sizeof(hostbuf); 1036 1037 n = dn_expand(answer, eom, cp, bp, buflen); 1038 DNS_ASSERT(n >= 0); 1039 cp += n + QFIXEDSZ; 1040 while (ancount-- > 0 && cp < eom) { 1041 n = dn_expand(answer, eom, cp, bp, buflen); 1042 DNS_ASSERT(n >= 0); 1043 cp += n; /* name */ 1044 type = _getshort(cp); 1045 cp += 2; /* type */ 1046 class = _getshort(cp); 1047 cp += 2; /* class */ 1048 ttl = _getlong(cp); 1049 cp += 4; /* ttl */ 1050 n = _getshort(cp); 1051 cp += 2; /* len */ 1052 DNS_ASSERT(class == C_IN); 1053 switch (type) { 1054 case T_PTR: 1055 n = dn_expand(answer, eom, cp, bp, buflen); 1056 DNS_ASSERT(n >= 0); 1057 cp += n; 1058 if (na >= MAXALIASES-1) 1059 break; 1060 if (hbuf.h_name == NULL) 1061 hbuf.h_name = bp; 1062 else 1063 alist[na++] = bp; 1064 n = strlen(bp) + 1; 1065 bp += n; 1066 buflen -= n; 1067 break; 1068 case T_CNAME: 1069 cp += n; 1070 break; 1071 default: 1072 badanswer: 1073 *errp = NO_RECOVERY; 1074 return NULL; 1075 } 1076 } 1077 if (hbuf.h_name == NULL) { 1078 *errp = h_errno; 1079 return NULL; 1080 } 1081 alist[na] = NULL; 1082 return _hpcopy(&hbuf, errp); 1083} 1084 1085#ifdef ICMPNL 1086 1087/* 1088 * experimental: 1089 * draft-ietf-ipngwg-icmp-namelookups-02.txt 1090 * ifindex is assumed to be encoded in addr. 1091 */ 1092#include <sys/uio.h> 1093#include <netinet/ip6.h> 1094#include <netinet/icmp6.h> 1095 1096struct _icmp_host_cache { 1097 struct _icmp_host_cache *hc_next; 1098 int hc_ifindex; 1099 struct in6_addr hc_addr; 1100 char *hc_name; 1101}; 1102 1103static char * 1104_icmp_fqdn_query(const struct in6_addr *addr, int ifindex) 1105{ 1106 int s; 1107 struct icmp6_filter filter; 1108 struct msghdr msg; 1109 struct cmsghdr *cmsg; 1110 struct in6_pktinfo *pkt; 1111 char cbuf[256]; 1112 char buf[1024]; 1113 int cc; 1114 struct icmp6_fqdn_query *fq; 1115 struct icmp6_fqdn_reply *fr; 1116 struct _icmp_host_cache *hc; 1117 struct sockaddr_in6 sin6; 1118 struct iovec iov; 1119 fd_set s_fds, fds; 1120 struct timeval tout; 1121 int len; 1122 char *name; 1123 static int pid; 1124 static struct _icmp_host_cache *hc_head; 1125 1126 for (hc = hc_head; hc; hc = hc->hc_next) { 1127 if (hc->hc_ifindex == ifindex 1128 && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) 1129 return hc->hc_name; 1130 } 1131 1132 if (pid == 0) 1133 pid = getpid(); 1134 1135 ICMP6_FILTER_SETBLOCKALL(&filter); 1136 ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); 1137 1138 FD_ZERO(&s_fds); 1139 tout.tv_sec = 0; 1140 tout.tv_usec = 200000; /*XXX: 200ms*/ 1141 1142 fq = (struct icmp6_fqdn_query *)buf; 1143 fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; 1144 fq->icmp6_fqdn_code = 0; 1145 fq->icmp6_fqdn_cksum = 0; 1146 fq->icmp6_fqdn_id = (u_short)pid; 1147 fq->icmp6_fqdn_unused = 0; 1148 fq->icmp6_fqdn_cookie[0] = 0; 1149 fq->icmp6_fqdn_cookie[1] = 0; 1150 1151 memset(&sin6, 0, sizeof(sin6)); 1152 sin6.sin6_family = AF_INET6; 1153 sin6.sin6_addr = *addr; 1154 1155 memset(&msg, 0, sizeof(msg)); 1156 msg.msg_name = (caddr_t)&sin6; 1157 msg.msg_namelen = sizeof(sin6); 1158 msg.msg_iov = &iov; 1159 msg.msg_iovlen = 1; 1160 msg.msg_control = NULL; 1161 msg.msg_controllen = 0; 1162 iov.iov_base = (caddr_t)buf; 1163 iov.iov_len = sizeof(struct icmp6_fqdn_query); 1164 1165 if (ifindex) { 1166 msg.msg_control = cbuf; 1167 msg.msg_controllen = sizeof(cbuf); 1168 cmsg = CMSG_FIRSTHDR(&msg); 1169 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1170 cmsg->cmsg_level = IPPROTO_IPV6; 1171 cmsg->cmsg_type = IPV6_PKTINFO; 1172 pkt = (struct in6_pktinfo *)&cmsg[1]; 1173 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); 1174 pkt->ipi6_ifindex = ifindex; 1175 cmsg = CMSG_NXTHDR(&msg, cmsg); 1176 msg.msg_controllen = (char *)cmsg - cbuf; 1177 } 1178 1179 if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) 1180 return NULL; 1181 (void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, 1182 (char *)&filter, sizeof(filter)); 1183 cc = sendmsg(s, &msg, 0); 1184 if (cc < 0) { 1185 close(s); 1186 return NULL; 1187 } 1188 FD_SET(s, &s_fds); 1189 for (;;) { 1190 fds = s_fds; 1191 if (select(s + 1, &fds, NULL, NULL, &tout) <= 0) { 1192 close(s); 1193 return NULL; 1194 } 1195 len = sizeof(sin6); 1196 cc = recvfrom(s, buf, sizeof(buf), 0, 1197 (struct sockaddr *)&sin6, &len); 1198 if (cc <= 0) { 1199 close(s); 1200 return NULL; 1201 } 1202 if (cc < sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr)) 1203 continue; 1204 if (!IN6_ARE_ADDR_EQUAL(addr, &sin6.sin6_addr)) 1205 continue; 1206 fr = (struct icmp6_fqdn_reply *)(buf + sizeof(struct ip6_hdr)); 1207 if (fr->icmp6_fqdn_type == ICMP6_FQDN_REPLY) 1208 break; 1209 } 1210 close(s); 1211 if (fr->icmp6_fqdn_cookie[1] != 0) { 1212 /* rfc1788 type */ 1213 name = buf + sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4; 1214 len = (buf + cc) - name; 1215 } else { 1216 len = fr->icmp6_fqdn_namelen; 1217 name = fr->icmp6_fqdn_name; 1218 } 1219 if (len <= 0) 1220 return NULL; 1221 name[len] = 0; 1222 1223 if ((hc = (struct _icmp_host_cache *)malloc(sizeof(*hc))) == NULL) 1224 return NULL; 1225 /* XXX: limit number of cached entries */ 1226 hc->hc_ifindex = ifindex; 1227 hc->hc_addr = *addr; 1228 hc->hc_name = strdup(name); 1229 hc->hc_next = hc_head; 1230 hc_head = hc; 1231 return hc->hc_name; 1232} 1233 1234static struct hostent * 1235_icmp_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 1236{ 1237 char *hname; 1238 int ifindex; 1239 struct in6_addr addr6; 1240 1241 if (af != AF_INET6) { 1242 /* 1243 * Note: rfc1788 defines Who Are You for IPv4, 1244 * but no one implements it. 1245 */ 1246 return NULL; 1247 } 1248 1249 memcpy(&addr6, addr, addrlen); 1250 ifindex = (addr6.s6_addr[2] << 8) | addr6.s6_addr[3]; 1251 addr6.s6_addr[2] = addr6.s6_addr[3] = 0; 1252 1253 if (!IN6_IS_ADDR_LINKLOCAL(&addr6)) 1254 return NULL; /*XXX*/ 1255 1256 if ((hname = _icmp_fqdn_query(&addr6, ifindex)) == NULL) 1257 return NULL; 1258 return _hpaddr(af, hname, &addr6, errp); 1259} 1260#endif /* ICMPNL */ 1261