gethostnamadr.c revision 145633
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: head/lib/libc/net/gethostnamadr.c 145633 2005-04-28 18:03:43Z ume $"); 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" 471573Srgrimes 4865532Snectarextern int _ht_gethostbyname(void *, void *, va_list); 4965532Snectarextern int _dns_gethostbyname(void *, void *, va_list); 5065532Snectarextern int _nis_gethostbyname(void *, void *, va_list); 5165532Snectarextern int _ht_gethostbyaddr(void *, void *, va_list); 5265532Snectarextern int _dns_gethostbyaddr(void *, void *, va_list); 5365532Snectarextern int _nis_gethostbyaddr(void *, void *, va_list); 54145512Sumeextern const char *_res_hostalias(const char *, char *, size_t); 551991Swollman 56145633Sumestatic int gethostbyname_internal(const char *, int, struct hostent *, 57145633Sume struct hostent_data *); 58145512Sume 5965532Snectar/* Host lookup order if nsswitch.conf is broken or nonexistant */ 60145512Sumestatic const ns_src default_src[] = { 6165532Snectar { NSSRC_FILES, NS_SUCCESS }, 6265532Snectar { NSSRC_DNS, NS_SUCCESS }, 6365532Snectar { 0 } 641991Swollman}; 651991Swollman 66145633Sumestatic struct hostdata hostdata; 67145633Sumestatic thread_key_t hostdata_key; 68145633Sumestatic once_t hostdata_init_once = ONCE_INITIALIZER; 69145633Sumestatic int hostdata_thr_keycreated = 0; 70145633Sume 71145633Sumestatic void 72145633Sumehostdata_free(void *ptr) 731991Swollman{ 74145633Sume struct hostdata *hd = ptr; 7517903Speter 76145633Sume if (hd == NULL) 77145633Sume return; 78145633Sume hd->data.stayopen = 0; 79145633Sume _endhosthtent(&hd->data); 80145633Sume free(hd); 81145633Sume} 82145633Sume 83145633Sumestatic void 84145633Sumehostdata_keycreate(void) 85145633Sume{ 86145633Sume hostdata_thr_keycreated = 87145633Sume (thr_keycreate(&hostdata_key, hostdata_free) == 0); 88145633Sume} 89145633Sume 90145633Sumestruct hostdata * 91145633Sume__hostdata_init(void) 92145633Sume{ 93145633Sume struct hostdata *hd; 94145633Sume 95145633Sume if (thr_main() != 0) 96145633Sume return &hostdata; 97145633Sume if (thr_once(&hostdata_init_once, hostdata_keycreate) != 0 || 98145633Sume !hostdata_thr_keycreated) 99145633Sume return NULL; 100145633Sume if ((hd = thr_getspecific(hostdata_key)) != NULL) 101145633Sume return hd; 102145633Sume if ((hd = calloc(1, sizeof(*hd))) == NULL) 103145633Sume return NULL; 104145633Sume if (thr_setspecific(hostdata_key, hd) == 0) 105145633Sume return hd; 106145633Sume free(hd); 107145633Sume return NULL; 108145633Sume} 109145633Sume 110145633Sumeint 111145633Sumegethostbyname_r(const char *name, struct hostent *he, struct hostent_data *hed) 112145633Sume{ 113145633Sume int error; 114145633Sume 11567709Sume if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 11667709Sume h_errno = NETDB_INTERNAL; 117145633Sume return -1; 11867709Sume } 119145512Sume if (_res.options & RES_USE_INET6) { 120145633Sume error = gethostbyname_internal(name, AF_INET6, he, hed); 121145633Sume if (error == 0) 122145633Sume return 0; 123145512Sume } 124145633Sume return gethostbyname_internal(name, AF_INET, he, hed); 12517903Speter} 12617903Speter 127145633Sumeint 128145633Sumegethostbyname2_r(const char *name, int af, struct hostent *he, 129145633Sume struct hostent_data *hed) 13017903Speter{ 131145512Sume if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 132145512Sume h_errno = NETDB_INTERNAL; 133145633Sume return -1; 134145512Sume } 135145633Sume return gethostbyname_internal(name, af, he, hed); 136145512Sume} 137145512Sume 138145633Sumestatic int 139145633Sumegethostbyname_internal(const char *name, int af, struct hostent *he, 140145633Sume struct hostent_data *hed) 141145512Sume{ 142145512Sume const char *cp; 143145512Sume char *bp, *ep; 144145512Sume int size, rval; 145145512Sume char abuf[MAXDNAME]; 1461991Swollman 14765532Snectar static const ns_dtab dtab[] = { 14865532Snectar NS_FILES_CB(_ht_gethostbyname, NULL) 14965532Snectar { NSSRC_DNS, _dns_gethostbyname, NULL }, 15065532Snectar NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ 15165532Snectar { 0 } 152145512Sume }; 153145512Sume 154145512Sume switch (af) { 155145512Sume case AF_INET: 156145512Sume size = INADDRSZ; 157145512Sume break; 158145512Sume case AF_INET6: 159145512Sume size = IN6ADDRSZ; 160145512Sume break; 161145512Sume default: 162145512Sume h_errno = NETDB_INTERNAL; 163145512Sume errno = EAFNOSUPPORT; 164145633Sume return -1; 165145512Sume } 166145512Sume 167145633Sume he->h_addrtype = af; 168145633Sume he->h_length = size; 169145512Sume 170145512Sume /* 171145512Sume * if there aren't any dots, it could be a user-level alias. 172145512Sume * this is also done in res_query() since we are not the only 173145512Sume * function that looks up host names. 174145512Sume */ 175145512Sume if (!strchr(name, '.') && 176145512Sume (cp = _res_hostalias(name, abuf, sizeof abuf))) 177145512Sume name = cp; 178145512Sume 179145512Sume /* 180145512Sume * disallow names consisting only of digits/dots, unless 181145512Sume * they end in a dot. 182145512Sume */ 183145512Sume if (isdigit((u_char)name[0])) 184145512Sume for (cp = name;; ++cp) { 185145512Sume if (!*cp) { 186145512Sume if (*--cp == '.') 187145512Sume break; 188145512Sume /* 189145512Sume * All-numeric, no dot at the end. 190145512Sume * Fake up a hostent as if we'd actually 191145512Sume * done a lookup. 192145512Sume */ 193145633Sume if (inet_pton(af, name, hed->host_addr) <= 0) { 194145512Sume h_errno = HOST_NOT_FOUND; 195145633Sume return -1; 196145512Sume } 197145633Sume strncpy(hed->hostbuf, name, MAXDNAME); 198145633Sume hed->hostbuf[MAXDNAME] = '\0'; 199145633Sume bp = hed->hostbuf + MAXDNAME + 1; 200145633Sume ep = hed->hostbuf + sizeof hed->hostbuf; 201145633Sume he->h_name = hed->hostbuf; 202145633Sume he->h_aliases = hed->host_aliases; 203145633Sume hed->host_aliases[0] = NULL; 204145633Sume hed->h_addr_ptrs[0] = (char *)hed->host_addr; 205145633Sume hed->h_addr_ptrs[1] = NULL; 206145633Sume he->h_addr_list = hed->h_addr_ptrs; 207145512Sume if (_res.options & RES_USE_INET6) 208145633Sume _map_v4v6_hostent(he, &bp, &ep); 209145512Sume h_errno = NETDB_SUCCESS; 210145633Sume return 0; 211145512Sume } 212145512Sume if (!isdigit((u_char)*cp) && *cp != '.') 213145512Sume break; 214145512Sume } 215145512Sume if ((isxdigit((u_char)name[0]) && strchr(name, ':') != NULL) || 216145512Sume name[0] == ':') 217145512Sume for (cp = name;; ++cp) { 218145512Sume if (!*cp) { 219145512Sume if (*--cp == '.') 220145512Sume break; 221145512Sume /* 222145512Sume * All-IPv6-legal, no dot at the end. 223145512Sume * Fake up a hostent as if we'd actually 224145512Sume * done a lookup. 225145512Sume */ 226145633Sume if (inet_pton(af, name, hed->host_addr) <= 0) { 227145512Sume h_errno = HOST_NOT_FOUND; 228145633Sume return -1; 229145512Sume } 230145633Sume strncpy(hed->hostbuf, name, MAXDNAME); 231145633Sume hed->hostbuf[MAXDNAME] = '\0'; 232145633Sume he->h_name = hed->hostbuf; 233145633Sume he->h_aliases = hed->host_aliases; 234145633Sume hed->host_aliases[0] = NULL; 235145633Sume hed->h_addr_ptrs[0] = (char *)hed->host_addr; 236145633Sume hed->h_addr_ptrs[1] = NULL; 237145633Sume he->h_addr_list = hed->h_addr_ptrs; 238145512Sume h_errno = NETDB_SUCCESS; 239145633Sume return 0; 240145512Sume } 241145512Sume if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.') 242145512Sume break; 243145512Sume } 244145512Sume 245145633Sume rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyname", 246145633Sume default_src, name, af, he, hed); 2471991Swollman 248145633Sume return (rval == NS_SUCCESS) ? 0 : -1; 2491991Swollman} 2501991Swollman 251145633Sumeint 252145633Sumegethostbyaddr_r(const char *addr, int len, int af, struct hostent *he, 253145633Sume struct hostent_data *hed) 2541991Swollman{ 25565532Snectar int rval; 2561991Swollman 25765532Snectar static const ns_dtab dtab[] = { 25865532Snectar NS_FILES_CB(_ht_gethostbyaddr, NULL) 25965532Snectar { NSSRC_DNS, _dns_gethostbyaddr, NULL }, 26065532Snectar NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */ 26165532Snectar { 0 } 262145633Sume }; 2631991Swollman 264145633Sume rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr", 265145633Sume default_src, addr, len, af, he, hed); 26665532Snectar 267145633Sume return (rval == NS_SUCCESS) ? 0 : -1; 2681991Swollman} 2691991Swollman 2703070Spstvoid 271145633Sumesethostent_r(int stayopen, struct hostent_data *hed) 2723070Spst{ 273145633Sume _sethosthtent(stayopen, hed); 2743070Spst _sethostdnsent(stayopen); 2753070Spst} 2763070Spst 2773070Spstvoid 278145633Sumeendhostent_r(struct hostent_data *hed) 2793070Spst{ 280145633Sume _endhosthtent(hed); 2813070Spst _endhostdnsent(); 2823070Spst} 283145633Sume 284145633Sumestruct hostent * 285145633Sumegethostbyname(const char *name) 286145633Sume{ 287145633Sume struct hostdata *hd; 288145633Sume 289145633Sume if ((hd = __hostdata_init()) == NULL) 290145633Sume return NULL; 291145633Sume if (gethostbyname_r(name, &hd->host, &hd->data) != 0) 292145633Sume return NULL; 293145633Sume return &hd->host; 294145633Sume} 295145633Sume 296145633Sumestruct hostent * 297145633Sumegethostbyname2(const char *name, int af) 298145633Sume{ 299145633Sume struct hostdata *hd; 300145633Sume 301145633Sume if ((hd = __hostdata_init()) == NULL) 302145633Sume return NULL; 303145633Sume if (gethostbyname2_r(name, af, &hd->host, &hd->data) != 0) 304145633Sume return NULL; 305145633Sume return &hd->host; 306145633Sume} 307145633Sume 308145633Sumestruct hostent * 309145633Sumegethostbyaddr(const char *addr, int len, int af) 310145633Sume{ 311145633Sume struct hostdata *hd; 312145633Sume 313145633Sume if ((hd = __hostdata_init()) == NULL) 314145633Sume return NULL; 315145633Sume if (gethostbyaddr_r(addr, len, af, &hd->host, &hd->data) != 0) 316145633Sume return NULL; 317145633Sume return &hd->host; 318145633Sume} 319145633Sume 320145633Sumevoid 321145633Sumesethostent(int stayopen) 322145633Sume{ 323145633Sume struct hostdata *hd; 324145633Sume 325145633Sume if ((hd = __hostdata_init()) == NULL) 326145633Sume return; 327145633Sume sethostent_r(stayopen, &hd->data); 328145633Sume} 329145633Sume 330145633Sumevoid 331145633Sumeendhostent(void) 332145633Sume{ 333145633Sume struct hostdata *hd; 334145633Sume 335145633Sume if ((hd = __hostdata_init()) == NULL) 336145633Sume return; 337145633Sume endhostent_r(&hd->data); 338145633Sume} 339