xref: /openbsd-src/lib/libc/asr/gethostnamadr.c (revision 1ed934d0d08bf9c3f460e8740d169e7606f8702f)
1 /*	$OpenBSD: gethostnamadr.c,v 1.7 2013/05/27 17:31:01 eric Exp $	*/
2 /*
3  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/types.h>
19 #include <netinet/in.h>
20 
21 #include <errno.h>
22 #include <resolv.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "asr.h"
28 
29 static struct hostent *_gethostbyname(const char *, int);
30 static void _fillhostent(const struct hostent *, struct hostent *, char *buf,
31     size_t);
32 
33 static struct hostent	 _hostent;
34 static char		 _entbuf[4096];
35 
36 static char *_empty[] = { NULL, };
37 
38 static void
39 _fillhostent(const struct hostent *h, struct hostent *r, char *buf, size_t len)
40 {
41 	char	**ptr, *end, *pos;
42 	size_t	n, i;
43 	int	naliases, naddrs;
44 
45 	bzero(buf, len);
46 	bzero(r, sizeof(*r));
47 	r->h_aliases = _empty;
48 	r->h_addr_list = _empty;
49 
50 	end = buf + len;
51 	ptr = (char **)ALIGN(buf);
52 
53 	if ((char *)ptr >= end)
54 		return;
55 
56 	for (naliases = 0; h->h_aliases[naliases]; naliases++)
57 		;
58 	for (naddrs = 0; h->h_addr_list[naddrs]; naddrs++)
59 		;
60 
61 	pos = (char *)(ptr + (naliases + 1) + (naddrs + 1));
62 	if (pos >= end)
63 		return;
64 
65 	r->h_name = NULL;
66 	r->h_addrtype = h->h_addrtype;
67 	r->h_length = h->h_length;
68 	r->h_aliases = ptr;
69 	r->h_addr_list = ptr + naliases + 1;
70 
71 	n = strlcpy(pos, h->h_name, end - pos);
72 	if (n >= end - pos)
73 		return;
74 	r->h_name = pos;
75 	pos += n + 1;
76 
77 	for (i = 0; i < naliases; i++) {
78 		n = strlcpy(pos, h->h_aliases[i], end - pos);
79 		if (n >= end - pos)
80 			return;
81 		r->h_aliases[i] = pos;
82 		pos += n + 1;
83 	}
84 
85 	pos = (char *)ALIGN(pos);
86 	if (pos >= end)
87 		return;
88 
89 	for (i = 0; i < naddrs; i++) {
90 		if (r->h_length > end - pos)
91 			return;
92 		memmove(pos, h->h_addr_list[i], r->h_length);
93 		r->h_addr_list[i] = pos;
94 		pos += r->h_length;
95 	}
96 }
97 
98 static struct hostent *
99 _gethostbyname(const char *name, int af)
100 {
101 	struct async		*as;
102 	struct async_res	 ar;
103 
104 	if (af == -1)
105 		as = gethostbyname_async(name, NULL);
106 	else
107 		as = gethostbyname2_async(name, af, NULL);
108 
109 	if (as == NULL) {
110 		h_errno = NETDB_INTERNAL;
111 		return (NULL);
112 	}
113 
114 	async_run_sync(as, &ar);
115 
116 	errno = ar.ar_errno;
117 	h_errno = ar.ar_h_errno;
118 	if (ar.ar_hostent == NULL)
119 		return (NULL);
120 
121 	_fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf));
122 	free(ar.ar_hostent);
123 
124 	return (&_hostent);
125 }
126 
127 struct hostent *
128 gethostbyname(const char *name)
129 {
130 	struct hostent	*h;
131 
132 	res_init();
133 
134 	if (_res.options & RES_USE_INET6 &&
135 	    (h = _gethostbyname(name, AF_INET6)))
136 			return (h);
137 
138 	return _gethostbyname(name, AF_INET);
139 }
140 
141 struct hostent *
142 gethostbyname2(const char *name, int af)
143 {
144 	res_init();
145 
146 	return _gethostbyname(name, af);
147 }
148 
149 struct hostent *
150 gethostbyaddr(const void *addr, socklen_t len, int af)
151 {
152 	struct async	*as;
153 	struct async_res ar;
154 
155 	res_init();
156 
157 	as = gethostbyaddr_async(addr, len, af, NULL);
158 	if (as == NULL) {
159 		h_errno = NETDB_INTERNAL;
160 		return (NULL);
161 	}
162 
163 	async_run_sync(as, &ar);
164 
165 	errno = ar.ar_errno;
166 	h_errno = ar.ar_h_errno;
167 	if (ar.ar_hostent == NULL)
168 		return (NULL);
169 
170 	_fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf));
171 	free(ar.ar_hostent);
172 
173 	return (&_hostent);
174 }
175