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