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$"); 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 5165532Snectarextern int _ht_gethostbyname(void *, void *, va_list); 5265532Snectarextern int _dns_gethostbyname(void *, void *, va_list); 5365532Snectarextern int _nis_gethostbyname(void *, void *, va_list); 5465532Snectarextern int _ht_gethostbyaddr(void *, void *, va_list); 5565532Snectarextern int _dns_gethostbyaddr(void *, void *, va_list); 5665532Snectarextern int _nis_gethostbyaddr(void *, void *, va_list); 571991Swollman 58157779Sumestatic int gethostbyname_internal(const char *, int, struct hostent *, char *, 59157779Sume size_t, struct hostent **, int *, res_state); 60145512Sume 6165532Snectar/* Host lookup order if nsswitch.conf is broken or nonexistant */ 62145512Sumestatic const ns_src default_src[] = { 6365532Snectar { NSSRC_FILES, NS_SUCCESS }, 6465532Snectar { NSSRC_DNS, NS_SUCCESS }, 6565532Snectar { 0 } 661991Swollman}; 67158115Sume#ifdef NS_CACHING 68158115Sumestatic int host_id_func(char *, size_t *, va_list, void *); 69158115Sumestatic int host_marshal_func(char *, size_t *, void *, va_list, void *); 70158115Sumestatic int host_unmarshal_func(char *, size_t, void *, va_list, void *); 71158115Sume#endif 721991Swollman 73157779SumeNETDB_THREAD_ALLOC(hostent) 74157779SumeNETDB_THREAD_ALLOC(hostent_data) 75157779SumeNETDB_THREAD_ALLOC(hostdata) 76145633Sume 77145633Sumestatic void 78157779Sumehostent_free(void *ptr) 791991Swollman{ 80157779Sume free(ptr); 81157779Sume} 8217903Speter 83157779Sumestatic void 84157779Sumehostent_data_free(void *ptr) 85157779Sume{ 86157779Sume struct hostent_data *hed = ptr; 87157779Sume 88157779Sume if (hed == NULL) 89145633Sume return; 90157779Sume hed->stayopen = 0; 91157779Sume _endhosthtent(hed); 92157779Sume free(hed); 93145633Sume} 94145633Sume 95145633Sumestatic void 96157779Sumehostdata_free(void *ptr) 97145633Sume{ 98157779Sume free(ptr); 99145633Sume} 100145633Sume 101157779Sumeint 102157779Sume__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf, 103157779Sume size_t buflen) 104145633Sume{ 105157779Sume char *cp; 106157779Sume char **ptr; 107157779Sume int i, n; 108157779Sume int nptr, len; 109145633Sume 110157779Sume /* Find out the amount of space required to store the answer. */ 111157779Sume nptr = 2; /* NULL ptrs */ 112157779Sume len = (char *)ALIGN(buf) - buf; 113157779Sume for (i = 0; he->h_addr_list[i]; i++, nptr++) { 114157779Sume len += he->h_length; 115157779Sume } 116157779Sume for (i = 0; he->h_aliases[i]; i++, nptr++) { 117157779Sume len += strlen(he->h_aliases[i]) + 1; 118157779Sume } 119157779Sume len += strlen(he->h_name) + 1; 120157779Sume len += nptr * sizeof(char*); 121157779Sume 122157779Sume if (len > buflen) { 123157779Sume errno = ERANGE; 124157779Sume return (-1); 125157779Sume } 126157779Sume 127157779Sume /* copy address size and type */ 128157779Sume hptr->h_addrtype = he->h_addrtype; 129157779Sume n = hptr->h_length = he->h_length; 130157779Sume 131157779Sume ptr = (char **)ALIGN(buf); 132157779Sume cp = (char *)ALIGN(buf) + nptr * sizeof(char *); 133157779Sume 134157779Sume /* copy address list */ 135157779Sume hptr->h_addr_list = ptr; 136157779Sume for (i = 0; he->h_addr_list[i]; i++ , ptr++) { 137157779Sume memcpy(cp, he->h_addr_list[i], n); 138157779Sume hptr->h_addr_list[i] = cp; 139157779Sume cp += n; 140157779Sume } 141157779Sume hptr->h_addr_list[i] = NULL; 142157779Sume ptr++; 143157779Sume 144157779Sume /* copy official name */ 145157779Sume n = strlen(he->h_name) + 1; 146157779Sume strcpy(cp, he->h_name); 147157779Sume hptr->h_name = cp; 148157779Sume cp += n; 149157779Sume 150157779Sume /* copy aliases */ 151157779Sume hptr->h_aliases = ptr; 152157779Sume for (i = 0 ; he->h_aliases[i]; i++) { 153157779Sume n = strlen(he->h_aliases[i]) + 1; 154157779Sume strcpy(cp, he->h_aliases[i]); 155157779Sume hptr->h_aliases[i] = cp; 156157779Sume cp += n; 157157779Sume } 158157779Sume hptr->h_aliases[i] = NULL; 159157779Sume 160157779Sume return (0); 161145633Sume} 162145633Sume 163158115Sume#ifdef NS_CACHING 164157779Sumestatic int 165158115Sumehost_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata) 166158115Sume{ 167158115Sume res_state statp; 168158115Sume u_long res_options; 169158115Sume 170158115Sume const int op_id = 1; 171158115Sume char *str; 172158791Sume void *addr; 173158791Sume socklen_t len; 174158791Sume int type; 175158115Sume 176158115Sume size_t desired_size, size; 177158115Sume enum nss_lookup_type lookup_type; 178158115Sume char *p; 179158115Sume int res = NS_UNAVAIL; 180158115Sume 181158115Sume statp = __res_state(); 182158115Sume res_options = statp->options & (RES_RECURSE | RES_DEFNAMES | 183158115Sume RES_DNSRCH | RES_NOALIASES | RES_USE_INET6); 184158115Sume 185158115Sume lookup_type = (enum nss_lookup_type)cache_mdata; 186158115Sume switch (lookup_type) { 187158115Sume case nss_lt_name: 188158115Sume str = va_arg(ap, char *); 189158115Sume type = va_arg(ap, int); 190158115Sume 191158115Sume size = strlen(str); 192158115Sume desired_size = sizeof(res_options) + sizeof(int) + 193158115Sume sizeof(enum nss_lookup_type) + sizeof(int) + size + 1; 194158115Sume 195158115Sume if (desired_size > *buffer_size) { 196158115Sume res = NS_RETURN; 197158115Sume goto fin; 198158115Sume } 199158115Sume 200158115Sume p = buffer; 201158115Sume 202158115Sume memcpy(p, &res_options, sizeof(res_options)); 203158115Sume p += sizeof(res_options); 204158115Sume 205158115Sume memcpy(p, &op_id, sizeof(int)); 206158115Sume p += sizeof(int); 207158115Sume 208158115Sume memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); 209158115Sume p += sizeof(int); 210158115Sume 211158115Sume memcpy(p, &type, sizeof(int)); 212158115Sume p += sizeof(int); 213158115Sume 214158115Sume memcpy(p, str, size + 1); 215158115Sume 216158115Sume res = NS_SUCCESS; 217158115Sume break; 218158115Sume case nss_lt_id: 219158791Sume addr = va_arg(ap, void *); 220158791Sume len = va_arg(ap, socklen_t); 221158115Sume type = va_arg(ap, int); 222158115Sume 223158115Sume desired_size = sizeof(res_options) + sizeof(int) + 224158791Sume sizeof(enum nss_lookup_type) + sizeof(int) + 225158791Sume sizeof(socklen_t) + len; 226158115Sume 227158115Sume if (desired_size > *buffer_size) { 228158115Sume res = NS_RETURN; 229158115Sume goto fin; 230158115Sume } 231158115Sume 232158115Sume p = buffer; 233158115Sume memcpy(p, &res_options, sizeof(res_options)); 234158115Sume p += sizeof(res_options); 235158115Sume 236158115Sume memcpy(p, &op_id, sizeof(int)); 237158115Sume p += sizeof(int); 238158115Sume 239158115Sume memcpy(p, &lookup_type, sizeof(enum nss_lookup_type)); 240158115Sume p += sizeof(int); 241158115Sume 242158115Sume memcpy(p, &type, sizeof(int)); 243158115Sume p += sizeof(int); 244158115Sume 245158791Sume memcpy(p, &len, sizeof(socklen_t)); 246158791Sume p += sizeof(socklen_t); 247158115Sume 248158791Sume memcpy(p, addr, len); 249158115Sume 250158115Sume res = NS_SUCCESS; 251158115Sume break; 252158115Sume default: 253158115Sume /* should be unreachable */ 254158115Sume return (NS_UNAVAIL); 255158115Sume } 256158115Sume 257158115Sumefin: 258158115Sume *buffer_size = desired_size; 259158115Sume return (res); 260158115Sume} 261158115Sume 262158115Sumestatic int 263158115Sumehost_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap, 264158115Sume void *cache_mdata) 265158115Sume{ 266158115Sume char *str; 267158791Sume void *addr; 268158791Sume socklen_t len; 269158791Sume int type; 270158115Sume struct hostent *ht; 271158115Sume 272158115Sume struct hostent new_ht; 273158115Sume size_t desired_size, aliases_size, addr_size, size; 274158115Sume char *p, **iter; 275158115Sume 276158115Sume switch ((enum nss_lookup_type)cache_mdata) { 277158115Sume case nss_lt_name: 278158115Sume str = va_arg(ap, char *); 279158115Sume type = va_arg(ap, int); 280158115Sume break; 281158115Sume case nss_lt_id: 282158791Sume addr = va_arg(ap, void *); 283158791Sume len = va_arg(ap, socklen_t); 284158115Sume type = va_arg(ap, int); 285158115Sume break; 286158115Sume default: 287158115Sume /* should be unreachable */ 288158115Sume return (NS_UNAVAIL); 289158115Sume } 290158115Sume ht = va_arg(ap, struct hostent *); 291158115Sume 292158115Sume desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *); 293158115Sume if (ht->h_name != NULL) 294158115Sume desired_size += strlen(ht->h_name) + 1; 295158115Sume 296158115Sume if (ht->h_aliases != NULL) { 297158115Sume aliases_size = 0; 298158115Sume for (iter = ht->h_aliases; *iter; ++iter) { 299158115Sume desired_size += strlen(*iter) + 1; 300158115Sume ++aliases_size; 301158115Sume } 302158115Sume 303158115Sume desired_size += _ALIGNBYTES + 304158115Sume (aliases_size + 1) * sizeof(char *); 305158115Sume } 306158115Sume 307158115Sume if (ht->h_addr_list != NULL) { 308158115Sume addr_size = 0; 309158115Sume for (iter = ht->h_addr_list; *iter; ++iter) 310158115Sume ++addr_size; 311158115Sume 312158115Sume desired_size += addr_size * _ALIGN(ht->h_length); 313158115Sume desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *); 314158115Sume } 315158115Sume 316158115Sume if (desired_size > *buffer_size) { 317158115Sume /* this assignment is here for future use */ 318158115Sume *buffer_size = desired_size; 319158115Sume return (NS_RETURN); 320158115Sume } 321158115Sume 322158115Sume memcpy(&new_ht, ht, sizeof(struct hostent)); 323158115Sume memset(buffer, 0, desired_size); 324158115Sume 325158115Sume *buffer_size = desired_size; 326158115Sume p = buffer + sizeof(struct hostent) + sizeof(char *); 327158115Sume memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *)); 328158115Sume p = (char *)_ALIGN(p); 329158115Sume 330158115Sume if (new_ht.h_name != NULL) { 331158115Sume size = strlen(new_ht.h_name); 332158115Sume memcpy(p, new_ht.h_name, size); 333158115Sume new_ht.h_name = p; 334158115Sume p += size + 1; 335158115Sume } 336158115Sume 337158115Sume if (new_ht.h_aliases != NULL) { 338158115Sume p = (char *)_ALIGN(p); 339158115Sume memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size); 340158115Sume new_ht.h_aliases = (char **)p; 341158115Sume p += sizeof(char *) * (aliases_size + 1); 342158115Sume 343158115Sume for (iter = new_ht.h_aliases; *iter; ++iter) { 344158115Sume size = strlen(*iter); 345158115Sume memcpy(p, *iter, size); 346158115Sume *iter = p; 347158115Sume p += size + 1; 348158115Sume } 349158115Sume } 350158115Sume 351158115Sume if (new_ht.h_addr_list != NULL) { 352158115Sume p = (char *)_ALIGN(p); 353158115Sume memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size); 354158115Sume new_ht.h_addr_list = (char **)p; 355158115Sume p += sizeof(char *) * (addr_size + 1); 356158115Sume 357158115Sume size = _ALIGN(new_ht.h_length); 358158115Sume for (iter = new_ht.h_addr_list; *iter; ++iter) { 359158115Sume memcpy(p, *iter, size); 360158115Sume *iter = p; 361158115Sume p += size + 1; 362158115Sume } 363158115Sume } 364158115Sume memcpy(buffer, &new_ht, sizeof(struct hostent)); 365158115Sume return (NS_SUCCESS); 366158115Sume} 367158115Sume 368158115Sumestatic int 369158115Sumehost_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap, 370158115Sume void *cache_mdata) 371158115Sume{ 372158115Sume char *str; 373158791Sume void *addr; 374158791Sume socklen_t len; 375158791Sume int type; 376158115Sume struct hostent *ht; 377158115Sume 378158115Sume char *p; 379158115Sume char **iter; 380158115Sume char *orig_buf; 381158115Sume size_t orig_buf_size; 382158115Sume 383158115Sume switch ((enum nss_lookup_type)cache_mdata) { 384158115Sume case nss_lt_name: 385158115Sume str = va_arg(ap, char *); 386158115Sume type = va_arg(ap, int); 387158115Sume break; 388158115Sume case nss_lt_id: 389158791Sume addr = va_arg(ap, void *); 390158791Sume len = va_arg(ap, socklen_t); 391158115Sume type = va_arg(ap, int); 392158115Sume break; 393158115Sume default: 394158115Sume /* should be unreachable */ 395158115Sume return (NS_UNAVAIL); 396158115Sume } 397158115Sume 398158115Sume ht = va_arg(ap, struct hostent *); 399158115Sume orig_buf = va_arg(ap, char *); 400158115Sume orig_buf_size = va_arg(ap, size_t); 401158115Sume 402158115Sume if (orig_buf_size < 403158115Sume buffer_size - sizeof(struct hostent) - sizeof(char *)) { 404158115Sume errno = ERANGE; 405158115Sume return (NS_RETURN); 406158115Sume } 407158115Sume 408158115Sume memcpy(ht, buffer, sizeof(struct hostent)); 409158115Sume memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *)); 410158115Sume 411158115Sume orig_buf = (char *)_ALIGN(orig_buf); 412158115Sume memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) + 413158115Sume _ALIGN(p) - (size_t)p, 414158115Sume buffer_size - sizeof(struct hostent) - sizeof(char *) - 415158115Sume _ALIGN(p) + (size_t)p); 416158115Sume p = (char *)_ALIGN(p); 417158115Sume 418158115Sume NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *); 419158115Sume if (ht->h_aliases != NULL) { 420158115Sume NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **); 421158115Sume 422158115Sume for (iter = ht->h_aliases; *iter; ++iter) 423158115Sume NS_APPLY_OFFSET(*iter, orig_buf, p, char *); 424158115Sume } 425158115Sume 426158115Sume if (ht->h_addr_list != NULL) { 427158115Sume NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **); 428158115Sume 429158115Sume for (iter = ht->h_addr_list; *iter; ++iter) 430158115Sume NS_APPLY_OFFSET(*iter, orig_buf, p, char *); 431158115Sume } 432158115Sume 433158115Sume *((struct hostent **)retval) = ht; 434158115Sume return (NS_SUCCESS); 435158115Sume} 436158115Sume#endif /* NS_CACHING */ 437158115Sume 438158115Sumestatic int 439157779Sumefakeaddr(const char *name, int af, struct hostent *hp, char *buf, 440158115Sume size_t buflen, res_state statp) 441157779Sume{ 442157779Sume struct hostent_data *hed; 443157779Sume struct hostent he; 444157779Sume 445157779Sume if ((hed = __hostent_data_init()) == NULL) { 446157779Sume errno = ENOMEM; 447157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 448157779Sume return (-1); 449157779Sume } 450157779Sume 451157779Sume if ((af != AF_INET || 452157779Sume inet_aton(name, (struct in_addr *)hed->host_addr) != 1) && 453157779Sume inet_pton(af, name, hed->host_addr) != 1) { 454157779Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 455157779Sume return (-1); 456157779Sume } 457157779Sume strncpy(hed->hostbuf, name, MAXDNAME); 458157779Sume hed->hostbuf[MAXDNAME] = '\0'; 459157779Sume if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) { 460157779Sume _map_v4v6_address((char *)hed->host_addr, 461157779Sume (char *)hed->host_addr); 462157779Sume af = AF_INET6; 463157779Sume } 464157779Sume he.h_addrtype = af; 465157779Sume switch(af) { 466157779Sume case AF_INET: 467157779Sume he.h_length = NS_INADDRSZ; 468157779Sume break; 469157779Sume case AF_INET6: 470157779Sume he.h_length = NS_IN6ADDRSZ; 471157779Sume break; 472157779Sume default: 473157779Sume errno = EAFNOSUPPORT; 474157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 475157779Sume return (-1); 476157779Sume } 477157779Sume he.h_name = hed->hostbuf; 478157779Sume he.h_aliases = hed->host_aliases; 479157779Sume hed->host_aliases[0] = NULL; 480157779Sume hed->h_addr_ptrs[0] = (char *)hed->host_addr; 481157779Sume hed->h_addr_ptrs[1] = NULL; 482157779Sume he.h_addr_list = hed->h_addr_ptrs; 483211276Sume if (__copy_hostent(&he, hp, buf, buflen) != 0) { 484211276Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 485211276Sume return (-1); 486211276Sume } 487157779Sume RES_SET_H_ERRNO(statp, NETDB_SUCCESS); 488211276Sume return (0); 489157779Sume} 490157779Sume 491145633Sumeint 492157779Sumegethostbyname_r(const char *name, struct hostent *he, char *buffer, 493157779Sume size_t buflen, struct hostent **result, int *h_errnop) 494145633Sume{ 495157779Sume res_state statp; 496145633Sume 497157779Sume statp = __res_state(); 498157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 499157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 500157779Sume return (-1); 50167709Sume } 502157779Sume if (statp->options & RES_USE_INET6) { 503157779Sume if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) { 504157779Sume *result = he; 505157779Sume return (0); 506157779Sume } 507157779Sume if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen, 508157779Sume result, h_errnop, statp) == 0) 509157779Sume return (0); 510145512Sume } 511157779Sume return (gethostbyname_internal(name, AF_INET, he, buffer, buflen, 512157779Sume result, h_errnop, statp)); 51317903Speter} 51417903Speter 515145633Sumeint 516157779Sumegethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer, 517157779Sume size_t buflen, struct hostent **result, int *h_errnop) 51817903Speter{ 519157779Sume res_state statp; 520157779Sume 521157779Sume statp = __res_state(); 522157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 523157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 524157779Sume return (-1); 525145512Sume } 526157779Sume return (gethostbyname_internal(name, af, he, buffer, buflen, result, 527157779Sume h_errnop, statp)); 528145512Sume} 529145512Sume 530157779Sumeint 531157779Sumegethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf, 532157779Sume size_t buflen, struct hostent **result, int *h_errnop, res_state statp) 533145512Sume{ 534145512Sume const char *cp; 535211276Sume int rval, ret_errno = 0; 536145512Sume char abuf[MAXDNAME]; 5371991Swollman 538158115Sume#ifdef NS_CACHING 539158115Sume static const nss_cache_info cache_info = 540158115Sume NS_COMMON_CACHE_INFO_INITIALIZER( 541158115Sume hosts, (void *)nss_lt_name, 542158115Sume host_id_func, host_marshal_func, host_unmarshal_func); 543158115Sume#endif 54465532Snectar static const ns_dtab dtab[] = { 54565532Snectar NS_FILES_CB(_ht_gethostbyname, NULL) 54665532Snectar { NSSRC_DNS, _dns_gethostbyname, NULL }, 54765532Snectar NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ 548158115Sume#ifdef NS_CACHING 549158115Sume NS_CACHE_CB(&cache_info) 550158115Sume#endif 55165532Snectar { 0 } 552145512Sume }; 553145512Sume 554145512Sume switch (af) { 555145512Sume case AF_INET: 556145512Sume case AF_INET6: 557145512Sume break; 558145512Sume default: 559157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 560157779Sume *h_errnop = statp->res_h_errno; 561145512Sume errno = EAFNOSUPPORT; 562157779Sume return (-1); 563145512Sume } 564145512Sume 565145512Sume /* 566145512Sume * if there aren't any dots, it could be a user-level alias. 567145512Sume * this is also done in res_query() since we are not the only 568145512Sume * function that looks up host names. 569145512Sume */ 570145512Sume if (!strchr(name, '.') && 571157779Sume (cp = res_hostalias(statp, name, abuf, sizeof abuf))) 572145512Sume name = cp; 573145512Sume 574157779Sume if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) { 575157779Sume *result = hp; 576157779Sume return (0); 577157779Sume } 578145512Sume 579157779Sume rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, 580157779Sume "gethostbyname2_r", default_src, name, af, hp, buf, buflen, 581157779Sume &ret_errno, h_errnop); 5821991Swollman 583211276Sume if (rval != NS_SUCCESS) { 584211276Sume errno = ret_errno; 585211276Sume return ((ret_errno != 0) ? ret_errno : -1); 586211276Sume } 587211276Sume return (0); 5881991Swollman} 5891991Swollman 590145633Sumeint 591158791Sumegethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, 592158791Sume char *buf, size_t buflen, struct hostent **result, int *h_errnop) 5931991Swollman{ 594145687Sume const u_char *uaddr = (const u_char *)addr; 595145687Sume const struct in6_addr *addr6; 596145687Sume socklen_t size; 597211276Sume int rval, ret_errno = 0; 598157779Sume res_state statp; 5991991Swollman 600158115Sume#ifdef NS_CACHING 601158115Sume static const nss_cache_info cache_info = 602158115Sume NS_COMMON_CACHE_INFO_INITIALIZER( 603158115Sume hosts, (void *)nss_lt_id, 604158115Sume host_id_func, host_marshal_func, host_unmarshal_func); 605158115Sume#endif 60665532Snectar static const ns_dtab dtab[] = { 60765532Snectar NS_FILES_CB(_ht_gethostbyaddr, NULL) 60865532Snectar { NSSRC_DNS, _dns_gethostbyaddr, NULL }, 60965532Snectar NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ 610158115Sume#ifdef NS_CACHING 611158115Sume NS_CACHE_CB(&cache_info) 612158115Sume#endif 61365532Snectar { 0 } 614145633Sume }; 6151991Swollman 616157779Sume statp = __res_state(); 617157779Sume if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) { 618157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 619157779Sume *h_errnop = statp->res_h_errno; 620157779Sume return (-1); 621145728Sume } 622145728Sume 623157779Sume if (af == AF_INET6 && len == NS_IN6ADDRSZ) { 624158477Sume addr6 = (const struct in6_addr *)addr; 625145687Sume if (IN6_IS_ADDR_LINKLOCAL(addr6)) { 626157779Sume RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); 627157779Sume *h_errnop = statp->res_h_errno; 628157779Sume return (-1); 629145687Sume } 630145687Sume if (IN6_IS_ADDR_V4MAPPED(addr6) || 631145687Sume IN6_IS_ADDR_V4COMPAT(addr6)) { 632145687Sume /* Unmap. */ 633157779Sume uaddr += NS_IN6ADDRSZ - NS_INADDRSZ; 634145687Sume af = AF_INET; 635157779Sume len = NS_INADDRSZ; 636145687Sume } 637145687Sume } 638145687Sume switch (af) { 639145687Sume case AF_INET: 640157779Sume size = NS_INADDRSZ; 641145687Sume break; 642145687Sume case AF_INET6: 643157779Sume size = NS_IN6ADDRSZ; 644145687Sume break; 645145687Sume default: 646145687Sume errno = EAFNOSUPPORT; 647157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 648157779Sume *h_errnop = statp->res_h_errno; 649157779Sume return (-1); 650145687Sume } 651145687Sume if (size != len) { 652145687Sume errno = EINVAL; 653157779Sume RES_SET_H_ERRNO(statp, NETDB_INTERNAL); 654157779Sume *h_errnop = statp->res_h_errno; 655157779Sume return (-1); 656145687Sume } 657145687Sume 658157779Sume rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS, 659157779Sume "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen, 660157779Sume &ret_errno, h_errnop); 66165532Snectar 662211276Sume if (rval != NS_SUCCESS) { 663211276Sume errno = ret_errno; 664211276Sume return ((ret_errno != 0) ? ret_errno : -1); 665211276Sume } 666211276Sume return (0); 6671991Swollman} 6681991Swollman 669145633Sumestruct hostent * 670145633Sumegethostbyname(const char *name) 671145633Sume{ 672145633Sume struct hostdata *hd; 673157779Sume struct hostent *rval; 674157779Sume int ret_h_errno; 675145633Sume 676145633Sume if ((hd = __hostdata_init()) == NULL) 677157779Sume return (NULL); 678157779Sume if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval, 679157779Sume &ret_h_errno) != 0) 680157779Sume return (NULL); 681157779Sume return (rval); 682145633Sume} 683145633Sume 684145633Sumestruct hostent * 685145633Sumegethostbyname2(const char *name, int af) 686145633Sume{ 687145633Sume struct hostdata *hd; 688157779Sume struct hostent *rval; 689157779Sume int ret_h_errno; 690145633Sume 691145633Sume if ((hd = __hostdata_init()) == NULL) 692157779Sume return (NULL); 693157779Sume if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data), 694157779Sume &rval, &ret_h_errno) != 0) 695157779Sume return (NULL); 696157779Sume return (rval); 697145633Sume} 698145633Sume 699145633Sumestruct hostent * 700158477Sumegethostbyaddr(const void *addr, socklen_t len, int af) 701145633Sume{ 702145633Sume struct hostdata *hd; 703157779Sume struct hostent *rval; 704157779Sume int ret_h_errno; 705145633Sume 706145633Sume if ((hd = __hostdata_init()) == NULL) 707157779Sume return (NULL); 708157779Sume if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data, 709157779Sume sizeof(hd->data), &rval, &ret_h_errno) != 0) 710157779Sume return (NULL); 711157779Sume return (rval); 712145633Sume} 713145633Sume 714145633Sumevoid 715145633Sumesethostent(int stayopen) 716145633Sume{ 717157779Sume struct hostent_data *hed; 718145633Sume 719157779Sume if ((hed = __hostent_data_init()) == NULL) 720145633Sume return; 721157779Sume _sethosthtent(stayopen, hed); 722157779Sume _sethostdnsent(stayopen); 723145633Sume} 724145633Sume 725145633Sumevoid 726145633Sumeendhostent(void) 727145633Sume{ 728157779Sume struct hostent_data *hed; 729145633Sume 730157779Sume if ((hed = __hostent_data_init()) == NULL) 731145633Sume return; 732157779Sume _endhosthtent(hed); 733157779Sume _endhostdnsent(); 734145633Sume} 735