11573Srgrimes/*- 23070Spst * Copyright (c) 1994, Garrett Wollman 31573Srgrimes * 41573Srgrimes * Redistribution and use in source and binary forms, with or without 51573Srgrimes * modification, are permitted provided that the following conditions 61573Srgrimes * are met: 71573Srgrimes * 1. Redistributions of source code must retain the above copyright 81573Srgrimes * notice, this list of conditions and the following disclaimer. 91573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 101573Srgrimes * notice, this list of conditions and the following disclaimer in the 111573Srgrimes * documentation and/or other materials provided with the distribution. 121573Srgrimes * 133070Spst * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND 141573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 151573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 171573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 181573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 191573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 201573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 211573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 221573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 231573Srgrimes * SUCH DAMAGE. 241573Srgrimes */ 251573Srgrimes 2692986Sobrien#include <sys/cdefs.h> 2792986Sobrien__FBSDID("$FreeBSD: releng/11.0/lib/libc/net/gethostnamadr.c 298830 2016-04-30 01:24:24Z pfg $"); 281573Srgrimes 29113977Snectar#include "namespace.h" 30145633Sume#include "reentrant.h" 311573Srgrimes#include <sys/param.h> 321573Srgrimes#include <sys/socket.h> 331573Srgrimes#include <netinet/in.h> 341573Srgrimes#include <arpa/inet.h> 351573Srgrimes#include <netdb.h> 361573Srgrimes#include <stdio.h> 371573Srgrimes#include <ctype.h> 38145512Sume#include <errno.h> 39145633Sume#include <stdlib.h> 401573Srgrimes#include <string.h> 4165532Snectar#include <stdarg.h> 4265532Snectar#include <nsswitch.h> 4317903Speter#include <arpa/nameser.h> /* XXX hack for _res */ 4417903Speter#include <resolv.h> /* XXX hack for _res */ 45113977Snectar#include "un-namespace.h" 46145602Sume#include "netdb_private.h" 47158115Sume#ifdef NS_CACHING 48158115Sume#include "nscache.h" 49158115Sume#endif 501573Srgrimes 51157779Sumestatic int gethostbyname_internal(const char *, int, struct hostent *, char *, 52157779Sume size_t, struct hostent **, int *, res_state); 53145512Sume 54298830Spfg/* Host lookup order if nsswitch.conf is broken or nonexistent */ 55145512Sumestatic const ns_src default_src[] = { 5665532Snectar { NSSRC_FILES, NS_SUCCESS }, 5765532Snectar { NSSRC_DNS, NS_SUCCESS }, 5865532Snectar { 0 } 591991Swollman}; 60158115Sume#ifdef NS_CACHING 61158115Sumestatic int host_id_func(char *, size_t *, va_list, void *); 62158115Sumestatic int host_marshal_func(char *, size_t *, void *, va_list, void *); 63158115Sumestatic int host_unmarshal_func(char *, size_t, void *, va_list, void *); 64158115Sume#endif 651991Swollman 66157779SumeNETDB_THREAD_ALLOC(hostent) 67157779SumeNETDB_THREAD_ALLOC(hostent_data) 68157779SumeNETDB_THREAD_ALLOC(hostdata) 69145633Sume 70145633Sumestatic void 71157779Sumehostent_free(void *ptr) 721991Swollman{ 73157779Sume free(ptr); 74157779Sume} 7517903Speter 76157779Sumestatic void 77157779Sumehostent_data_free(void *ptr) 78157779Sume{ 79157779Sume struct hostent_data *hed = ptr; 80157779Sume 81157779Sume if (hed == NULL) 82145633Sume return; 83157779Sume hed->stayopen = 0; 84157779Sume _endhosthtent(hed); 85157779Sume free(hed); 86145633Sume} 87145633Sume 88145633Sumestatic void 89157779Sumehostdata_free(void *ptr) 90145633Sume{ 91157779Sume free(ptr); 92145633Sume} 93145633Sume 94157779Sumeint 95157779Sume__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf, 96157779Sume size_t buflen) 97145633Sume{ 98157779Sume char *cp; 99157779Sume char **ptr; 100157779Sume int i, n; 101157779Sume int nptr, len; 102145633Sume 103157779Sume /* Find out the amount of space required to store the answer. */ 104157779Sume nptr = 2; /* NULL ptrs */ 105157779Sume len = (char *)ALIGN(buf) - buf; 106157779Sume for (i = 0; he->h_addr_list[i]; i++, nptr++) { 107157779Sume len += he->h_length; 108157779Sume } 109157779Sume for (i = 0; he->h_aliases[i]; i++, nptr++) { 110157779Sume len += strlen(he->h_aliases[i]) + 1; 111157779Sume } 112157779Sume len += strlen(he->h_name) + 1; 113157779Sume len += nptr * sizeof(char*); 114157779Sume 115157779Sume if (len > buflen) { 116157779Sume errno = ERANGE; 117157779Sume return (-1); 118157779Sume } 119157779Sume 120157779Sume /* copy address size and type */ 121157779Sume hptr->h_addrtype = he->h_addrtype; 122157779Sume n = hptr->h_length = he->h_length; 123157779Sume 124157779Sume ptr = (char **)ALIGN(buf); 125157779Sume cp = (char *)ALIGN(buf) + nptr * sizeof(char *); 126157779Sume 127157779Sume /* copy address list */ 128157779Sume hptr->h_addr_list = ptr; 129157779Sume for (i = 0; he->h_addr_list[i]; i++ , ptr++) { 130157779Sume memcpy(cp, he->h_addr_list[i], n); 131157779Sume hptr->h_addr_list[i] = cp; 132157779Sume cp += n; 133157779Sume } 134157779Sume hptr->h_addr_list[i] = NULL; 135157779Sume ptr++; 136157779Sume 137157779Sume /* copy official name */ 138157779Sume n = strlen(he->h_name) + 1; 139157779Sume strcpy(cp, he->h_name); 140157779Sume hptr->h_name = cp; 141157779Sume cp += n; 142157779Sume 143157779Sume /* copy aliases */ 144157779Sume hptr->h_aliases = ptr; 145157779Sume for (i = 0 ; he->h_aliases[i]; i++) { 146157779Sume n = strlen(he->h_aliases[i]) + 1; 147157779Sume strcpy(cp, he->h_aliases[i]); 148157779Sume hptr->h_aliases[i] = cp; 149157779Sume cp += n; 150157779Sume } 151157779Sume hptr->h_aliases[i] = NULL; 152157779Sume 153157779Sume return (0); 154145633Sume} 155145633Sume 156158115Sume#ifdef NS_CACHING 157157779Sumestatic int 158158115Sumehost_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) 159158115Sume{ 160158115Sume res_state statp; 161158115Sume u_long res_options; 162158115Sume 163158115Sume const int op_id = 1; 164158115Sume char *str; 165158791Sume void *addr; 166158791Sume socklen_t len; 167158791Sume int type; 168158115Sume 169158115Sume size_t desired_size, size; 170158115Sume enum nss_lookup_type lookup_type; 171158115Sume char *p; 172158115Sume int res = NS_UNAVAIL; 173158115Sume 174158115Sume statp = __res_state(); 175158115Sume res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | 176158115Sume RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); 177158115Sume 178158115Sume lookup_type = (enum nss_lookup_type)cache_mdata; 179158115Sume switch (lookup_type) { 180158115Sume case nss_lt_name: 181158115Sume str = va_arg(ap, char *); 182158115Sume type = va_arg(ap, int); 183158115Sume 184158115Sume size = strlen(str); 185158115Sume desired_size = sizeof(res_options) + sizeof(int) + 186158115Sume sizeof(enum nss_lookup_type) + sizeof(int) + size + 1; 187158115Sume 188158115Sume if (desired_size > *buffer_size) { 189158115Sume res = NS_RETURN; 190158115Sume goto fin; 191158115Sume } 192158115Sume 193158115Sume p = buffer; 194158115Sume 195158115Sume memcpy(p, &res_options, sizeof(res_options)); 196158115Sume p += sizeof(res_options); 197158115Sume 198158115Sume memcpy(p, &op_id, sizeof(int)); 199158115Sume p += sizeof(int); 200158115Sume 201158115Sume memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); 202158115Sume p += sizeof(int); 203158115Sume 204158115Sume memcpy(p, &type, sizeof(int)); 205158115Sume p += sizeof(int); 206158115Sume 207158115Sume memcpy(p, str, size + 1); 208158115Sume 209158115Sume res = NS_SUCCESS; 210158115Sume break; 211158115Sume case nss_lt_id: 212158791Sume addr = va_arg(ap, void *); 213158791Sume len = va_arg(ap, socklen_t); 214158115Sume type = va_arg(ap, int); 215158115Sume 216158115Sume desired_size = sizeof(res_options) + sizeof(int) + 217158791Sume sizeof(enum nss_lookup_type) + sizeof(int) + 218158791Sume sizeof(socklen_t) + len; 219158115Sume 220158115Sume if (desired_size > *buffer_size) { 221158115Sume res = NS_RETURN; 222158115Sume goto fin; 223158115Sume } 224158115Sume 225158115Sume p = buffer; 226158115Sume memcpy(p, &res_options, sizeof(res_options)); 227158115Sume p += sizeof(res_options); 228158115Sume 229158115Sume memcpy(p, &op_id, sizeof(int)); 230158115Sume p += sizeof(int); 231158115Sume 232158115Sume memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); 233158115Sume p += sizeof(int); 234158115Sume 235158115Sume memcpy(p, &type, sizeof(int)); 236158115Sume p += sizeof(int); 237158115Sume 238158791Sume memcpy(p, &len, sizeof(socklen_t)); 239158791Sume p += sizeof(socklen_t); 240158115Sume 241158791Sume memcpy(p, addr, len); 242158115Sume 243158115Sume res = NS_SUCCESS; 244158115Sume break; 245158115Sume default: 246158115Sume /* should be unreachable */ 247158115Sume return (NS_UNAVAIL); 248158115Sume } 249158115Sume 250158115Sumefin: 251158115Sume *buffer_size = desired_size; 252158115Sume return (res); 253158115Sume} 254158115Sume 255158115Sumestatic int 256158115Sumehost_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, 257158115Sume void *cache_mdata) 258158115Sume{ 259158115Sume char *str; 260158791Sume void *addr; 261158791Sume socklen_t len; 262158791Sume int type; 263158115Sume struct hostent *ht; 264158115Sume 265158115Sume struct hostent new_ht; 266158115Sume size_t desired_size, aliases_size, addr_size, size; 267158115Sume char *p, **iter; 268158115Sume 269158115Sume switch ((enum nss_lookup_type)cache_mdata) { 270158115Sume case nss_lt_name: 271158115Sume str = va_arg(ap, char *); 272158115Sume type = va_arg(ap, int); 273158115Sume break; 274158115Sume case nss_lt_id: 275158791Sume addr = va_arg(ap, void *); 276158791Sume len = va_arg(ap, socklen_t); 277158115Sume type = va_arg(ap, int); 278158115Sume break; 279158115Sume default: 280158115Sume /* should be unreachable */ 281158115Sume return (NS_UNAVAIL); 282158115Sume } 283158115Sume ht = va_arg(ap, struct hostent *); 284158115Sume 285158115Sume desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *); 286158115Sume if (ht->h_name != NULL) 287158115Sume desired_size += strlen(ht->h_name) + 1; 288158115Sume 289158115Sume if (ht->h_aliases != NULL) { 290158115Sume aliases_size = 0; 291158115Sume for (iter = ht->h_aliases; *iter; ++iter) { 292158115Sume desired_size += strlen(*iter) + 1; 293158115Sume ++aliases_size; 294158115Sume } 295158115Sume 296158115Sume desired_size += _ALIGNBYTES + 297158115Sume (aliases_size + 1) * sizeof(char *); 298158115Sume } 299158115Sume 300158115Sume if (ht->h_addr_list != NULL) { 301158115Sume addr_size = 0; 302158115Sume for (iter = ht->h_addr_list; *iter; ++iter) 303158115Sume ++addr_size; 304158115Sume 305158115Sume desired_size += addr_size * _ALIGN(ht->h_length); 306158115Sume desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *); 307158115Sume } 308158115Sume 309158115Sume if (desired_size > *buffer_size) { 310158115Sume /* this assignment is here for future use */ 311158115Sume *buffer_size = desired_size; 312158115Sume return (NS_RETURN); 313158115Sume } 314158115Sume 315158115Sume memcpy(&new_ht, ht, sizeof(struct hostent)); 316158115Sume memset(buffer, 0, desired_size); 317158115Sume 318158115Sume *buffer_size = desired_size; 319158115Sume p = buffer + sizeof(struct hostent) + sizeof(char *); 320158115Sume memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *)); 321158115Sume p = (char *)_ALIGN(p); 322158115Sume 323158115Sume if (new_ht.h_name != NULL) { 324158115Sume size = strlen(new_ht.h_name); 325158115Sume memcpy(p, new_ht.h_name, size); 326158115Sume new_ht.h_name = p; 327158115Sume p += size + 1; 328158115Sume } 329158115Sume 330158115Sume if (new_ht.h_aliases != NULL) { 331158115Sume p = (char *)_ALIGN(p); 332158115Sume memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size); 333158115Sume new_ht.h_aliases = (char **)p; 334158115Sume p += sizeof(char *) * (aliases_size + 1); 335158115Sume 336158115Sume for (iter = new_ht.h_aliases; *iter; ++iter) { 337158115Sume size = strlen(*iter); 338158115Sume memcpy(p, *iter, size); 339158115Sume *iter = p; 340158115Sume p += size + 1; 341158115Sume } 342158115Sume } 343158115Sume 344158115Sume if (new_ht.h_addr_list != NULL) { 345158115Sume p = (char *)_ALIGN(p); 346158115Sume memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size); 347158115Sume new_ht.h_addr_list = (char **)p; 348158115Sume p += sizeof(char *) * (addr_size + 1); 349158115Sume 350158115Sume size = _ALIGN(new_ht.h_length); 351158115Sume for (iter = new_ht.h_addr_list; *iter; ++iter) { 352158115Sume memcpy(p, *iter, size); 353158115Sume *iter = p; 354158115Sume p += size + 1; 355158115Sume } 356158115Sume } 357158115Sume memcpy(buffer, &new_ht, sizeof(struct hostent)); 358158115Sume return (NS_SUCCESS); 359158115Sume} 360158115Sume 361158115Sumestatic int 362158115Sumehost_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, 363158115Sume void *cache_mdata) 364158115Sume{ 365158115Sume char *str; 366158791Sume void *addr; 367158791Sume socklen_t len; 368158791Sume int type; 369158115Sume struct hostent *ht; 370158115Sume 371158115Sume char *p; 372158115Sume char **iter; 373158115Sume char *orig_buf; 374158115Sume size_t orig_buf_size; 375158115Sume 376158115Sume switch ((enum nss_lookup_type)cache_mdata) { 377158115Sume case nss_lt_name: 378158115Sume str = va_arg(ap, char *); 379158115Sume type = va_arg(ap, int); 380158115Sume break; 381158115Sume case nss_lt_id: 382158791Sume addr = va_arg(ap, void *); 383158791Sume len = va_arg(ap, socklen_t); 384158115Sume type = va_arg(ap, int); 385158115Sume break; 386158115Sume default: 387158115Sume /* should be unreachable */ 388158115Sume return (NS_UNAVAIL); 389158115Sume } 390158115Sume 391158115Sume ht = va_arg(ap, struct hostent *); 392158115Sume orig_buf = va_arg(ap, char *); 393158115Sume orig_buf_size = va_arg(ap, size_t); 394158115Sume 395158115Sume if (orig_buf_size < 396158115Sume buffer_size - sizeof(struct hostent) - sizeof(char *)) { 397158115Sume errno = ERANGE; 398158115Sume return (NS_RETURN); 399158115Sume } 400158115Sume 401158115Sume memcpy(ht, buffer, sizeof(struct hostent)); 402158115Sume memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *)); 403158115Sume 404158115Sume orig_buf = (char *)_ALIGN(orig_buf); 405158115Sume memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) + 406158115Sume _ALIGN(p) - (size_t)p, 407158115Sume buffer_size - sizeof(struct hostent) - sizeof(char *) - 408158115Sume _ALIGN(p) + (size_t)p); 409158115Sume p = (char *)_ALIGN(p); 410158115Sume 411158115Sume NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *); 412158115Sume if (ht->h_aliases != NULL) { 413158115Sume NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **); 414158115Sume 415158115Sume for (iter = ht->h_aliases; *iter; ++iter) 416158115Sume NS_APPLY_OFFSET(*iter, orig_buf, p, char *); 417158115Sume } 418158115Sume 419158115Sume if (ht->h_addr_list != NULL) { 420158115Sume NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **); 421158115Sume 422158115Sume for (iter = ht->h_addr_list; *iter; ++iter) 423158115Sume NS_APPLY_OFFSET(*iter, orig_buf, p, char *); 424158115Sume } 425158115Sume 426158115Sume *((struct hostent **)retval) = ht; 427158115Sume return (NS_SUCCESS); 428158115Sume} 429158115Sume#endif /* NS_CACHING */ 430158115Sume 431158115Sumestatic int 432157779Sumefakeaddr(const char *name, int af, struct hostent *hp, char *buf, 433158115Sume size_t buflen, res_state statp) 434157779Sume{ 435157779Sume struct hostent_data *hed; 436157779Sume struct hostent he; 437157779Sume 438157779Sume if ((hed = __hostent_data_init()) == NULL) { 439157779Sume errno = ENOMEM; 440157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 441157779Sume return (-1); 442157779Sume } 443157779Sume 444157779Sume if ((af != AF_INET || 445157779Sume inet_aton(name, (struct in_addr *)hed->host_addr) != 1) && 446157779Sume inet_pton(af, name, hed->host_addr) != 1) { 447157779Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 448157779Sume return (-1); 449157779Sume } 450157779Sume strncpy(hed->hostbuf, name, MAXDNAME); 451157779Sume hed->hostbuf[MAXDNAME] = '\0'; 452157779Sume if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) { 453157779Sume _map_v4v6_address((char *)hed->host_addr, 454157779Sume (char *)hed->host_addr); 455157779Sume af = AF_INET6; 456157779Sume } 457157779Sume he.h_addrtype = af; 458157779Sume switch(af) { 459157779Sume case AF_INET: 460157779Sume he.h_length = NS_INADDRSZ; 461157779Sume break; 462157779Sume case AF_INET6: 463157779Sume he.h_length = NS_IN6ADDRSZ; 464157779Sume break; 465157779Sume default: 466157779Sume errno = EAFNOSUPPORT; 467157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 468157779Sume return (-1); 469157779Sume } 470157779Sume he.h_name = hed->hostbuf; 471157779Sume he.h_aliases = hed->host_aliases; 472157779Sume hed->host_aliases[0] = NULL; 473157779Sume hed->h_addr_ptrs[0] = (char *)hed->host_addr; 474157779Sume hed->h_addr_ptrs[1] = NULL; 475157779Sume he.h_addr_list = hed->h_addr_ptrs; 476211276Sume if (__copy_hostent(&he, hp, buf, buflen) != 0) { 477211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 478211276Sume return (-1); 479211276Sume } 480157779Sume RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 481211276Sume return (0); 482157779Sume} 483157779Sume 484145633Sumeint 485157779Sumegethostbyname_r(const char *name, struct hostent *he, char *buffer, 486157779Sume size_t buflen, struct hostent **result, int *h_errnop) 487145633Sume{ 488157779Sume res_state statp; 489145633Sume 490157779Sume statp = __res_state(); 491157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 492157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 493157779Sume return (-1); 49467709Sume } 495157779Sume if (statp->options & RES_USE_INET6) { 496157779Sume if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) { 497157779Sume *result = he; 498157779Sume return (0); 499157779Sume } 500157779Sume if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen, 501157779Sume result, h_errnop, statp) == 0) 502157779Sume return (0); 503145512Sume } 504157779Sume return (gethostbyname_internal(name, AF_INET, he, buffer, buflen, 505157779Sume result, h_errnop, statp)); 50617903Speter} 50717903Speter 508145633Sumeint 509157779Sumegethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer, 510157779Sume size_t buflen, struct hostent **result, int *h_errnop) 51117903Speter{ 512157779Sume res_state statp; 513157779Sume 514157779Sume statp = __res_state(); 515157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 516157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 517157779Sume return (-1); 518145512Sume } 519157779Sume return (gethostbyname_internal(name, af, he, buffer, buflen, result, 520157779Sume h_errnop, statp)); 521145512Sume} 522145512Sume 523157779Sumeint 524157779Sumegethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf, 525157779Sume size_t buflen, struct hostent **result, int *h_errnop, res_state statp) 526145512Sume{ 527145512Sume const char *cp; 528211276Sume int rval, ret_errno = 0; 529145512Sume char abuf[MAXDNAME]; 5301991Swollman 531158115Sume#ifdef NS_CACHING 532158115Sume static const nss_cache_info cache_info = 533158115Sume NS_COMMON_CACHE_INFO_INITIALIZER( 534158115Sume hosts, (void *)nss_lt_name, 535158115Sume host_id_func, host_marshal_func, host_unmarshal_func); 536158115Sume#endif 53765532Snectar static const ns_dtab dtab[] = { 53865532Snectar NS_FILES_CB(_ht_gethostbyname, NULL) 53965532Snectar { NSSRC_DNS, _dns_gethostbyname, NULL }, 54065532Snectar NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ 541158115Sume#ifdef NS_CACHING 542158115Sume NS_CACHE_CB(&cache_info) 543158115Sume#endif 54465532Snectar { 0 } 545145512Sume }; 546145512Sume 547145512Sume switch (af) { 548145512Sume case AF_INET: 549145512Sume case AF_INET6: 550145512Sume break; 551145512Sume default: 552157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 553157779Sume *h_errnop = statp->res_h_errno; 554145512Sume errno = EAFNOSUPPORT; 555157779Sume return (-1); 556145512Sume } 557145512Sume 558145512Sume /* 559145512Sume * if there aren't any dots, it could be a user-level alias. 560145512Sume * this is also done in res_query() since we are not the only 561145512Sume * function that looks up host names. 562145512Sume */ 563145512Sume if (!strchr(name, '.') && 564157779Sume (cp = res_hostalias(statp, name, abuf, sizeof abuf))) 565145512Sume name = cp; 566145512Sume 567157779Sume if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) { 568157779Sume *result = hp; 569157779Sume return (0); 570157779Sume } 571145512Sume 572157779Sume rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, 573157779Sume "gethostbyname2_r", default_src, name, af, hp, buf, buflen, 574157779Sume &ret_errno, h_errnop); 5751991Swollman 576211276Sume if (rval != NS_SUCCESS) { 577211276Sume errno = ret_errno; 578211276Sume return ((ret_errno != 0) ? ret_errno : -1); 579211276Sume } 580211276Sume return (0); 5811991Swollman} 5821991Swollman 583145633Sumeint 584158791Sumegethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, 585158791Sume char *buf, size_t buflen, struct hostent **result, int *h_errnop) 5861991Swollman{ 587145687Sume const u_char *uaddr = (const u_char *)addr; 588145687Sume const struct in6_addr *addr6; 589145687Sume socklen_t size; 590211276Sume int rval, ret_errno = 0; 591157779Sume res_state statp; 5921991Swollman 593158115Sume#ifdef NS_CACHING 594158115Sume static const nss_cache_info cache_info = 595158115Sume NS_COMMON_CACHE_INFO_INITIALIZER( 596158115Sume hosts, (void *)nss_lt_id, 597158115Sume host_id_func, host_marshal_func, host_unmarshal_func); 598158115Sume#endif 59965532Snectar static const ns_dtab dtab[] = { 60065532Snectar NS_FILES_CB(_ht_gethostbyaddr, NULL) 60165532Snectar { NSSRC_DNS, _dns_gethostbyaddr, NULL }, 60265532Snectar NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ 603158115Sume#ifdef NS_CACHING 604158115Sume NS_CACHE_CB(&cache_info) 605158115Sume#endif 60665532Snectar { 0 } 607145633Sume }; 6081991Swollman 609157779Sume statp = __res_state(); 610157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 611157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 612157779Sume *h_errnop = statp->res_h_errno; 613157779Sume return (-1); 614145728Sume } 615145728Sume 616157779Sume if (af == AF_INET6 && len == NS_IN6ADDRSZ) { 617158477Sume addr6 = (const struct in6_addr *)addr; 618145687Sume if (IN6_IS_ADDR_LINKLOCAL(addr6)) { 619157779Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 620157779Sume *h_errnop = statp->res_h_errno; 621157779Sume return (-1); 622145687Sume } 623145687Sume if (IN6_IS_ADDR_V4MAPPED(addr6) || 624145687Sume IN6_IS_ADDR_V4COMPAT(addr6)) { 625145687Sume /* Unmap. */ 626157779Sume uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; 627145687Sume af = AF_INET; 628157779Sume len = NS_INADDRSZ; 629145687Sume } 630145687Sume } 631145687Sume switch (af) { 632145687Sume case AF_INET: 633157779Sume size = NS_INADDRSZ; 634145687Sume break; 635145687Sume case AF_INET6: 636157779Sume size = NS_IN6ADDRSZ; 637145687Sume break; 638145687Sume default: 639145687Sume errno = EAFNOSUPPORT; 640157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 641157779Sume *h_errnop = statp->res_h_errno; 642157779Sume return (-1); 643145687Sume } 644145687Sume if (size != len) { 645145687Sume errno = EINVAL; 646157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 647157779Sume *h_errnop = statp->res_h_errno; 648157779Sume return (-1); 649145687Sume } 650145687Sume 651157779Sume rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, 652157779Sume "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen, 653157779Sume &ret_errno, h_errnop); 65465532Snectar 655211276Sume if (rval != NS_SUCCESS) { 656211276Sume errno = ret_errno; 657211276Sume return ((ret_errno != 0) ? ret_errno : -1); 658211276Sume } 659211276Sume return (0); 6601991Swollman} 6611991Swollman 662145633Sumestruct hostent * 663145633Sumegethostbyname(const char *name) 664145633Sume{ 665145633Sume struct hostdata *hd; 666157779Sume struct hostent *rval; 667157779Sume int ret_h_errno; 668145633Sume 669145633Sume if ((hd = __hostdata_init()) == NULL) 670157779Sume return (NULL); 671157779Sume if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval, 672157779Sume &ret_h_errno) != 0) 673157779Sume return (NULL); 674157779Sume return (rval); 675145633Sume} 676145633Sume 677145633Sumestruct hostent * 678145633Sumegethostbyname2(const char *name, int af) 679145633Sume{ 680145633Sume struct hostdata *hd; 681157779Sume struct hostent *rval; 682157779Sume int ret_h_errno; 683145633Sume 684145633Sume if ((hd = __hostdata_init()) == NULL) 685157779Sume return (NULL); 686157779Sume if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data), 687157779Sume &rval, &ret_h_errno) != 0) 688157779Sume return (NULL); 689157779Sume return (rval); 690145633Sume} 691145633Sume 692145633Sumestruct hostent * 693158477Sumegethostbyaddr(const void *addr, socklen_t len, int af) 694145633Sume{ 695145633Sume struct hostdata *hd; 696157779Sume struct hostent *rval; 697157779Sume int ret_h_errno; 698145633Sume 699145633Sume if ((hd = __hostdata_init()) == NULL) 700157779Sume return (NULL); 701157779Sume if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data, 702157779Sume sizeof(hd->data), &rval, &ret_h_errno) != 0) 703157779Sume return (NULL); 704157779Sume return (rval); 705145633Sume} 706145633Sume 707145633Sumevoid 708145633Sumesethostent(int stayopen) 709145633Sume{ 710157779Sume struct hostent_data *hed; 711145633Sume 712157779Sume if ((hed = __hostent_data_init()) == NULL) 713145633Sume return; 714157779Sume _sethosthtent(stayopen, hed); 715157779Sume _sethostdnsent(stayopen); 716145633Sume} 717145633Sume 718145633Sumevoid 719145633Sumeendhostent(void) 720145633Sume{ 721157779Sume struct hostent_data *hed; 722145633Sume 723157779Sume if ((hed = __hostent_data_init()) == NULL) 724145633Sume return; 725157779Sume _endhosthtent(hed); 726157779Sume _endhostdnsent(); 727145633Sume} 728