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 */
| 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 */
|
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_UNSPECIFIED((struct in6_addr *)src)) 373 return NULL; 374 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) 375 || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { 376 src = (char *)src + 377 (sizeof(struct in6_addr) - sizeof(struct in_addr)); 378 af = AF_INET; 379 len = sizeof(struct in_addr); 380 } 381 break; 382#endif 383 default: 384 *errp = NO_RECOVERY; 385 return NULL; 386 } 387 388 if (!_hostconf_init_done) 389 _hostconf_init(); 390 for (i = 0; i < MAXHOSTCONF; i++) { 391 if (_hostconf[i].byaddr 392 && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL) 393 return hp; 394 } 395 396 return NULL; 397} 398 399void 400freehostent(struct hostent *ptr) 401{ 402 free(ptr); 403} 404 405#if 0 406 407/* XXX: should be deprecated */ 408struct hostent * 409getnodebyname(const char *name, int af, int flags) 410{ 411 return getipnodebyname(name, af, flags, &h_errno); 412} 413 414#ifdef __warn_references 415__warn_references(getnodebyname, 416 "warning: getnodebyname() deprecated, " 417 "should use getaddrinfo() or getipnodebyname()"); 418#endif 419 420struct hostent * 421getnodebyaddr(const void *src, size_t len, int af) 422{ 423 return getipnodebyaddr(src, len, af, &h_errno); 424} 425 426#ifdef __warn_references 427__warn_references(getnodebyaddr, 428 "warning: getnodebyaddr() deprecated, " 429 "should use getnameinfo() or getipnodebyaddr()"); 430#endif 431 432#endif 433 434/* 435 * Private utility functions 436 */ 437 438/* 439 * _hpcopy: allocate and copy hostent structure 440 */ 441static struct hostent * 442_hpcopy(struct hostent *hp, int *errp) 443{ 444 struct hostent *nhp; 445 char *cp, **pp; 446 int size, addrsize; 447 int nalias = 0, naddr = 0; 448 int al_off; 449 int i; 450 451 if (hp == NULL) 452 return hp; 453 454 /* count size to be allocated */ 455 size = sizeof(struct hostent); 456 if (hp->h_name != NULL && *hp->h_name != '\0') 457 size += strlen(hp->h_name) + 1; 458 if ((pp = hp->h_aliases) != NULL) { 459 for (i = 0; *pp != NULL; i++, pp++) { 460 if (**pp != '\0') { 461 size += strlen(*pp) + 1; 462 nalias++; 463 } 464 } 465 } 466 /* adjust alignment */ 467 size = ALIGN(size); 468 al_off = size; 469 size += sizeof(char *) * (nalias + 1); 470 addrsize = ALIGN(hp->h_length); 471 if ((pp = hp->h_addr_list) != NULL) { 472 while (*pp++ != NULL) 473 naddr++; 474 } 475 size += addrsize * naddr; 476 size += sizeof(char *) * (naddr + 1); 477 478 /* copy */ 479 if ((nhp = (struct hostent *)malloc(size)) == NULL) { 480 *errp = TRY_AGAIN; 481 return NULL; 482 } 483 cp = (char *)&nhp[1]; 484 if (hp->h_name != NULL && *hp->h_name != '\0') { 485 nhp->h_name = cp; 486 strcpy(cp, hp->h_name); 487 cp += strlen(cp) + 1; 488 } else 489 nhp->h_name = NULL; 490 nhp->h_aliases = (char **)((char *)nhp + al_off); 491 if ((pp = hp->h_aliases) != NULL) { 492 for (i = 0; *pp != NULL; pp++) { 493 if (**pp != '\0') { 494 nhp->h_aliases[i++] = cp; 495 strcpy(cp, *pp); 496 cp += strlen(cp) + 1; 497 } 498 } 499 } 500 nhp->h_aliases[nalias] = NULL; 501 cp = (char *)&nhp->h_aliases[nalias + 1]; 502 nhp->h_addrtype = hp->h_addrtype; 503 nhp->h_length = hp->h_length; 504 nhp->h_addr_list = (char **)cp; 505 if ((pp = hp->h_addr_list) != NULL) { 506 cp = (char *)&nhp->h_addr_list[naddr + 1]; 507 for (i = 0; *pp != NULL; pp++) { 508 nhp->h_addr_list[i++] = cp; 509 memcpy(cp, *pp, hp->h_length); 510 cp += addrsize; 511 } 512 } 513 nhp->h_addr_list[naddr] = NULL; 514 return nhp; 515} 516 517/* 518 * _hpaddr: construct hostent structure with one address 519 */ 520static struct hostent * 521_hpaddr(int af, const char *name, void *addr, int *errp) 522{ 523 struct hostent *hp, hpbuf; 524 char *addrs[2]; 525 526 hp = &hpbuf; 527 hp->h_name = (char *)name; 528 hp->h_aliases = NULL; 529 hp->h_addrtype = af; 530 hp->h_length = ADDRLEN(af); 531 hp->h_addr_list = addrs; 532 addrs[0] = (char *)addr; 533 addrs[1] = NULL; 534 return _hpcopy(hp, errp); 535} 536 537/* 538 * _hpmerge: merge 2 hostent structure, arguments will be freed 539 */ 540static struct hostent * 541_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) 542{ 543 int i, j; 544 int naddr, nalias; 545 char **pp; 546 struct hostent *hp, hpbuf; 547 char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; 548 union inx_addr addrbuf[MAXADDRS]; 549 550 if (hp1 == NULL) 551 return hp2; 552 if (hp2 == NULL) 553 return hp1; 554 555#define HP(i) (i == 1 ? hp1 : hp2) 556 hp = &hpbuf; 557 hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); 558 hp->h_aliases = aliases; 559 nalias = 0; 560 for (i = 1; i <= 2; i++) { 561 if ((pp = HP(i)->h_aliases) == NULL) 562 continue; 563 for (; nalias < MAXALIASES && *pp != NULL; pp++) { 564 /* check duplicates */ 565 for (j = 0; j < nalias; j++) 566 if (strcasecmp(*pp, aliases[j]) == 0) 567 break; 568 if (j == nalias) 569 aliases[nalias++] = *pp; 570 } 571 } 572 aliases[nalias] = NULL; 573#ifdef INET6 574 if (hp1->h_length != hp2->h_length) { 575 hp->h_addrtype = AF_INET6; 576 hp->h_length = sizeof(struct in6_addr); 577 } else { 578#endif 579 hp->h_addrtype = hp1->h_addrtype; 580 hp->h_length = hp1->h_length; 581#ifdef INET6 582 } 583#endif 584 hp->h_addr_list = addrs; 585 naddr = 0; 586 for (i = 1; i <= 2; i++) { 587 if ((pp = HP(i)->h_addr_list) == NULL) 588 continue; 589 if (HP(i)->h_length == hp->h_length) { 590 while (naddr < MAXADDRS && *pp != NULL) 591 addrs[naddr++] = *pp++; 592 } else { 593 /* copy IPv4 addr as mapped IPv6 addr */ 594 while (naddr < MAXADDRS && *pp != NULL) { 595 MAPADDR(&addrbuf[naddr], *pp++); 596 addrs[naddr] = (char *)&addrbuf[naddr]; 597 naddr++; 598 } 599 } 600 } 601 addrs[naddr] = NULL; 602 hp = _hpcopy(hp, errp); 603 freehostent(hp1); 604 freehostent(hp2); 605 return hp; 606} 607 608/* 609 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses 610 */ 611#ifdef INET6 612static struct hostent * 613_hpmapv6(struct hostent *hp, int *errp) 614{ 615 struct hostent *hp6; 616 617 if (hp == NULL) 618 return NULL; 619 if (hp->h_addrtype == AF_INET6) 620 return hp; 621 622 /* make dummy hostent to convert IPv6 address */ 623 if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { 624 *errp = TRY_AGAIN; 625 return NULL; 626 } 627 hp6->h_name = NULL; 628 hp6->h_aliases = NULL; 629 hp6->h_addrtype = AF_INET6; 630 hp6->h_length = sizeof(struct in6_addr); 631 hp6->h_addr_list = NULL; 632 return _hpmerge(hp6, hp, errp); 633} 634#endif 635 636/* 637 * _hpsort: sort address by sortlist 638 */ 639static struct hostent * 640_hpsort(struct hostent *hp) 641{ 642 int i, j, n; 643 u_char *ap, *sp, *mp, **pp; 644 char t; 645 char order[MAXADDRS]; 646 int nsort = _res.nsort; 647 648 if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) 649 return hp; 650 for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { 651 for (j = 0; j < nsort; j++) { 652#ifdef INET6 653 if (_res_ext.sort_list[j].af != hp->h_addrtype) 654 continue; 655 sp = (u_char *)&_res_ext.sort_list[j].addr; 656 mp = (u_char *)&_res_ext.sort_list[j].mask; 657#else 658 sp = (u_char *)&_res.sort_list[j].addr; 659 mp = (u_char *)&_res.sort_list[j].mask; 660#endif 661 for (n = 0; n < hp->h_length; n++) { 662 if ((ap[n] & mp[n]) != sp[n]) 663 break; 664 } 665 if (n == hp->h_length) 666 break; 667 } 668 order[i] = j; 669 } 670 n = i; 671 pp = (u_char **)hp->h_addr_list; 672 for (i = 0; i < n - 1; i++) { 673 for (j = i + 1; j < n; j++) { 674 if (order[i] > order[j]) { 675 ap = pp[i]; 676 pp[i] = pp[j]; 677 pp[j] = ap; 678 t = order[i]; 679 order[i] = order[j]; 680 order[j] = t; 681 } 682 } 683 } 684 return hp; 685} 686 687static char * 688_hgetword(char **pp) 689{ 690 char c, *p, *ret; 691 const char *sp; 692 static const char sep[] = "# \t\n"; 693 694 ret = NULL; 695 for (p = *pp; (c = *p) != '\0'; p++) { 696 for (sp = sep; *sp != '\0'; sp++) { 697 if (c == *sp) 698 break; 699 } 700 if (c == '#') 701 p[1] = '\0'; /* ignore rest of line */ 702 if (ret == NULL) { 703 if (*sp == '\0') 704 ret = p; 705 } else { 706 if (*sp != '\0') { 707 *p++ = '\0'; 708 break; 709 } 710 } 711 } 712 *pp = p; 713 if (ret == NULL || *ret == '\0') 714 return NULL; 715 return ret; 716} 717 718/* 719 * FILES (/etc/hosts) 720 */ 721 722static FILE * 723_files_open(int *errp) 724{ 725 FILE *fp; 726 fp = fopen(_PATH_HOSTS, "r"); 727 if (fp == NULL) 728 *errp = NO_RECOVERY; 729 return fp; 730} 731 732static struct hostent * 733_files_ghbyname(const char *name, int af, int *errp) 734{ 735 int match, nalias; 736 char *p, *line, *addrstr, *cname; 737 FILE *fp; 738 struct hostent *rethp, *hp, hpbuf; 739 char *aliases[MAXALIASES + 1], *addrs[2]; 740 union inx_addr addrbuf; 741 char buf[BUFSIZ]; 742 743 if ((fp = _files_open(errp)) == NULL) 744 return NULL; 745 rethp = hp = NULL; 746 747 while (fgets(buf, sizeof(buf), fp)) { 748 line = buf; 749 if ((addrstr = _hgetword(&line)) == NULL 750 || (cname = _hgetword(&line)) == NULL) 751 continue; 752 match = (strcasecmp(cname, name) == 0); 753 nalias = 0; 754 while ((p = _hgetword(&line)) != NULL) { 755 if (!match) 756 match = (strcasecmp(p, name) == 0); 757 if (nalias < MAXALIASES) 758 aliases[nalias++] = p; 759 } 760 if (!match) 761 continue; 762 if (inet_pton(af, addrstr, &addrbuf) != 1) { 763 *errp = NO_DATA; /* name found */ 764 continue; 765 } 766 hp = &hpbuf; 767 hp->h_name = cname; 768 hp->h_aliases = aliases; 769 aliases[nalias] = NULL; 770 hp->h_addrtype = af; 771 hp->h_length = ADDRLEN(af); 772 hp->h_addr_list = addrs; 773 addrs[0] = (char *)&addrbuf; 774 addrs[1] = NULL; 775 hp = _hpcopy(hp, errp); 776 rethp = _hpmerge(rethp, hp, errp); 777 } 778 fclose(fp); 779 return rethp; 780} 781 782static struct hostent * 783_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 784{ 785 int nalias; 786 char *p, *line; 787 FILE *fp; 788 struct hostent *hp, hpbuf; 789 char *aliases[MAXALIASES + 1], *addrs[2]; 790 union inx_addr addrbuf; 791 char buf[BUFSIZ]; 792 793 if ((fp = _files_open(errp)) == NULL) 794 return NULL; 795 hp = NULL; 796 while (fgets(buf, sizeof(buf), fp)) { 797 line = buf; 798 if ((p = _hgetword(&line)) == NULL 799 || inet_pton(af, p, &addrbuf) != 1 800 || memcmp(addr, &addrbuf, addrlen) != 0 801 || (p = _hgetword(&line)) == NULL) 802 continue; 803 hp = &hpbuf; 804 hp->h_name = p; 805 hp->h_aliases = aliases; 806 nalias = 0; 807 while ((p = _hgetword(&line)) != NULL) { 808 if (nalias < MAXALIASES) 809 aliases[nalias++] = p; 810 } 811 aliases[nalias] = NULL; 812 hp->h_addrtype = af; 813 hp->h_length = addrlen; 814 hp->h_addr_list = addrs; 815 addrs[0] = (char *)&addrbuf; 816 addrs[1] = NULL; 817 hp = _hpcopy(hp, errp); 818 break; 819 } 820 fclose(fp); 821 return hp; 822} 823 824#ifdef DEBUG 825#define DNS_ASSERT(X) if (!(X)) { fprintf(stderr, "ASSFAIL: %s %d: %s\n", __FILE__, __LINE__, #X); goto badanswer; } 826#else 827#define DNS_ASSERT(X) if (!(X)) { goto badanswer; } 828#endif 829 830static struct hostent * 831_dns_ghbyname(const char *name, int af, int *errp) 832{ 833 int n; 834 u_char answer[BUFSIZ]; 835 char tbuf[MAXDNAME+1]; 836 HEADER *hp; 837 u_char *cp, *eom; 838 int qtype; 839 int type, class, ancount, qdcount; 840 u_long ttl; 841 char hostbuf[BUFSIZ]; 842 char *bp; 843 char *alist[MAXALIASES]; 844 char *hlist[MAXADDRS]; 845 struct hostent hbuf; 846 int buflen; 847 int na, nh; 848 849 if ((_res.options & RES_INIT) == 0) { 850 if (res_init() < 0) { 851 *errp = h_errno; 852 return NULL; 853 } 854 } 855 hbuf.h_aliases = alist; 856 hbuf.h_addrtype = af; 857 hbuf.h_length = ADDRLEN(af); 858 hbuf.h_addr_list = hlist; 859 na = nh = 0; 860 861#ifdef INET6 862 qtype = (af == AF_INET6 ? T_AAAA : T_A); 863#else 864 qtype = T_A; 865#endif 866 n = res_search(name, C_IN, qtype, answer, sizeof(answer)); 867 if (n < 0) { 868 *errp = h_errno; 869 return NULL; 870 } 871 hp = (HEADER *)answer; 872 eom = answer + n; 873 ancount = ntohs(hp->ancount); 874 qdcount = ntohs(hp->qdcount); 875 DNS_ASSERT(qdcount == 1); 876 cp = answer + sizeof(HEADER); 877 bp = hostbuf; 878 buflen = sizeof(hostbuf); 879 880 n = dn_expand(answer, eom, cp, bp, buflen); 881 DNS_ASSERT(n >= 0); 882 cp += n + QFIXEDSZ; 883 hbuf.h_name = bp; 884 n = strlen(bp) + 1; 885 bp += n; 886 buflen -= n; 887 while (ancount-- > 0 && cp < eom) { 888 n = dn_expand(answer, eom, cp, bp, buflen); 889 DNS_ASSERT(n >= 0); 890 cp += n; /* name */ 891 type = _getshort(cp); 892 cp += 2; /* type */ 893 class = _getshort(cp); 894 cp += 2; /* class */ 895 ttl = _getlong(cp); 896 cp += 4; /* ttl */ 897 n = _getshort(cp); 898 cp += 2; /* len */ 899 DNS_ASSERT(class == C_IN); 900 switch (type) { 901 case T_CNAME: 902 if (na >= MAXALIASES-1) { 903 cp += n; 904 break; 905 } 906 n = dn_expand(answer, eom, cp, tbuf, sizeof(tbuf)); 907 DNS_ASSERT(n >= 0); 908 cp += n; 909 /* alias */ 910 alist[na++] = bp; 911 n = strlen(bp) + 1; 912 bp += n; 913 buflen -= n; 914 /* canon */ 915 n = strlen(tbuf) + 1; 916 DNS_ASSERT(n < buflen); 917 strcpy(bp, tbuf); 918 hbuf.h_name = bp; 919 bp += n; 920 buflen -= n; 921 break; 922 case T_A: 923#ifdef INET6 924 case T_AAAA: 925#endif 926 DNS_ASSERT(type == qtype); 927 bp = (char *)ALIGN(bp); 928 DNS_ASSERT(n == hbuf.h_length); 929 DNS_ASSERT(n < buflen); 930 if (nh < MAXADDRS-1) { 931 hlist[nh++] = bp; 932 memcpy(bp, cp, n); 933 bp += n; 934 buflen -= n; 935 } 936 cp += n; 937 break; 938 default: 939 DNS_ASSERT(0); 940 cp += n; 941 break; 942 } 943 } 944 if (nh == 0) { 945 badanswer: 946 *errp = NO_RECOVERY; 947 return NULL; 948 } 949 alist[na] = NULL; 950 hlist[nh] = NULL; 951 return _hpcopy(&hbuf, errp); 952} 953 954static struct hostent * 955_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 956{ 957 int n; 958 u_char answer[BUFSIZ]; 959 HEADER *hp; 960 u_char c, *cp, *eom; 961 int type, class, ancount, qdcount; 962 u_long ttl; 963 char hostbuf[BUFSIZ]; 964 char *bp; 965 char *alist[MAXALIASES]; 966 char *hlist[2]; 967 struct hostent hbuf; 968 int buflen; 969 int na; 970#ifdef INET6 971 static const char hex[] = "0123456789abcdef"; 972#endif 973 974#ifdef INET6 975 /* XXX */ 976 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) 977 return NULL; 978#endif 979 980 if ((_res.options & RES_INIT) == 0) { 981 if (res_init() < 0) { 982 *errp = h_errno; 983 return NULL; 984 } 985 } 986 hbuf.h_name = NULL; 987 hbuf.h_aliases = alist; 988 hbuf.h_addrtype = af; 989 hbuf.h_length = addrlen; 990 hbuf.h_addr_list = hlist; 991 hlist[0] = (char *)addr; 992 hlist[1] = NULL; 993 na = 0; 994 995 n = 0; 996 bp = hostbuf; 997 cp = (u_char *)addr+addrlen-1; 998 switch (af) { 999#ifdef INET6 1000 case AF_INET6: 1001 for (; n < addrlen; n++, cp--) { 1002 c = *cp; 1003 *bp++ = hex[c & 0xf]; 1004 *bp++ = '.'; 1005 *bp++ = hex[c >> 4]; 1006 *bp++ = '.'; 1007 } 1008 strcpy(bp, "ip6.int"); 1009 break; 1010#endif 1011 default: 1012 for (; n < addrlen; n++, cp--) { 1013 c = *cp; 1014 if (c >= 100) 1015 *bp++ = '0' + c / 100; 1016 if (c >= 10) 1017 *bp++ = '0' + (c % 100) / 10; 1018 *bp++ = '0' + c % 10; 1019 *bp++ = '.'; 1020 } 1021 strcpy(bp, "in-addr.arpa"); 1022 break; 1023 } 1024 1025 n = res_query(hostbuf, C_IN, T_PTR, answer, sizeof(answer)); 1026 if (n < 0) { 1027 *errp = h_errno; 1028 return NULL; 1029 } 1030 hp = (HEADER *)answer; 1031 eom = answer + n; 1032 ancount = ntohs(hp->ancount); 1033 qdcount = ntohs(hp->qdcount); 1034 DNS_ASSERT(qdcount == 1); 1035 cp = answer + sizeof(HEADER); 1036 bp = hostbuf; 1037 buflen = sizeof(hostbuf); 1038 1039 n = dn_expand(answer, eom, cp, bp, buflen); 1040 DNS_ASSERT(n >= 0); 1041 cp += n + QFIXEDSZ; 1042 while (ancount-- > 0 && cp < eom) { 1043 n = dn_expand(answer, eom, cp, bp, buflen); 1044 DNS_ASSERT(n >= 0); 1045 cp += n; /* name */ 1046 type = _getshort(cp); 1047 cp += 2; /* type */ 1048 class = _getshort(cp); 1049 cp += 2; /* class */ 1050 ttl = _getlong(cp); 1051 cp += 4; /* ttl */ 1052 n = _getshort(cp); 1053 cp += 2; /* len */ 1054 DNS_ASSERT(class == C_IN); 1055 switch (type) { 1056 case T_PTR: 1057 n = dn_expand(answer, eom, cp, bp, buflen); 1058 DNS_ASSERT(n >= 0); 1059 cp += n; 1060 if (na >= MAXALIASES-1) 1061 break; 1062 if (hbuf.h_name == NULL) 1063 hbuf.h_name = bp; 1064 else 1065 alist[na++] = bp; 1066 n = strlen(bp) + 1; 1067 bp += n; 1068 buflen -= n; 1069 break; 1070 case T_CNAME: 1071 cp += n; 1072 break; 1073 default: 1074 badanswer: 1075 *errp = NO_RECOVERY; 1076 return NULL; 1077 } 1078 } 1079 if (hbuf.h_name == NULL) { 1080 *errp = h_errno; 1081 return NULL; 1082 } 1083 alist[na] = NULL; 1084 return _hpcopy(&hbuf, errp); 1085} 1086 1087#ifdef ICMPNL 1088 1089/* 1090 * experimental: 1091 * draft-ietf-ipngwg-icmp-namelookups-02.txt 1092 * ifindex is assumed to be encoded in addr. 1093 */ 1094#include <sys/uio.h> 1095#include <netinet/ip6.h> 1096#include <netinet/icmp6.h> 1097 1098struct _icmp_host_cache { 1099 struct _icmp_host_cache *hc_next; 1100 int hc_ifindex; 1101 struct in6_addr hc_addr; 1102 char *hc_name; 1103}; 1104 1105static char * 1106_icmp_fqdn_query(const struct in6_addr *addr, int ifindex) 1107{ 1108 int s; 1109 struct icmp6_filter filter; 1110 struct msghdr msg; 1111 struct cmsghdr *cmsg; 1112 struct in6_pktinfo *pkt; 1113 char cbuf[256]; 1114 char buf[1024]; 1115 int cc; 1116 struct icmp6_fqdn_query *fq; 1117 struct icmp6_fqdn_reply *fr; 1118 struct _icmp_host_cache *hc; 1119 struct sockaddr_in6 sin6; 1120 struct iovec iov; 1121 fd_set s_fds, fds; 1122 struct timeval tout; 1123 int len; 1124 char *name; 1125 static int pid; 1126 static struct _icmp_host_cache *hc_head; 1127 1128 for (hc = hc_head; hc; hc = hc->hc_next) { 1129 if (hc->hc_ifindex == ifindex 1130 && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) 1131 return hc->hc_name; 1132 } 1133 1134 if (pid == 0) 1135 pid = getpid(); 1136 1137 ICMP6_FILTER_SETBLOCKALL(&filter); 1138 ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); 1139 1140 FD_ZERO(&s_fds); 1141 tout.tv_sec = 0; 1142 tout.tv_usec = 200000; /*XXX: 200ms*/ 1143 1144 fq = (struct icmp6_fqdn_query *)buf; 1145 fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; 1146 fq->icmp6_fqdn_code = 0; 1147 fq->icmp6_fqdn_cksum = 0; 1148 fq->icmp6_fqdn_id = (u_short)pid; 1149 fq->icmp6_fqdn_unused = 0; 1150 fq->icmp6_fqdn_cookie[0] = 0; 1151 fq->icmp6_fqdn_cookie[1] = 0; 1152 1153 memset(&sin6, 0, sizeof(sin6)); 1154 sin6.sin6_family = AF_INET6; 1155 sin6.sin6_addr = *addr; 1156 1157 memset(&msg, 0, sizeof(msg)); 1158 msg.msg_name = (caddr_t)&sin6; 1159 msg.msg_namelen = sizeof(sin6); 1160 msg.msg_iov = &iov; 1161 msg.msg_iovlen = 1; 1162 msg.msg_control = NULL; 1163 msg.msg_controllen = 0; 1164 iov.iov_base = (caddr_t)buf; 1165 iov.iov_len = sizeof(struct icmp6_fqdn_query); 1166 1167 if (ifindex) { 1168 msg.msg_control = cbuf; 1169 msg.msg_controllen = sizeof(cbuf); 1170 cmsg = CMSG_FIRSTHDR(&msg); 1171 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1172 cmsg->cmsg_level = IPPROTO_IPV6; 1173 cmsg->cmsg_type = IPV6_PKTINFO; 1174 pkt = (struct in6_pktinfo *)&cmsg[1]; 1175 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); 1176 pkt->ipi6_ifindex = ifindex; 1177 cmsg = CMSG_NXTHDR(&msg, cmsg); 1178 msg.msg_controllen = (char *)cmsg - cbuf; 1179 } 1180 1181 if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) 1182 return NULL; 1183 (void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, 1184 (char *)&filter, sizeof(filter)); 1185 cc = sendmsg(s, &msg, 0); 1186 if (cc < 0) {
| 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_UNSPECIFIED((struct in6_addr *)src)) 373 return NULL; 374 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src) 375 || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) { 376 src = (char *)src + 377 (sizeof(struct in6_addr) - sizeof(struct in_addr)); 378 af = AF_INET; 379 len = sizeof(struct in_addr); 380 } 381 break; 382#endif 383 default: 384 *errp = NO_RECOVERY; 385 return NULL; 386 } 387 388 if (!_hostconf_init_done) 389 _hostconf_init(); 390 for (i = 0; i < MAXHOSTCONF; i++) { 391 if (_hostconf[i].byaddr 392 && (hp = (*_hostconf[i].byaddr)(src, len, af, errp)) != NULL) 393 return hp; 394 } 395 396 return NULL; 397} 398 399void 400freehostent(struct hostent *ptr) 401{ 402 free(ptr); 403} 404 405#if 0 406 407/* XXX: should be deprecated */ 408struct hostent * 409getnodebyname(const char *name, int af, int flags) 410{ 411 return getipnodebyname(name, af, flags, &h_errno); 412} 413 414#ifdef __warn_references 415__warn_references(getnodebyname, 416 "warning: getnodebyname() deprecated, " 417 "should use getaddrinfo() or getipnodebyname()"); 418#endif 419 420struct hostent * 421getnodebyaddr(const void *src, size_t len, int af) 422{ 423 return getipnodebyaddr(src, len, af, &h_errno); 424} 425 426#ifdef __warn_references 427__warn_references(getnodebyaddr, 428 "warning: getnodebyaddr() deprecated, " 429 "should use getnameinfo() or getipnodebyaddr()"); 430#endif 431 432#endif 433 434/* 435 * Private utility functions 436 */ 437 438/* 439 * _hpcopy: allocate and copy hostent structure 440 */ 441static struct hostent * 442_hpcopy(struct hostent *hp, int *errp) 443{ 444 struct hostent *nhp; 445 char *cp, **pp; 446 int size, addrsize; 447 int nalias = 0, naddr = 0; 448 int al_off; 449 int i; 450 451 if (hp == NULL) 452 return hp; 453 454 /* count size to be allocated */ 455 size = sizeof(struct hostent); 456 if (hp->h_name != NULL && *hp->h_name != '\0') 457 size += strlen(hp->h_name) + 1; 458 if ((pp = hp->h_aliases) != NULL) { 459 for (i = 0; *pp != NULL; i++, pp++) { 460 if (**pp != '\0') { 461 size += strlen(*pp) + 1; 462 nalias++; 463 } 464 } 465 } 466 /* adjust alignment */ 467 size = ALIGN(size); 468 al_off = size; 469 size += sizeof(char *) * (nalias + 1); 470 addrsize = ALIGN(hp->h_length); 471 if ((pp = hp->h_addr_list) != NULL) { 472 while (*pp++ != NULL) 473 naddr++; 474 } 475 size += addrsize * naddr; 476 size += sizeof(char *) * (naddr + 1); 477 478 /* copy */ 479 if ((nhp = (struct hostent *)malloc(size)) == NULL) { 480 *errp = TRY_AGAIN; 481 return NULL; 482 } 483 cp = (char *)&nhp[1]; 484 if (hp->h_name != NULL && *hp->h_name != '\0') { 485 nhp->h_name = cp; 486 strcpy(cp, hp->h_name); 487 cp += strlen(cp) + 1; 488 } else 489 nhp->h_name = NULL; 490 nhp->h_aliases = (char **)((char *)nhp + al_off); 491 if ((pp = hp->h_aliases) != NULL) { 492 for (i = 0; *pp != NULL; pp++) { 493 if (**pp != '\0') { 494 nhp->h_aliases[i++] = cp; 495 strcpy(cp, *pp); 496 cp += strlen(cp) + 1; 497 } 498 } 499 } 500 nhp->h_aliases[nalias] = NULL; 501 cp = (char *)&nhp->h_aliases[nalias + 1]; 502 nhp->h_addrtype = hp->h_addrtype; 503 nhp->h_length = hp->h_length; 504 nhp->h_addr_list = (char **)cp; 505 if ((pp = hp->h_addr_list) != NULL) { 506 cp = (char *)&nhp->h_addr_list[naddr + 1]; 507 for (i = 0; *pp != NULL; pp++) { 508 nhp->h_addr_list[i++] = cp; 509 memcpy(cp, *pp, hp->h_length); 510 cp += addrsize; 511 } 512 } 513 nhp->h_addr_list[naddr] = NULL; 514 return nhp; 515} 516 517/* 518 * _hpaddr: construct hostent structure with one address 519 */ 520static struct hostent * 521_hpaddr(int af, const char *name, void *addr, int *errp) 522{ 523 struct hostent *hp, hpbuf; 524 char *addrs[2]; 525 526 hp = &hpbuf; 527 hp->h_name = (char *)name; 528 hp->h_aliases = NULL; 529 hp->h_addrtype = af; 530 hp->h_length = ADDRLEN(af); 531 hp->h_addr_list = addrs; 532 addrs[0] = (char *)addr; 533 addrs[1] = NULL; 534 return _hpcopy(hp, errp); 535} 536 537/* 538 * _hpmerge: merge 2 hostent structure, arguments will be freed 539 */ 540static struct hostent * 541_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp) 542{ 543 int i, j; 544 int naddr, nalias; 545 char **pp; 546 struct hostent *hp, hpbuf; 547 char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1]; 548 union inx_addr addrbuf[MAXADDRS]; 549 550 if (hp1 == NULL) 551 return hp2; 552 if (hp2 == NULL) 553 return hp1; 554 555#define HP(i) (i == 1 ? hp1 : hp2) 556 hp = &hpbuf; 557 hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name); 558 hp->h_aliases = aliases; 559 nalias = 0; 560 for (i = 1; i <= 2; i++) { 561 if ((pp = HP(i)->h_aliases) == NULL) 562 continue; 563 for (; nalias < MAXALIASES && *pp != NULL; pp++) { 564 /* check duplicates */ 565 for (j = 0; j < nalias; j++) 566 if (strcasecmp(*pp, aliases[j]) == 0) 567 break; 568 if (j == nalias) 569 aliases[nalias++] = *pp; 570 } 571 } 572 aliases[nalias] = NULL; 573#ifdef INET6 574 if (hp1->h_length != hp2->h_length) { 575 hp->h_addrtype = AF_INET6; 576 hp->h_length = sizeof(struct in6_addr); 577 } else { 578#endif 579 hp->h_addrtype = hp1->h_addrtype; 580 hp->h_length = hp1->h_length; 581#ifdef INET6 582 } 583#endif 584 hp->h_addr_list = addrs; 585 naddr = 0; 586 for (i = 1; i <= 2; i++) { 587 if ((pp = HP(i)->h_addr_list) == NULL) 588 continue; 589 if (HP(i)->h_length == hp->h_length) { 590 while (naddr < MAXADDRS && *pp != NULL) 591 addrs[naddr++] = *pp++; 592 } else { 593 /* copy IPv4 addr as mapped IPv6 addr */ 594 while (naddr < MAXADDRS && *pp != NULL) { 595 MAPADDR(&addrbuf[naddr], *pp++); 596 addrs[naddr] = (char *)&addrbuf[naddr]; 597 naddr++; 598 } 599 } 600 } 601 addrs[naddr] = NULL; 602 hp = _hpcopy(hp, errp); 603 freehostent(hp1); 604 freehostent(hp2); 605 return hp; 606} 607 608/* 609 * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses 610 */ 611#ifdef INET6 612static struct hostent * 613_hpmapv6(struct hostent *hp, int *errp) 614{ 615 struct hostent *hp6; 616 617 if (hp == NULL) 618 return NULL; 619 if (hp->h_addrtype == AF_INET6) 620 return hp; 621 622 /* make dummy hostent to convert IPv6 address */ 623 if ((hp6 = (struct hostent *)malloc(sizeof(struct hostent))) == NULL) { 624 *errp = TRY_AGAIN; 625 return NULL; 626 } 627 hp6->h_name = NULL; 628 hp6->h_aliases = NULL; 629 hp6->h_addrtype = AF_INET6; 630 hp6->h_length = sizeof(struct in6_addr); 631 hp6->h_addr_list = NULL; 632 return _hpmerge(hp6, hp, errp); 633} 634#endif 635 636/* 637 * _hpsort: sort address by sortlist 638 */ 639static struct hostent * 640_hpsort(struct hostent *hp) 641{ 642 int i, j, n; 643 u_char *ap, *sp, *mp, **pp; 644 char t; 645 char order[MAXADDRS]; 646 int nsort = _res.nsort; 647 648 if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0) 649 return hp; 650 for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) { 651 for (j = 0; j < nsort; j++) { 652#ifdef INET6 653 if (_res_ext.sort_list[j].af != hp->h_addrtype) 654 continue; 655 sp = (u_char *)&_res_ext.sort_list[j].addr; 656 mp = (u_char *)&_res_ext.sort_list[j].mask; 657#else 658 sp = (u_char *)&_res.sort_list[j].addr; 659 mp = (u_char *)&_res.sort_list[j].mask; 660#endif 661 for (n = 0; n < hp->h_length; n++) { 662 if ((ap[n] & mp[n]) != sp[n]) 663 break; 664 } 665 if (n == hp->h_length) 666 break; 667 } 668 order[i] = j; 669 } 670 n = i; 671 pp = (u_char **)hp->h_addr_list; 672 for (i = 0; i < n - 1; i++) { 673 for (j = i + 1; j < n; j++) { 674 if (order[i] > order[j]) { 675 ap = pp[i]; 676 pp[i] = pp[j]; 677 pp[j] = ap; 678 t = order[i]; 679 order[i] = order[j]; 680 order[j] = t; 681 } 682 } 683 } 684 return hp; 685} 686 687static char * 688_hgetword(char **pp) 689{ 690 char c, *p, *ret; 691 const char *sp; 692 static const char sep[] = "# \t\n"; 693 694 ret = NULL; 695 for (p = *pp; (c = *p) != '\0'; p++) { 696 for (sp = sep; *sp != '\0'; sp++) { 697 if (c == *sp) 698 break; 699 } 700 if (c == '#') 701 p[1] = '\0'; /* ignore rest of line */ 702 if (ret == NULL) { 703 if (*sp == '\0') 704 ret = p; 705 } else { 706 if (*sp != '\0') { 707 *p++ = '\0'; 708 break; 709 } 710 } 711 } 712 *pp = p; 713 if (ret == NULL || *ret == '\0') 714 return NULL; 715 return ret; 716} 717 718/* 719 * FILES (/etc/hosts) 720 */ 721 722static FILE * 723_files_open(int *errp) 724{ 725 FILE *fp; 726 fp = fopen(_PATH_HOSTS, "r"); 727 if (fp == NULL) 728 *errp = NO_RECOVERY; 729 return fp; 730} 731 732static struct hostent * 733_files_ghbyname(const char *name, int af, int *errp) 734{ 735 int match, nalias; 736 char *p, *line, *addrstr, *cname; 737 FILE *fp; 738 struct hostent *rethp, *hp, hpbuf; 739 char *aliases[MAXALIASES + 1], *addrs[2]; 740 union inx_addr addrbuf; 741 char buf[BUFSIZ]; 742 743 if ((fp = _files_open(errp)) == NULL) 744 return NULL; 745 rethp = hp = NULL; 746 747 while (fgets(buf, sizeof(buf), fp)) { 748 line = buf; 749 if ((addrstr = _hgetword(&line)) == NULL 750 || (cname = _hgetword(&line)) == NULL) 751 continue; 752 match = (strcasecmp(cname, name) == 0); 753 nalias = 0; 754 while ((p = _hgetword(&line)) != NULL) { 755 if (!match) 756 match = (strcasecmp(p, name) == 0); 757 if (nalias < MAXALIASES) 758 aliases[nalias++] = p; 759 } 760 if (!match) 761 continue; 762 if (inet_pton(af, addrstr, &addrbuf) != 1) { 763 *errp = NO_DATA; /* name found */ 764 continue; 765 } 766 hp = &hpbuf; 767 hp->h_name = cname; 768 hp->h_aliases = aliases; 769 aliases[nalias] = NULL; 770 hp->h_addrtype = af; 771 hp->h_length = ADDRLEN(af); 772 hp->h_addr_list = addrs; 773 addrs[0] = (char *)&addrbuf; 774 addrs[1] = NULL; 775 hp = _hpcopy(hp, errp); 776 rethp = _hpmerge(rethp, hp, errp); 777 } 778 fclose(fp); 779 return rethp; 780} 781 782static struct hostent * 783_files_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 784{ 785 int nalias; 786 char *p, *line; 787 FILE *fp; 788 struct hostent *hp, hpbuf; 789 char *aliases[MAXALIASES + 1], *addrs[2]; 790 union inx_addr addrbuf; 791 char buf[BUFSIZ]; 792 793 if ((fp = _files_open(errp)) == NULL) 794 return NULL; 795 hp = NULL; 796 while (fgets(buf, sizeof(buf), fp)) { 797 line = buf; 798 if ((p = _hgetword(&line)) == NULL 799 || inet_pton(af, p, &addrbuf) != 1 800 || memcmp(addr, &addrbuf, addrlen) != 0 801 || (p = _hgetword(&line)) == NULL) 802 continue; 803 hp = &hpbuf; 804 hp->h_name = p; 805 hp->h_aliases = aliases; 806 nalias = 0; 807 while ((p = _hgetword(&line)) != NULL) { 808 if (nalias < MAXALIASES) 809 aliases[nalias++] = p; 810 } 811 aliases[nalias] = NULL; 812 hp->h_addrtype = af; 813 hp->h_length = addrlen; 814 hp->h_addr_list = addrs; 815 addrs[0] = (char *)&addrbuf; 816 addrs[1] = NULL; 817 hp = _hpcopy(hp, errp); 818 break; 819 } 820 fclose(fp); 821 return hp; 822} 823 824#ifdef DEBUG 825#define DNS_ASSERT(X) if (!(X)) { fprintf(stderr, "ASSFAIL: %s %d: %s\n", __FILE__, __LINE__, #X); goto badanswer; } 826#else 827#define DNS_ASSERT(X) if (!(X)) { goto badanswer; } 828#endif 829 830static struct hostent * 831_dns_ghbyname(const char *name, int af, int *errp) 832{ 833 int n; 834 u_char answer[BUFSIZ]; 835 char tbuf[MAXDNAME+1]; 836 HEADER *hp; 837 u_char *cp, *eom; 838 int qtype; 839 int type, class, ancount, qdcount; 840 u_long ttl; 841 char hostbuf[BUFSIZ]; 842 char *bp; 843 char *alist[MAXALIASES]; 844 char *hlist[MAXADDRS]; 845 struct hostent hbuf; 846 int buflen; 847 int na, nh; 848 849 if ((_res.options & RES_INIT) == 0) { 850 if (res_init() < 0) { 851 *errp = h_errno; 852 return NULL; 853 } 854 } 855 hbuf.h_aliases = alist; 856 hbuf.h_addrtype = af; 857 hbuf.h_length = ADDRLEN(af); 858 hbuf.h_addr_list = hlist; 859 na = nh = 0; 860 861#ifdef INET6 862 qtype = (af == AF_INET6 ? T_AAAA : T_A); 863#else 864 qtype = T_A; 865#endif 866 n = res_search(name, C_IN, qtype, answer, sizeof(answer)); 867 if (n < 0) { 868 *errp = h_errno; 869 return NULL; 870 } 871 hp = (HEADER *)answer; 872 eom = answer + n; 873 ancount = ntohs(hp->ancount); 874 qdcount = ntohs(hp->qdcount); 875 DNS_ASSERT(qdcount == 1); 876 cp = answer + sizeof(HEADER); 877 bp = hostbuf; 878 buflen = sizeof(hostbuf); 879 880 n = dn_expand(answer, eom, cp, bp, buflen); 881 DNS_ASSERT(n >= 0); 882 cp += n + QFIXEDSZ; 883 hbuf.h_name = bp; 884 n = strlen(bp) + 1; 885 bp += n; 886 buflen -= n; 887 while (ancount-- > 0 && cp < eom) { 888 n = dn_expand(answer, eom, cp, bp, buflen); 889 DNS_ASSERT(n >= 0); 890 cp += n; /* name */ 891 type = _getshort(cp); 892 cp += 2; /* type */ 893 class = _getshort(cp); 894 cp += 2; /* class */ 895 ttl = _getlong(cp); 896 cp += 4; /* ttl */ 897 n = _getshort(cp); 898 cp += 2; /* len */ 899 DNS_ASSERT(class == C_IN); 900 switch (type) { 901 case T_CNAME: 902 if (na >= MAXALIASES-1) { 903 cp += n; 904 break; 905 } 906 n = dn_expand(answer, eom, cp, tbuf, sizeof(tbuf)); 907 DNS_ASSERT(n >= 0); 908 cp += n; 909 /* alias */ 910 alist[na++] = bp; 911 n = strlen(bp) + 1; 912 bp += n; 913 buflen -= n; 914 /* canon */ 915 n = strlen(tbuf) + 1; 916 DNS_ASSERT(n < buflen); 917 strcpy(bp, tbuf); 918 hbuf.h_name = bp; 919 bp += n; 920 buflen -= n; 921 break; 922 case T_A: 923#ifdef INET6 924 case T_AAAA: 925#endif 926 DNS_ASSERT(type == qtype); 927 bp = (char *)ALIGN(bp); 928 DNS_ASSERT(n == hbuf.h_length); 929 DNS_ASSERT(n < buflen); 930 if (nh < MAXADDRS-1) { 931 hlist[nh++] = bp; 932 memcpy(bp, cp, n); 933 bp += n; 934 buflen -= n; 935 } 936 cp += n; 937 break; 938 default: 939 DNS_ASSERT(0); 940 cp += n; 941 break; 942 } 943 } 944 if (nh == 0) { 945 badanswer: 946 *errp = NO_RECOVERY; 947 return NULL; 948 } 949 alist[na] = NULL; 950 hlist[nh] = NULL; 951 return _hpcopy(&hbuf, errp); 952} 953 954static struct hostent * 955_dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp) 956{ 957 int n; 958 u_char answer[BUFSIZ]; 959 HEADER *hp; 960 u_char c, *cp, *eom; 961 int type, class, ancount, qdcount; 962 u_long ttl; 963 char hostbuf[BUFSIZ]; 964 char *bp; 965 char *alist[MAXALIASES]; 966 char *hlist[2]; 967 struct hostent hbuf; 968 int buflen; 969 int na; 970#ifdef INET6 971 static const char hex[] = "0123456789abcdef"; 972#endif 973 974#ifdef INET6 975 /* XXX */ 976 if (af == AF_INET6 && IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr)) 977 return NULL; 978#endif 979 980 if ((_res.options & RES_INIT) == 0) { 981 if (res_init() < 0) { 982 *errp = h_errno; 983 return NULL; 984 } 985 } 986 hbuf.h_name = NULL; 987 hbuf.h_aliases = alist; 988 hbuf.h_addrtype = af; 989 hbuf.h_length = addrlen; 990 hbuf.h_addr_list = hlist; 991 hlist[0] = (char *)addr; 992 hlist[1] = NULL; 993 na = 0; 994 995 n = 0; 996 bp = hostbuf; 997 cp = (u_char *)addr+addrlen-1; 998 switch (af) { 999#ifdef INET6 1000 case AF_INET6: 1001 for (; n < addrlen; n++, cp--) { 1002 c = *cp; 1003 *bp++ = hex[c & 0xf]; 1004 *bp++ = '.'; 1005 *bp++ = hex[c >> 4]; 1006 *bp++ = '.'; 1007 } 1008 strcpy(bp, "ip6.int"); 1009 break; 1010#endif 1011 default: 1012 for (; n < addrlen; n++, cp--) { 1013 c = *cp; 1014 if (c >= 100) 1015 *bp++ = '0' + c / 100; 1016 if (c >= 10) 1017 *bp++ = '0' + (c % 100) / 10; 1018 *bp++ = '0' + c % 10; 1019 *bp++ = '.'; 1020 } 1021 strcpy(bp, "in-addr.arpa"); 1022 break; 1023 } 1024 1025 n = res_query(hostbuf, C_IN, T_PTR, answer, sizeof(answer)); 1026 if (n < 0) { 1027 *errp = h_errno; 1028 return NULL; 1029 } 1030 hp = (HEADER *)answer; 1031 eom = answer + n; 1032 ancount = ntohs(hp->ancount); 1033 qdcount = ntohs(hp->qdcount); 1034 DNS_ASSERT(qdcount == 1); 1035 cp = answer + sizeof(HEADER); 1036 bp = hostbuf; 1037 buflen = sizeof(hostbuf); 1038 1039 n = dn_expand(answer, eom, cp, bp, buflen); 1040 DNS_ASSERT(n >= 0); 1041 cp += n + QFIXEDSZ; 1042 while (ancount-- > 0 && cp < eom) { 1043 n = dn_expand(answer, eom, cp, bp, buflen); 1044 DNS_ASSERT(n >= 0); 1045 cp += n; /* name */ 1046 type = _getshort(cp); 1047 cp += 2; /* type */ 1048 class = _getshort(cp); 1049 cp += 2; /* class */ 1050 ttl = _getlong(cp); 1051 cp += 4; /* ttl */ 1052 n = _getshort(cp); 1053 cp += 2; /* len */ 1054 DNS_ASSERT(class == C_IN); 1055 switch (type) { 1056 case T_PTR: 1057 n = dn_expand(answer, eom, cp, bp, buflen); 1058 DNS_ASSERT(n >= 0); 1059 cp += n; 1060 if (na >= MAXALIASES-1) 1061 break; 1062 if (hbuf.h_name == NULL) 1063 hbuf.h_name = bp; 1064 else 1065 alist[na++] = bp; 1066 n = strlen(bp) + 1; 1067 bp += n; 1068 buflen -= n; 1069 break; 1070 case T_CNAME: 1071 cp += n; 1072 break; 1073 default: 1074 badanswer: 1075 *errp = NO_RECOVERY; 1076 return NULL; 1077 } 1078 } 1079 if (hbuf.h_name == NULL) { 1080 *errp = h_errno; 1081 return NULL; 1082 } 1083 alist[na] = NULL; 1084 return _hpcopy(&hbuf, errp); 1085} 1086 1087#ifdef ICMPNL 1088 1089/* 1090 * experimental: 1091 * draft-ietf-ipngwg-icmp-namelookups-02.txt 1092 * ifindex is assumed to be encoded in addr. 1093 */ 1094#include <sys/uio.h> 1095#include <netinet/ip6.h> 1096#include <netinet/icmp6.h> 1097 1098struct _icmp_host_cache { 1099 struct _icmp_host_cache *hc_next; 1100 int hc_ifindex; 1101 struct in6_addr hc_addr; 1102 char *hc_name; 1103}; 1104 1105static char * 1106_icmp_fqdn_query(const struct in6_addr *addr, int ifindex) 1107{ 1108 int s; 1109 struct icmp6_filter filter; 1110 struct msghdr msg; 1111 struct cmsghdr *cmsg; 1112 struct in6_pktinfo *pkt; 1113 char cbuf[256]; 1114 char buf[1024]; 1115 int cc; 1116 struct icmp6_fqdn_query *fq; 1117 struct icmp6_fqdn_reply *fr; 1118 struct _icmp_host_cache *hc; 1119 struct sockaddr_in6 sin6; 1120 struct iovec iov; 1121 fd_set s_fds, fds; 1122 struct timeval tout; 1123 int len; 1124 char *name; 1125 static int pid; 1126 static struct _icmp_host_cache *hc_head; 1127 1128 for (hc = hc_head; hc; hc = hc->hc_next) { 1129 if (hc->hc_ifindex == ifindex 1130 && IN6_ARE_ADDR_EQUAL(&hc->hc_addr, addr)) 1131 return hc->hc_name; 1132 } 1133 1134 if (pid == 0) 1135 pid = getpid(); 1136 1137 ICMP6_FILTER_SETBLOCKALL(&filter); 1138 ICMP6_FILTER_SETPASS(ICMP6_FQDN_REPLY, &filter); 1139 1140 FD_ZERO(&s_fds); 1141 tout.tv_sec = 0; 1142 tout.tv_usec = 200000; /*XXX: 200ms*/ 1143 1144 fq = (struct icmp6_fqdn_query *)buf; 1145 fq->icmp6_fqdn_type = ICMP6_FQDN_QUERY; 1146 fq->icmp6_fqdn_code = 0; 1147 fq->icmp6_fqdn_cksum = 0; 1148 fq->icmp6_fqdn_id = (u_short)pid; 1149 fq->icmp6_fqdn_unused = 0; 1150 fq->icmp6_fqdn_cookie[0] = 0; 1151 fq->icmp6_fqdn_cookie[1] = 0; 1152 1153 memset(&sin6, 0, sizeof(sin6)); 1154 sin6.sin6_family = AF_INET6; 1155 sin6.sin6_addr = *addr; 1156 1157 memset(&msg, 0, sizeof(msg)); 1158 msg.msg_name = (caddr_t)&sin6; 1159 msg.msg_namelen = sizeof(sin6); 1160 msg.msg_iov = &iov; 1161 msg.msg_iovlen = 1; 1162 msg.msg_control = NULL; 1163 msg.msg_controllen = 0; 1164 iov.iov_base = (caddr_t)buf; 1165 iov.iov_len = sizeof(struct icmp6_fqdn_query); 1166 1167 if (ifindex) { 1168 msg.msg_control = cbuf; 1169 msg.msg_controllen = sizeof(cbuf); 1170 cmsg = CMSG_FIRSTHDR(&msg); 1171 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1172 cmsg->cmsg_level = IPPROTO_IPV6; 1173 cmsg->cmsg_type = IPV6_PKTINFO; 1174 pkt = (struct in6_pktinfo *)&cmsg[1]; 1175 memset(&pkt->ipi6_addr, 0, sizeof(struct in6_addr)); 1176 pkt->ipi6_ifindex = ifindex; 1177 cmsg = CMSG_NXTHDR(&msg, cmsg); 1178 msg.msg_controllen = (char *)cmsg - cbuf; 1179 } 1180 1181 if ((s = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) 1182 return NULL; 1183 (void)setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, 1184 (char *)&filter, sizeof(filter)); 1185 cc = sendmsg(s, &msg, 0); 1186 if (cc < 0) {
|