xref: /openbsd-src/lib/libc/asr/gethostnamadr.c (revision 06201dd4d8b19e0383322797ffab28e23bd09e0e)
1*06201dd4Sguenther /*	$OpenBSD: gethostnamadr.c,v 1.13 2015/09/14 07:38:37 guenther Exp $	*/
28082e013Seric /*
3f5615e53Seric  * Copyright (c) 2012,2013 Eric Faurot <eric@openbsd.org>
48082e013Seric  *
58082e013Seric  * Permission to use, copy, modify, and distribute this software for any
68082e013Seric  * purpose with or without fee is hereby granted, provided that the above
78082e013Seric  * copyright notice and this permission notice appear in all copies.
88082e013Seric  *
98082e013Seric  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
108082e013Seric  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
118082e013Seric  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
128082e013Seric  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
138082e013Seric  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
148082e013Seric  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
158082e013Seric  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
168082e013Seric  */
178082e013Seric 
18aea60beeSderaadt #include <sys/param.h>	/* ALIGN */
198082e013Seric #include <sys/types.h>
20d216d6b1Seric #include <sys/socket.h>
218082e013Seric #include <netinet/in.h>
22d216d6b1Seric #include <netdb.h>
238082e013Seric 
24d216d6b1Seric #include <asr.h>
258082e013Seric #include <errno.h>
268082e013Seric #include <resolv.h>
27cd214be2Seric #include <stdint.h>
288082e013Seric #include <stdlib.h>
298082e013Seric #include <string.h>
308082e013Seric 
31f5615e53Seric static int _gethostbyname(const char *, int, struct hostent *, char *, size_t,
32f5615e53Seric     int *);
33f5615e53Seric static int _fillhostent(const struct hostent *, struct hostent *, char *,
348082e013Seric     size_t);
358082e013Seric 
368082e013Seric static struct hostent	 _hostent;
378082e013Seric static char		 _entbuf[4096];
388082e013Seric 
398082e013Seric static char *_empty[] = { NULL, };
408082e013Seric 
41f5615e53Seric static int
_fillhostent(const struct hostent * h,struct hostent * r,char * buf,size_t len)428082e013Seric _fillhostent(const struct hostent *h, struct hostent *r, char *buf, size_t len)
438082e013Seric {
448082e013Seric 	char	**ptr, *end, *pos;
458082e013Seric 	size_t	n, i;
468082e013Seric 	int	naliases, naddrs;
478082e013Seric 
48cd214be2Seric 	bzero(buf, len);
49cd214be2Seric 	bzero(r, sizeof(*r));
50cd214be2Seric 	r->h_aliases = _empty;
51cd214be2Seric 	r->h_addr_list = _empty;
52cd214be2Seric 
538082e013Seric 	end = buf + len;
546a7aae72Seric 	ptr = (char **)ALIGN(buf);
55cd214be2Seric 
56cd214be2Seric 	if ((char *)ptr >= end)
57f5615e53Seric 		return (ERANGE);
588082e013Seric 
598082e013Seric 	for (naliases = 0; h->h_aliases[naliases]; naliases++)
608082e013Seric 		;
618082e013Seric 	for (naddrs = 0; h->h_addr_list[naddrs]; naddrs++)
628082e013Seric 		;
638082e013Seric 
64cd214be2Seric 	pos = (char *)(ptr + (naliases + 1) + (naddrs + 1));
65cd214be2Seric 	if (pos >= end)
66f5615e53Seric 		return (ERANGE);
67cd214be2Seric 
688082e013Seric 	r->h_name = NULL;
698082e013Seric 	r->h_addrtype = h->h_addrtype;
708082e013Seric 	r->h_length = h->h_length;
718082e013Seric 	r->h_aliases = ptr;
728082e013Seric 	r->h_addr_list = ptr + naliases + 1;
738082e013Seric 
748082e013Seric 	n = strlcpy(pos, h->h_name, end - pos);
758082e013Seric 	if (n >= end - pos)
76f5615e53Seric 		return (ERANGE);
778082e013Seric 	r->h_name = pos;
788082e013Seric 	pos += n + 1;
798082e013Seric 
808082e013Seric 	for (i = 0; i < naliases; i++) {
818082e013Seric 		n = strlcpy(pos, h->h_aliases[i], end - pos);
828082e013Seric 		if (n >= end - pos)
83f5615e53Seric 			return (ERANGE);
848082e013Seric 		r->h_aliases[i] = pos;
858082e013Seric 		pos += n + 1;
868082e013Seric 	}
878082e013Seric 
886a7aae72Seric 	pos = (char *)ALIGN(pos);
89cd214be2Seric 	if (pos >= end)
90f5615e53Seric 		return (ERANGE);
91cd214be2Seric 
928082e013Seric 	for (i = 0; i < naddrs; i++) {
938082e013Seric 		if (r->h_length > end - pos)
94f5615e53Seric 			return (ERANGE);
958082e013Seric 		memmove(pos, h->h_addr_list[i], r->h_length);
968082e013Seric 		r->h_addr_list[i] = pos;
978082e013Seric 		pos += r->h_length;
988082e013Seric 	}
99f5615e53Seric 
100f5615e53Seric 	return (0);
1018082e013Seric }
1028082e013Seric 
103f5615e53Seric static int
_gethostbyname(const char * name,int af,struct hostent * ret,char * buf,size_t buflen,int * h_errnop)104f5615e53Seric _gethostbyname(const char *name, int af, struct hostent *ret, char *buf,
105f5615e53Seric     size_t buflen, int *h_errnop)
1068082e013Seric {
1075be03f8fSeric 	struct asr_query *as;
1085be03f8fSeric 	struct asr_result ar;
109f5615e53Seric 	int r;
1108082e013Seric 
1118082e013Seric 	if (af == -1)
1128082e013Seric 		as = gethostbyname_async(name, NULL);
1138082e013Seric 	else
1148082e013Seric 		as = gethostbyname2_async(name, af, NULL);
1158082e013Seric 
116f5615e53Seric 	if (as == NULL)
117f5615e53Seric 		return (errno);
1188082e013Seric 
1195be03f8fSeric 	asr_run_sync(as, &ar);
1208082e013Seric 
1218082e013Seric 	errno = ar.ar_errno;
122f5615e53Seric 	*h_errnop = ar.ar_h_errno;
1238082e013Seric 	if (ar.ar_hostent == NULL)
124f5615e53Seric 		return (0);
1258082e013Seric 
126f5615e53Seric 	r = _fillhostent(ar.ar_hostent, ret, buf, buflen);
1278082e013Seric 	free(ar.ar_hostent);
1288082e013Seric 
129f5615e53Seric 	return (r);
1308082e013Seric }
1318082e013Seric 
1328082e013Seric struct hostent *
gethostbyname(const char * name)1338082e013Seric gethostbyname(const char *name)
1348082e013Seric {
1351ed934d0Seric 	struct hostent	*h;
1361ed934d0Seric 
1371ed934d0Seric 	res_init();
1381ed934d0Seric 
1391ed934d0Seric 	if (_res.options & RES_USE_INET6 &&
140f5615e53Seric 	    (h = gethostbyname2(name, AF_INET6)))
1411ed934d0Seric 		return (h);
1421ed934d0Seric 
143f5615e53Seric 	return gethostbyname2(name, AF_INET);
1448082e013Seric }
145*06201dd4Sguenther DEF_WEAK(gethostbyname);
1468082e013Seric 
1478082e013Seric struct hostent *
gethostbyname2(const char * name,int af)1488082e013Seric gethostbyname2(const char *name, int af)
1498082e013Seric {
150f5615e53Seric 	int	r;
151f5615e53Seric 
1521ed934d0Seric 	res_init();
1531ed934d0Seric 
154f5615e53Seric 	r = _gethostbyname(name, af, &_hostent, _entbuf, sizeof(_entbuf),
155f5615e53Seric 	    &h_errno);
156f5615e53Seric 	if (r) {
157f5615e53Seric 		h_errno = NETDB_INTERNAL;
158f5615e53Seric 		errno = r;
159f5615e53Seric 	}
160f5615e53Seric 
161f5615e53Seric 	if (h_errno)
162f5615e53Seric 		return (NULL);
163f5615e53Seric 
164f5615e53Seric 	return (&_hostent);
1658082e013Seric }
166*06201dd4Sguenther DEF_WEAK(gethostbyname2);
1678082e013Seric 
1688082e013Seric struct hostent *
gethostbyaddr(const void * addr,socklen_t len,int af)1698082e013Seric gethostbyaddr(const void *addr, socklen_t len, int af)
1708082e013Seric {
1715be03f8fSeric 	struct asr_query *as;
1725be03f8fSeric 	struct asr_result ar;
173f5615e53Seric 	int r;
1748082e013Seric 
1751ed934d0Seric 	res_init();
1761ed934d0Seric 
1778082e013Seric 	as = gethostbyaddr_async(addr, len, af, NULL);
1788082e013Seric 	if (as == NULL) {
1798082e013Seric 		h_errno = NETDB_INTERNAL;
1808082e013Seric 		return (NULL);
1818082e013Seric 	}
1828082e013Seric 
1835be03f8fSeric 	asr_run_sync(as, &ar);
1848082e013Seric 
1858082e013Seric 	errno = ar.ar_errno;
1868082e013Seric 	h_errno = ar.ar_h_errno;
1878082e013Seric 	if (ar.ar_hostent == NULL)
1888082e013Seric 		return (NULL);
1898082e013Seric 
190f5615e53Seric 	r = _fillhostent(ar.ar_hostent, &_hostent, _entbuf, sizeof(_entbuf));
1918082e013Seric 	free(ar.ar_hostent);
1928082e013Seric 
193f5615e53Seric 	if (r) {
194f5615e53Seric 		h_errno = NETDB_INTERNAL;
195f5615e53Seric 		errno = r;
196f5615e53Seric 		return (NULL);
197f5615e53Seric 	}
198f5615e53Seric 
1998082e013Seric 	return (&_hostent);
2008082e013Seric }
201