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