xref: /openbsd-src/lib/libc/asr/gethostnamadr.c (revision cd214be2c826f2ccad0f3aa1029e25d761d3ae3c)
1 /*	$OpenBSD: gethostnamadr.c,v 1.3 2013/04/01 07:47:26 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 #define PALIGN(p, l) \
30 	((char*)(p) + (((uintptr_t)(p) % (l)) ? \
31                 (l) - (uintptr_t)(p) % (l) : 0))
32 
33 static struct hostent *_gethostbyname(const char *, int);
34 static void _fillhostent(const struct hostent *, struct hostent *, char *buf,
35     size_t);
36 
37 static struct hostent	 _hostent;
38 static char		 _entbuf[4096];
39 
40 static char *_empty[] = { NULL, };
41 
42 static void
43 _fillhostent(const struct hostent *h, struct hostent *r, char *buf, size_t len)
44 {
45 	char	**ptr, *end, *pos;
46 	size_t	n, i;
47 	int	naliases, naddrs;
48 
49 	bzero(buf, len);
50 	bzero(r, sizeof(*r));
51 	r->h_aliases = _empty;
52 	r->h_addr_list = _empty;
53 
54 	end = buf + len;
55 	ptr = (char**)PALIGN(buf, sizeof(char*));
56 
57 	if ((char*)ptr >= end)
58 		return;
59 
60 	for (naliases = 0; h->h_aliases[naliases]; naliases++)
61 		;
62 	for (naddrs = 0; h->h_addr_list[naddrs]; naddrs++)
63 		;
64 
65 	pos = (char*)(ptr + (naliases + 1) + (naddrs + 1));
66 	if (pos >= end)
67 		return;
68 
69 	r->h_name = NULL;
70 	r->h_addrtype = h->h_addrtype;
71 	r->h_length = h->h_length;
72 	r->h_aliases = ptr;
73 	r->h_addr_list = ptr + naliases + 1;
74 
75 	n = strlcpy(pos, h->h_name, end - pos);
76 	if (n >= end - pos)
77 		return;
78 	r->h_name = pos;
79 	pos += n + 1;
80 
81 	for (i = 0; i < naliases; i++) {
82 		n = strlcpy(pos, h->h_aliases[i], end - pos);
83 		if (n >= end - pos)
84 			return;
85 		r->h_aliases[i] = pos;
86 		pos += n + 1;
87 	}
88 
89 	pos = PALIGN(pos, r->h_length);
90 	if (pos >= end)
91 		return;
92 
93 	for (i = 0; i < naddrs; i++) {
94 		if (r->h_length > end - pos)
95 			return;
96 		memmove(pos, h->h_addr_list[i], r->h_length);
97 		r->h_addr_list[i] = pos;
98 		pos += r->h_length;
99 	}
100 }
101 
102 static struct hostent *
103 _gethostbyname(const char *name, int af)
104 {
105 	struct async		*as;
106 	struct async_res	 ar;
107 
108 	if (af == -1)
109 		as = gethostbyname_async(name, NULL);
110 	else
111 		as = gethostbyname2_async(name, af, NULL);
112 
113 	if (as == NULL) {
114 		h_errno = NETDB_INTERNAL;
115 		return (NULL);
116 	}
117 
118 	async_run_sync(as, &ar);
119 
120 	errno = ar.ar_errno;
121 	h_errno = ar.ar_h_errno;
122 	if (ar.ar_hostent == NULL)
123 		return (NULL);
124 
125 	_fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf));
126 	free(ar.ar_hostent);
127 
128 	return (&_hostent);
129 }
130 
131 struct hostent *
132 gethostbyname(const char *name)
133 {
134 	return _gethostbyname(name, -1);
135 }
136 
137 struct hostent *
138 gethostbyname2(const char *name, int af)
139 {
140 	return _gethostbyname(name, af);
141 }
142 
143 struct hostent *
144 gethostbyaddr(const void *addr, socklen_t len, int af)
145 {
146 	struct async	*as;
147 	struct async_res ar;
148 
149 	as = gethostbyaddr_async(addr, len, af, NULL);
150 	if (as == NULL) {
151 		h_errno = NETDB_INTERNAL;
152 		return (NULL);
153 	}
154 
155 	async_run_sync(as, &ar);
156 
157 	errno = ar.ar_errno;
158 	h_errno = ar.ar_h_errno;
159 	if (ar.ar_hostent == NULL)
160 		return (NULL);
161 
162 	_fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf));
163 	free(ar.ar_hostent);
164 
165 	return (&_hostent);
166 }
167