2 * Copyright (c) 1994, Garrett Wollman
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include "namespace.h"
30 #include "reentrant.h"
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
43 #include <arpa/nameser.h> /* XXX hack for _res */
44 #include <resolv.h> /* XXX hack for _res */
45 #include "un-namespace.h"
46 #include "netdb_private.h"
48 extern int _ht_gethostbyname(void *, void *, va_list);
49 extern int _dns_gethostbyname(void *, void *, va_list);
50 extern int _nis_gethostbyname(void *, void *, va_list);
51 extern int _ht_gethostbyaddr(void *, void *, va_list);
52 extern int _dns_gethostbyaddr(void *, void *, va_list);
53 extern int _nis_gethostbyaddr(void *, void *, va_list);
54 extern const char *_res_hostalias(const char *, char *, size_t);
56 static int gethostbyname_internal(const char *, int, struct hostent *,
57 struct hostent_data *);
59 /* Host lookup order if nsswitch.conf is broken or nonexistant */
60 static const ns_src default_src[] = {
61 { NSSRC_FILES, NS_SUCCESS },
62 { NSSRC_DNS, NS_SUCCESS },
66 static struct hostdata hostdata;
67 static thread_key_t hostdata_key;
68 static once_t hostdata_init_once = ONCE_INITIALIZER;
69 static int hostdata_thr_keycreated = 0;
72 hostdata_free(void *ptr)
74 struct hostdata *hd = ptr;
78 hd->data.stayopen = 0;
79 _endhosthtent(&hd->data);
84 hostdata_keycreate(void)
86 hostdata_thr_keycreated =
87 (thr_keycreate(&hostdata_key, hostdata_free) == 0);
97 if (thr_once(&hostdata_init_once, hostdata_keycreate) != 0 ||
98 !hostdata_thr_keycreated)
100 if ((hd = thr_getspecific(hostdata_key)) != NULL)
102 if ((hd = calloc(1, sizeof(*hd))) == NULL)
104 if (thr_setspecific(hostdata_key, hd) == 0)
111 gethostbyname_r(const char *name, struct hostent *he, struct hostent_data *hed)
115 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
116 h_errno = NETDB_INTERNAL;
119 if (_res.options & RES_USE_INET6) {
120 error = gethostbyname_internal(name, AF_INET6, he, hed);
124 return gethostbyname_internal(name, AF_INET, he, hed);
128 gethostbyname2_r(const char *name, int af, struct hostent *he,
129 struct hostent_data *hed)
131 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
132 h_errno = NETDB_INTERNAL;
135 return gethostbyname_internal(name, af, he, hed);
139 gethostbyname_internal(const char *name, int af, struct hostent *he,
140 struct hostent_data *hed)
147 static const ns_dtab dtab[] = {
148 NS_FILES_CB(_ht_gethostbyname, NULL)
149 { NSSRC_DNS, _dns_gethostbyname, NULL },
150 NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
162 h_errno = NETDB_INTERNAL;
163 errno = EAFNOSUPPORT;
171 * if there aren't any dots, it could be a user-level alias.
172 * this is also done in res_query() since we are not the only
173 * function that looks up host names.
175 if (!strchr(name, '.') &&
176 (cp = _res_hostalias(name, abuf, sizeof abuf)))
180 * disallow names consisting only of digits/dots, unless
183 if (isdigit((u_char)name[0]))
184 for (cp = name;; ++cp) {
189 * All-numeric, no dot at the end.
190 * Fake up a hostent as if we'd actually
193 if (inet_pton(af, name, hed->host_addr) <= 0) {
194 h_errno = HOST_NOT_FOUND;
197 strncpy(hed->hostbuf, name, MAXDNAME);
198 hed->hostbuf[MAXDNAME] = '\0';
199 bp = hed->hostbuf + MAXDNAME + 1;
200 ep = hed->hostbuf + sizeof hed->hostbuf;
201 he->h_name = hed->hostbuf;
202 he->h_aliases = hed->host_aliases;
203 hed->host_aliases[0] = NULL;
204 hed->h_addr_ptrs[0] = (char *)hed->host_addr;
205 hed->h_addr_ptrs[1] = NULL;
206 he->h_addr_list = hed->h_addr_ptrs;
207 if (_res.options & RES_USE_INET6)
208 _map_v4v6_hostent(he, &bp, ep);
209 h_errno = NETDB_SUCCESS;
212 if (!isdigit((u_char)*cp) && *cp != '.')
215 if ((isxdigit((u_char)name[0]) && strchr(name, ':') != NULL) ||
217 for (cp = name;; ++cp) {
222 * All-IPv6-legal, no dot at the end.
223 * Fake up a hostent as if we'd actually
226 if (inet_pton(af, name, hed->host_addr) <= 0) {
227 h_errno = HOST_NOT_FOUND;
230 strncpy(hed->hostbuf, name, MAXDNAME);
231 hed->hostbuf[MAXDNAME] = '\0';
232 he->h_name = hed->hostbuf;
233 he->h_aliases = hed->host_aliases;
234 hed->host_aliases[0] = NULL;
235 hed->h_addr_ptrs[0] = (char *)hed->host_addr;
236 hed->h_addr_ptrs[1] = NULL;
237 he->h_addr_list = hed->h_addr_ptrs;
238 h_errno = NETDB_SUCCESS;
241 if (!isxdigit((u_char)*cp) && *cp != ':' && *cp != '.')
245 rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyname",
246 default_src, name, af, he, hed);
248 return (rval == NS_SUCCESS) ? 0 : -1;
252 gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
253 struct hostent_data *hed)
255 const u_char *uaddr = (const u_char *)addr;
256 const struct in6_addr *addr6;
260 static const ns_dtab dtab[] = {
261 NS_FILES_CB(_ht_gethostbyaddr, NULL)
262 { NSSRC_DNS, _dns_gethostbyaddr, NULL },
263 NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
267 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
268 h_errno = NETDB_INTERNAL;
272 if (af == AF_INET6 && len == IN6ADDRSZ) {
273 addr6 = (const struct in6_addr *)(const void *)uaddr;
274 if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
275 h_errno = HOST_NOT_FOUND;
278 if (IN6_IS_ADDR_V4MAPPED(addr6) ||
279 IN6_IS_ADDR_V4COMPAT(addr6)) {
281 uaddr += IN6ADDRSZ - INADDRSZ;
294 errno = EAFNOSUPPORT;
295 h_errno = NETDB_INTERNAL;
300 h_errno = NETDB_INTERNAL;
304 rval = _nsdispatch(NULL, dtab, NSDB_HOSTS, "gethostbyaddr",
305 default_src, uaddr, len, af, he, hed);
307 return (rval == NS_SUCCESS) ? 0 : -1;
311 sethostent_r(int stayopen, struct hostent_data *hed)
313 _sethosthtent(stayopen, hed);
314 _sethostdnsent(stayopen);
318 endhostent_r(struct hostent_data *hed)
325 gethostbyname(const char *name)
329 if ((hd = __hostdata_init()) == NULL)
331 if (gethostbyname_r(name, &hd->host, &hd->data) != 0)
337 gethostbyname2(const char *name, int af)
341 if ((hd = __hostdata_init()) == NULL)
343 if (gethostbyname2_r(name, af, &hd->host, &hd->data) != 0)
349 gethostbyaddr(const char *addr, int len, int af)
353 if ((hd = __hostdata_init()) == NULL)
355 if (gethostbyaddr_r(addr, len, af, &hd->host, &hd->data) != 0)
361 sethostent(int stayopen)
365 if ((hd = __hostdata_init()) == NULL)
367 sethostent_r(stayopen, &hd->data);
375 if ((hd = __hostdata_init()) == NULL)
377 endhostent_r(&hd->data);