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
25 * $FreeBSD: src/lib/libc/net/gethostnamadr.c,v 1.15.2.2 2001/03/05 10:40:42 obrien Exp $
26 * $DragonFly: src/lib/libc/net/gethostnamadr.c,v 1.6 2007/12/29 22:55:29 matthias Exp $
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
39 #include <arpa/nameser.h> /* XXX hack for _res */
40 #include <resolv.h> /* XXX hack for _res */
45 extern int _ht_gethostbyname(void *, void *, va_list);
46 extern int _dns_gethostbyname(void *, void *, va_list);
47 extern int _nis_gethostbyname(void *, void *, va_list);
48 extern int _ht_gethostbyaddr(void *, void *, va_list);
49 extern int _dns_gethostbyaddr(void *, void *, va_list);
50 extern int _nis_gethostbyaddr(void *, void *, va_list);
52 /* Host lookup order if nsswitch.conf is broken or nonexistant */
53 static const ns_src default_src[] = {
54 { NSSRC_FILES, NS_SUCCESS },
55 { NSSRC_DNS, NS_SUCCESS },
59 static int host_id_func(char *, size_t *, va_list, void *);
60 static int host_marshal_func(char *, size_t *, void *, va_list, void *);
61 static int host_unmarshal_func(char *, size_t, void *, va_list, void *);
65 gethostbyname(const char *name)
69 if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
70 h_errno = NETDB_INTERNAL;
73 if (_res.options & RES_USE_INET6) { /* XXX */
74 hp = gethostbyname2(name, AF_INET6); /* XXX */
76 return (hp); /* XXX */
78 return (gethostbyname2(name, AF_INET));
82 gethostbyname2(const char *name, int type)
84 struct hostent *hp = 0;
88 static const nss_cache_info cache_info =
89 NS_COMMON_CACHE_INFO_INITIALIZER(
90 hosts, (void *)nss_lt_name,
91 host_id_func, host_marshal_func, host_unmarshal_func);
93 static const ns_dtab dtab[] = {
94 NS_FILES_CB(_ht_gethostbyname, NULL)
95 { NSSRC_DNS, _dns_gethostbyname, NULL },
96 NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
98 NS_CACHE_CB(&cache_info)
103 rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname",
104 default_src, name, type);
106 if (rval != NS_SUCCESS)
113 gethostbyaddr(const void *addr, socklen_t len, int type)
115 struct hostent *hp = 0;
119 static const nss_cache_info cache_info =
120 NS_COMMON_CACHE_INFO_INITIALIZER(
121 hosts, (void *)nss_lt_id,
122 host_id_func, host_marshal_func, host_unmarshal_func);
124 static const ns_dtab dtab[] = {
125 NS_FILES_CB(_ht_gethostbyaddr, NULL)
126 { NSSRC_DNS, _dns_gethostbyaddr, NULL },
127 NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
129 NS_CACHE_CB(&cache_info)
134 rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
135 default_src, addr, len, type);
137 if (rval != NS_SUCCESS)
145 host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
154 size_t desired_size, size;
155 enum nss_lookup_type lookup_type;
157 int res = NS_UNAVAIL;
159 statp = __res_state();
160 res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
161 RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
163 lookup_type = (enum nss_lookup_type)cache_mdata;
164 switch (lookup_type) {
166 str = va_arg(ap, char *);
167 type = va_arg(ap, int);
170 desired_size = sizeof(res_options) + sizeof(int) +
171 sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
173 if (desired_size > *buffer_size) {
180 memcpy(p, &res_options, sizeof(res_options));
181 p += sizeof(res_options);
183 memcpy(p, &op_id, sizeof(int));
186 memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
189 memcpy(p, &type, sizeof(int));
192 memcpy(p, str, size + 1);
197 str = va_arg(ap, char *);
198 len = va_arg(ap, int);
199 type = va_arg(ap, int);
201 desired_size = sizeof(res_options) + sizeof(int) +
202 sizeof(enum nss_lookup_type) + sizeof(int) * 2 + len;
204 if (desired_size > *buffer_size) {
210 memcpy(p, &res_options, sizeof(res_options));
211 p += sizeof(res_options);
213 memcpy(p, &op_id, sizeof(int));
216 memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
219 memcpy(p, &type, sizeof(int));
222 memcpy(p, &len, sizeof(int));
230 /* should be unreachable */
235 *buffer_size = desired_size;
240 host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
247 struct hostent new_ht;
248 size_t desired_size, aliases_size, addr_size, size;
251 switch ((enum nss_lookup_type)cache_mdata) {
253 str = va_arg(ap, char *);
254 type = va_arg(ap, int);
257 str = va_arg(ap, char *);
258 len = va_arg(ap, int);
259 type = va_arg(ap, int);
262 /* should be unreachable */
265 ht = va_arg(ap, struct hostent *);
267 desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
268 if (ht->h_name != NULL)
269 desired_size += strlen(ht->h_name) + 1;
271 if (ht->h_aliases != NULL) {
273 for (iter = ht->h_aliases; *iter; ++iter) {
274 desired_size += strlen(*iter) + 1;
278 desired_size += _ALIGNBYTES +
279 (aliases_size + 1) * sizeof(char *);
282 if (ht->h_addr_list != NULL) {
284 for (iter = ht->h_addr_list; *iter; ++iter)
287 desired_size += addr_size * _ALIGN(ht->h_length);
288 desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
291 if (desired_size > *buffer_size) {
292 /* this assignment is here for future use */
293 *buffer_size = desired_size;
297 memcpy(&new_ht, ht, sizeof(struct hostent));
298 memset(buffer, 0, desired_size);
300 *buffer_size = desired_size;
301 p = buffer + sizeof(struct hostent) + sizeof(char *);
302 memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
303 p = (char *)_ALIGN(p);
305 if (new_ht.h_name != NULL) {
306 size = strlen(new_ht.h_name);
307 memcpy(p, new_ht.h_name, size);
312 if (new_ht.h_aliases != NULL) {
313 p = (char *)_ALIGN(p);
314 memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
315 new_ht.h_aliases = (char **)p;
316 p += sizeof(char *) * (aliases_size + 1);
318 for (iter = new_ht.h_aliases; *iter; ++iter) {
319 size = strlen(*iter);
320 memcpy(p, *iter, size);
326 if (new_ht.h_addr_list != NULL) {
327 p = (char *)_ALIGN(p);
328 memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
329 new_ht.h_addr_list = (char **)p;
330 p += sizeof(char *) * (addr_size + 1);
332 size = _ALIGN(new_ht.h_length);
333 for (iter = new_ht.h_addr_list; *iter; ++iter) {
334 memcpy(p, *iter, size);
339 memcpy(buffer, &new_ht, sizeof(struct hostent));
344 host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
354 size_t orig_buf_size;
356 switch ((enum nss_lookup_type)cache_mdata) {
358 str = va_arg(ap, char *);
359 type = va_arg(ap, int);
362 str = va_arg(ap, char *);
363 len = va_arg(ap, int);
364 type = va_arg(ap, int);
367 /* should be unreachable */
371 ht = va_arg(ap, struct hostent *);
372 orig_buf = va_arg(ap, char *);
373 orig_buf_size = va_arg(ap, size_t);
376 buffer_size - sizeof(struct hostent) - sizeof(char *)) {
381 memcpy(ht, buffer, sizeof(struct hostent));
382 memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
384 orig_buf = (char *)_ALIGN(orig_buf);
385 memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) +
386 _ALIGN(p) - (size_t)p,
387 buffer_size - sizeof(struct hostent) - sizeof(char *) -
388 _ALIGN(p) + (size_t)p);
389 p = (char *)_ALIGN(p);
391 NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
392 if (ht->h_aliases != NULL) {
393 NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
395 for (iter = ht->h_aliases; *iter; ++iter)
396 NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
399 if (ht->h_addr_list != NULL) {
400 NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
402 for (iter = ht->h_addr_list; *iter; ++iter)
403 NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
406 *((struct hostent **)retval) = ht;
409 #endif /* NS_CACHING */
412 sethostent(int stayopen)
414 _sethosthtent(stayopen);
415 _sethostdnsent(stayopen);