blob: c52620e723703a8304f6838f28c8e6df8cf0506f [file] [log] [blame]
Bernie Innocenti55864192018-08-30 04:05:20 +09001/* $NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1988, 1993
5 * -
6 * Copyright (c) 1985, 1988, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
Bernie Innocenti55864192018-08-30 04:05:20 +090054#include <arpa/inet.h>
55#include <arpa/nameser.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090056#include <assert.h>
57#include <ctype.h>
58#include <errno.h>
59#include <netdb.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090060#include <netinet/in.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090061#include <stdarg.h>
62#include <stdbool.h>
63#include <stdio.h>
64#include <strings.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090065#include <sys/param.h>
66#include <sys/socket.h>
Bernie Innocentif89b3512018-08-30 07:34:37 +090067#include <sys/types.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090068#include <sys/un.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090069#include <syslog.h>
70#include <unistd.h>
Bernie Innocentif89b3512018-08-30 07:34:37 +090071
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090072#include "resolv_cache.h"
73#include "resolv_netid.h"
74#include "resolv_private.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090075
Bernie Innocentif89b3512018-08-30 07:34:37 +090076// NetBSD uses _DIAGASSERT to null-check arguments and the like,
77// but it's clear from the number of mistakes in their assertions
78// that they don't actually test or ship with this.
79#define _DIAGASSERT(e) /* nothing */
80
Bernie Innocenti55864192018-08-30 04:05:20 +090081#define ALIGNBYTES (sizeof(uintptr_t) - 1)
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090082#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
Bernie Innocenti55864192018-08-30 04:05:20 +090083
84#ifndef LOG_AUTH
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090085#define LOG_AUTH 0
Bernie Innocenti55864192018-08-30 04:05:20 +090086#endif
87
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090088#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
Bernie Innocenti55864192018-08-30 04:05:20 +090089
Bernie Innocenti55864192018-08-30 04:05:20 +090090#include <stdlib.h>
91#include <string.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090092#include "nsswitch.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090093
94#include "hostent.h"
95
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090096#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || (ok)(nm) != 0)
Bernie Innocenti55864192018-08-30 04:05:20 +090097#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
98#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
99
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900100#define addalias(d, s, arr, siz) \
101 do { \
102 if (d >= &arr[siz]) { \
103 char** xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
104 if (xptr == NULL) goto nospc; \
105 d = xptr + (d - arr); \
106 arr = xptr; \
107 siz += 10; \
108 } \
109 *d++ = s; \
110 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900111
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900112#define setup(arr, siz) \
113 do { \
114 arr = malloc((siz = 10) * sizeof(*arr)); \
115 if (arr == NULL) goto nospc; \
116 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900117
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900118static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
Bernie Innocenti55864192018-08-30 04:05:20 +0900119
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900120static const struct android_net_context NETCONTEXT_UNSET = {.app_mark = MARK_UNSET,
121 .app_netid = NETID_UNSET,
122 .dns_mark = MARK_UNSET,
123 .dns_netid = NETID_UNSET,
124 .uid = NET_CONTEXT_INVALID_UID};
Bernie Innocenti55864192018-08-30 04:05:20 +0900125
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900126#define MAXPACKET (8 * 1024)
Bernie Innocenti55864192018-08-30 04:05:20 +0900127
128typedef union {
129 HEADER hdr;
130 u_char buf[MAXPACKET];
131} querybuf;
132
133typedef union {
134 int32_t al;
135 char ac;
136} align;
137
138#ifdef DEBUG
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900139static void debugprintf(const char*, res_state, ...) __attribute__((__format__(__printf__, 1, 3)));
Bernie Innocenti55864192018-08-30 04:05:20 +0900140#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900141static struct hostent* getanswer(const querybuf*, int, const char*, int, res_state, struct hostent*,
142 char*, size_t, int*);
143static void map_v4v6_address(const char*, char*);
144static void map_v4v6_hostent(struct hostent*, char**, char*);
145static void addrsort(char**, int, res_state);
Bernie Innocenti55864192018-08-30 04:05:20 +0900146
147void ht_sethostent(int);
148void ht_endhostent(void);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900149struct hostent* ht_gethostbyname(char*);
150struct hostent* ht_gethostbyaddr(const char*, int, int);
Bernie Innocenti55864192018-08-30 04:05:20 +0900151void dns_service(void);
152#undef dn_skipname
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900153int dn_skipname(const u_char*, const u_char*);
154static int _dns_gethtbyaddr(void*, void*, va_list);
155static int _dns_gethtbyname(void*, void*, va_list);
Bernie Innocenti55864192018-08-30 04:05:20 +0900156
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900157static struct hostent* gethostbyname_internal(const char*, int, res_state, struct hostent*, char*,
158 size_t, int*, const struct android_net_context*);
159static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
160 const void*, socklen_t, int, struct hostent*, char*, size_t, int*,
161 const struct android_net_context*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900162
163static const ns_src default_dns_files[] = {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900164 {NSSRC_FILES, NS_SUCCESS},
165 {NSSRC_DNS, NS_SUCCESS},
166 {0, 0}
167};
Bernie Innocenti55864192018-08-30 04:05:20 +0900168
169static int h_errno_to_result(int* herrno_p) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900170 // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
171 if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
172 errno = ERANGE;
173 return errno;
174 }
175 // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
176 return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900177}
178
179#ifdef DEBUG
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900180static void debugprintf(const char* msg, res_state res, ...) {
181 _DIAGASSERT(msg != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900182
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900183 if (res->options & RES_DEBUG) {
184 int save = errno;
185 va_list ap;
Bernie Innocenti55864192018-08-30 04:05:20 +0900186
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900187 va_start(ap, res);
188 vprintf(msg, ap);
189 va_end(ap);
Bernie Innocenti55864192018-08-30 04:05:20 +0900190
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900191 errno = save;
192 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900193}
194#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900195#define debugprintf(msg, res, num) /*nada*/
Bernie Innocenti55864192018-08-30 04:05:20 +0900196#endif
197
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900198#define BOUNDED_INCR(x) \
199 do { \
200 BOUNDS_CHECK(cp, x); \
201 cp += (x); \
202 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900203
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900204#define BOUNDS_CHECK(ptr, count) \
205 do { \
206 if (eom - (ptr) < (count)) goto no_recovery; \
207 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900208
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900209static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
210 res_state res, struct hostent* hent, char* buf, size_t buflen,
211 int* he) {
212 const HEADER* hp;
213 const u_char* cp;
214 int n;
215 size_t qlen;
216 const u_char *eom, *erdata;
217 char *bp, **ap, **hap, *ep;
218 int type, class, ancount, qdcount;
219 int haveanswer, had_error;
220 int toobig = 0;
221 char tbuf[MAXDNAME];
222 char** aliases;
223 size_t maxaliases;
224 char* addr_ptrs[MAXADDRS];
225 const char* tname;
226 int (*name_ok)(const char*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900227
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900228 _DIAGASSERT(answer != NULL);
229 _DIAGASSERT(qname != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900230
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900231 tname = qname;
232 hent->h_name = NULL;
233 eom = answer->buf + anslen;
234 switch (qtype) {
235 case T_A:
236 case T_AAAA:
237 name_ok = res_hnok;
238 break;
239 case T_PTR:
240 name_ok = res_dnok;
241 break;
242 default:
243 *he = NO_RECOVERY;
244 return NULL; /* XXX should be abort(); */
245 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900246
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900247 setup(aliases, maxaliases);
248 /*
249 * find first satisfactory answer
250 */
251 hp = &answer->hdr;
252 ancount = ntohs(hp->ancount);
253 qdcount = ntohs(hp->qdcount);
254 bp = buf;
255 ep = buf + buflen;
256 cp = answer->buf;
257 BOUNDED_INCR(HFIXEDSZ);
258 if (qdcount != 1) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900259
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900260 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
261 if ((n < 0) || !maybe_ok(res, bp, name_ok)) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900262
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900263 BOUNDED_INCR(n + QFIXEDSZ);
264 if (qtype == T_A || qtype == T_AAAA) {
265 /* res_send() has already verified that the query name is the
266 * same as the one we sent; this just gets the expanded name
267 * (i.e., with the succeeding search-domain tacked on).
268 */
269 n = (int) strlen(bp) + 1; /* for the \0 */
270 if (n >= MAXHOSTNAMELEN) goto no_recovery;
271 hent->h_name = bp;
272 bp += n;
273 /* The qname can be abbreviated, but h_name is now absolute. */
274 qname = hent->h_name;
275 }
276 hent->h_aliases = ap = aliases;
277 hent->h_addr_list = hap = addr_ptrs;
278 *ap = NULL;
279 *hap = NULL;
280 haveanswer = 0;
281 had_error = 0;
282 while (ancount-- > 0 && cp < eom && !had_error) {
283 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
284 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
285 had_error++;
286 continue;
287 }
288 cp += n; /* name */
289 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
290 type = _getshort(cp);
291 cp += INT16SZ; /* type */
292 class = _getshort(cp);
293 cp += INT16SZ + INT32SZ; /* class, TTL */
294 n = _getshort(cp);
295 cp += INT16SZ; /* len */
296 BOUNDS_CHECK(cp, n);
297 erdata = cp + n;
298 if (class != C_IN) {
299 /* XXX - debug? syslog? */
300 cp += n;
301 continue; /* XXX - had_error++ ? */
302 }
303 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
304 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
305 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
306 had_error++;
307 continue;
308 }
309 cp += n;
310 if (cp != erdata) goto no_recovery;
311 /* Store alias. */
312 addalias(ap, bp, aliases, maxaliases);
313 n = (int) strlen(bp) + 1; /* for the \0 */
314 if (n >= MAXHOSTNAMELEN) {
315 had_error++;
316 continue;
317 }
318 bp += n;
319 /* Get canonical name. */
320 n = (int) strlen(tbuf) + 1; /* for the \0 */
321 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
322 had_error++;
323 continue;
324 }
325 strlcpy(bp, tbuf, (size_t)(ep - bp));
326 hent->h_name = bp;
327 bp += n;
328 continue;
329 }
330 if (qtype == T_PTR && type == T_CNAME) {
331 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
332 if (n < 0 || !maybe_dnok(res, tbuf)) {
333 had_error++;
334 continue;
335 }
336 cp += n;
337 if (cp != erdata) goto no_recovery;
338 /* Get canonical name. */
339 n = (int) strlen(tbuf) + 1; /* for the \0 */
340 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
341 had_error++;
342 continue;
343 }
344 strlcpy(bp, tbuf, (size_t)(ep - bp));
345 tname = bp;
346 bp += n;
347 continue;
348 }
349 if (type != qtype) {
350 if (type != T_KEY && type != T_SIG)
351 syslog(LOG_NOTICE | LOG_AUTH,
352 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname,
353 p_class(C_IN), p_type(qtype), p_type(type));
354 cp += n;
355 continue; /* XXX - had_error++ ? */
356 }
357 switch (type) {
358 case T_PTR:
359 if (strcasecmp(tname, bp) != 0) {
360 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
361 cp += n;
362 continue; /* XXX - had_error++ ? */
363 }
364 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
365 if ((n < 0) || !maybe_hnok(res, bp)) {
366 had_error++;
367 break;
368 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900369#if MULTI_PTRS_ARE_ALIASES
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900370 cp += n;
371 if (cp != erdata) goto no_recovery;
372 if (!haveanswer)
373 hent->h_name = bp;
374 else
375 addalias(ap, bp, aliases, maxaliases);
376 if (n != -1) {
377 n = (int) strlen(bp) + 1; /* for the \0 */
378 if (n >= MAXHOSTNAMELEN) {
379 had_error++;
380 break;
381 }
382 bp += n;
383 }
384 break;
Bernie Innocenti55864192018-08-30 04:05:20 +0900385#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900386 hent->h_name = bp;
387 if (res->options & RES_USE_INET6) {
388 n = strlen(bp) + 1; /* for the \0 */
389 if (n >= MAXHOSTNAMELEN) {
390 had_error++;
391 break;
392 }
393 bp += n;
394 map_v4v6_hostent(hent, &bp, ep);
395 }
396 goto success;
Bernie Innocenti55864192018-08-30 04:05:20 +0900397#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900398 case T_A:
399 case T_AAAA:
400 if (strcasecmp(hent->h_name, bp) != 0) {
401 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, hent->h_name, bp);
402 cp += n;
403 continue; /* XXX - had_error++ ? */
404 }
405 if (n != hent->h_length) {
406 cp += n;
407 continue;
408 }
409 if (type == T_AAAA) {
410 struct in6_addr in6;
411 memcpy(&in6, cp, NS_IN6ADDRSZ);
412 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
413 cp += n;
414 continue;
415 }
416 }
417 if (!haveanswer) {
418 int nn;
Bernie Innocenti55864192018-08-30 04:05:20 +0900419
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900420 hent->h_name = bp;
421 nn = (int) strlen(bp) + 1; /* for the \0 */
422 bp += nn;
423 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900424
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900425 bp += sizeof(align) - (size_t)((u_long) bp % sizeof(align));
Bernie Innocenti55864192018-08-30 04:05:20 +0900426
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900427 if (bp + n >= ep) {
428 debugprintf("size (%d) too big\n", res, n);
429 had_error++;
430 continue;
431 }
432 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
433 if (!toobig++) {
434 debugprintf("Too many addresses (%d)\n", res, MAXADDRS);
435 }
436 cp += n;
437 continue;
438 }
439 (void) memcpy(*hap++ = bp, cp, (size_t) n);
440 bp += n;
441 cp += n;
442 if (cp != erdata) goto no_recovery;
443 break;
444 default:
445 abort();
446 }
447 if (!had_error) haveanswer++;
448 }
449 if (haveanswer) {
450 *ap = NULL;
451 *hap = NULL;
452 /*
453 * Note: we sort even if host can take only one address
454 * in its return structures - should give it the "best"
455 * address in that case, not some random one
456 */
457 if (res->nsort && haveanswer > 1 && qtype == T_A) addrsort(addr_ptrs, haveanswer, res);
458 if (!hent->h_name) {
459 n = (int) strlen(qname) + 1; /* for the \0 */
460 if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery;
461 strlcpy(bp, qname, (size_t)(ep - bp));
462 hent->h_name = bp;
463 bp += n;
464 }
465 if (res->options & RES_USE_INET6) map_v4v6_hostent(hent, &bp, ep);
466 goto success;
467 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900468no_recovery:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900469 free(aliases);
470 *he = NO_RECOVERY;
471 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900472success:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900473 bp = (char*) ALIGN(bp);
474 n = (int) (ap - aliases);
475 qlen = (n + 1) * sizeof(*hent->h_aliases);
476 if ((size_t)(ep - bp) < qlen) goto nospc;
477 hent->h_aliases = (void*) bp;
478 memcpy(bp, aliases, qlen);
479 free(aliases);
480 aliases = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900481
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900482 bp += qlen;
483 n = (int) (hap - addr_ptrs);
484 qlen = (n + 1) * sizeof(*hent->h_addr_list);
485 if ((size_t)(ep - bp) < qlen) goto nospc;
486 hent->h_addr_list = (void*) bp;
487 memcpy(bp, addr_ptrs, qlen);
488 *he = NETDB_SUCCESS;
489 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900490nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900491 free(aliases);
492 errno = ENOSPC;
493 *he = NETDB_INTERNAL;
494 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900495}
496
497/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900498int gethostbyname_r(const char* name, struct hostent* hp, char* buf, size_t buflen,
499 struct hostent** result, int* errorp) {
500 res_state res = __res_get_state();
501 if (res == NULL) {
502 *result = NULL;
503 *errorp = NETDB_INTERNAL;
504 return -1;
505 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900506
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900507 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900508
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900509 if (res->options & RES_USE_INET6) {
510 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
511 &NETCONTEXT_UNSET);
512 if (*result) {
513 __res_put_state(res);
514 return 0;
515 }
516 }
517 *result =
518 gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
519 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900520}
521
522/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900523int gethostbyname2_r(const char* name, int af, struct hostent* hp, char* buf, size_t buflen,
524 struct hostent** result, int* errorp) {
525 res_state res = __res_get_state();
526 if (res == NULL) {
527 *result = NULL;
528 *errorp = NETDB_INTERNAL;
529 return -1;
530 }
531 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
532 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900533}
534
535__LIBC_HIDDEN__ FILE* android_open_proxy() {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900536 const char* cache_mode = getenv("ANDROID_DNS_MODE");
537 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
538 if (!use_proxy) {
539 return NULL;
540 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900541
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900542 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
543 if (s == -1) {
544 return NULL;
545 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900546
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900547 const int one = 1;
548 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
Bernie Innocenti55864192018-08-30 04:05:20 +0900549
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900550 struct sockaddr_un proxy_addr;
551 memset(&proxy_addr, 0, sizeof(proxy_addr));
552 proxy_addr.sun_family = AF_UNIX;
553 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Bernie Innocenti55864192018-08-30 04:05:20 +0900554
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900555 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) !=
556 0) {
557 close(s);
558 return NULL;
559 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900560
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900561 return fdopen(s, "r+");
Bernie Innocenti55864192018-08-30 04:05:20 +0900562}
563
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900564static struct hostent* gethostbyname_internal_real(const char* name, int af, res_state res,
565 struct hostent* hp, char* buf, size_t buflen,
566 int* he) {
567 const char* cp;
568 struct getnamaddr info;
569 char hbuf[MAXHOSTNAMELEN];
570 size_t size;
Bernie Innocentif89b3512018-08-30 07:34:37 +0900571 static const ns_dtab dtab[] = {
572 {NSSRC_FILES, _hf_gethtbyname, NULL},
573 {NSSRC_DNS, _dns_gethtbyname, NULL},
574 {0, 0, 0}
575 };
Bernie Innocenti55864192018-08-30 04:05:20 +0900576
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900577 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900578
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900579 switch (af) {
580 case AF_INET:
581 size = NS_INADDRSZ;
582 break;
583 case AF_INET6:
584 size = NS_IN6ADDRSZ;
585 break;
586 default:
587 *he = NETDB_INTERNAL;
588 errno = EAFNOSUPPORT;
589 return NULL;
590 }
591 if (buflen < size) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900592
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900593 hp->h_addrtype = af;
594 hp->h_length = (int) size;
Bernie Innocenti55864192018-08-30 04:05:20 +0900595
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900596 /*
597 * if there aren't any dots, it could be a user-level alias.
598 * this is also done in res_nquery() since we are not the only
599 * function that looks up host names.
600 */
601 if (!strchr(name, '.') && (cp = res_hostalias(res, name, hbuf, sizeof(hbuf)))) name = cp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900602
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900603 /*
604 * disallow names consisting only of digits/dots, unless
605 * they end in a dot.
606 */
607 if (isdigit((u_char) name[0]))
608 for (cp = name;; ++cp) {
609 if (!*cp) {
610 if (*--cp == '.') break;
611 /*
612 * All-numeric, no dot at the end.
613 * Fake up a hostent as if we'd actually
614 * done a lookup.
615 */
616 goto fake;
617 }
618 if (!isdigit((u_char) *cp) && *cp != '.') break;
619 }
620 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || name[0] == ':')
621 for (cp = name;; ++cp) {
622 if (!*cp) {
623 if (*--cp == '.') break;
624 /*
625 * All-IPv6-legal, no dot at the end.
626 * Fake up a hostent as if we'd actually
627 * done a lookup.
628 */
629 goto fake;
630 }
631 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') break;
632 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900633
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900634 *he = NETDB_INTERNAL;
635 info.hp = hp;
636 info.buf = buf;
637 info.buflen = buflen;
638 info.he = he;
639 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", default_dns_files, name, strlen(name),
640 af) != NS_SUCCESS)
641 return NULL;
642 *he = NETDB_SUCCESS;
643 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900644nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900645 *he = NETDB_INTERNAL;
646 errno = ENOSPC;
647 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900648fake:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900649 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
650 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900651
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900652 hp->h_aliases[0] = NULL;
653 if (size > buflen) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900654
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900655 if (inet_pton(af, name, buf) <= 0) {
656 *he = HOST_NOT_FOUND;
657 return NULL;
658 }
659 hp->h_addr_list[0] = buf;
660 hp->h_addr_list[1] = NULL;
661 buf += size;
662 buflen -= size;
663 HENT_SCOPY(hp->h_name, name, buf, buflen);
664 if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
665 *he = NETDB_SUCCESS;
666 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900667}
668
669// very similar in proxy-ness to android_getaddrinfo_proxy
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900670static struct hostent* gethostbyname_internal(const char* name, int af, res_state res,
671 struct hostent* hp, char* hbuf, size_t hbuflen,
672 int* errorp,
673 const struct android_net_context* netcontext) {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900674 res_setnetcontext(res, netcontext);
675 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900676}
677
678/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900679int gethostbyaddr_r(const void* addr, socklen_t len, int af, struct hostent* hp, char* buf,
680 size_t buflen, struct hostent** result, int* h_errnop) {
681 *result = android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, hp, buf, buflen,
682 h_errnop, &NETCONTEXT_UNSET);
683 return h_errno_to_result(h_errnop);
Bernie Innocenti55864192018-08-30 04:05:20 +0900684}
685
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900686static struct hostent* android_gethostbyaddrfornetcontext_real(
687 const void* addr, socklen_t len, int af, struct hostent* hp, char* buf, size_t buflen,
688 int* he, const struct android_net_context* netcontext) {
689 const u_char* uaddr = (const u_char*) addr;
690 socklen_t size;
691 struct getnamaddr info;
Bernie Innocentif89b3512018-08-30 07:34:37 +0900692 static const ns_dtab dtab[] = {
693 {NSSRC_FILES, _hf_gethtbyaddr, NULL},
694 {NSSRC_DNS, _dns_gethtbyaddr, NULL},
695 {0, 0, 0}
696 };
Bernie Innocenti55864192018-08-30 04:05:20 +0900697
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900698 _DIAGASSERT(addr != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900699
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900700 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
701 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
702 IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
703 *he = HOST_NOT_FOUND;
704 return NULL;
705 }
706 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
707 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr*) addr) ||
708 IN6_IS_ADDR_V4COMPAT((const struct in6_addr*) addr))) {
709 /* Unmap. */
710 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
711 addr = uaddr;
712 af = AF_INET;
713 len = NS_INADDRSZ;
714 }
715 switch (af) {
716 case AF_INET:
717 size = NS_INADDRSZ;
718 break;
719 case AF_INET6:
720 size = NS_IN6ADDRSZ;
721 break;
722 default:
723 errno = EAFNOSUPPORT;
724 *he = NETDB_INTERNAL;
725 return NULL;
726 }
727 if (size != len) {
728 errno = EINVAL;
729 *he = NETDB_INTERNAL;
730 return NULL;
731 }
732 info.hp = hp;
733 info.buf = buf;
734 info.buflen = buflen;
735 info.he = he;
736 *he = NETDB_INTERNAL;
737 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", default_dns_files, uaddr, len, af,
738 netcontext) != NS_SUCCESS)
739 return NULL;
740 *he = NETDB_SUCCESS;
741 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900742}
743
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900744static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
745 const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
746 int* he, const struct android_net_context* netcontext) {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900747 return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
748 netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +0900749}
750
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900751struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
752 int* he) {
753 char *p, *name;
754 char *cp, **q;
755 int af, len;
756 size_t anum;
757 char** aliases;
758 size_t maxaliases;
759 struct in6_addr host_addr;
Bernie Innocenti55864192018-08-30 04:05:20 +0900760
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900761 if (hf == NULL) {
762 *he = NETDB_INTERNAL;
763 errno = EINVAL;
764 return NULL;
765 }
766 p = NULL;
767 setup(aliases, maxaliases);
Bernie Innocenti55864192018-08-30 04:05:20 +0900768
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900769 /* Allocate a new space to read file lines like upstream does.
770 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
771 * as the buffer may be used to store content for a previous hostent
772 * returned by non-reentrant functions like gethostbyname().
773 */
774 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
775 if ((p = malloc(line_buf_size)) == NULL) {
776 goto nospc;
777 }
778 for (;;) {
779 if (!fgets(p, line_buf_size, hf)) {
780 free(p);
781 free(aliases);
782 *he = HOST_NOT_FOUND;
783 return NULL;
784 }
785 if (*p == '#') {
786 continue;
787 }
788 if (!(cp = strpbrk(p, "#\n"))) {
789 continue;
790 }
791 *cp = '\0';
792 if (!(cp = strpbrk(p, " \t"))) continue;
793 *cp++ = '\0';
794 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
795 af = AF_INET6;
796 len = NS_IN6ADDRSZ;
797 } else {
798 if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900799
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900800 res_state res = __res_get_state();
801 if (res == NULL) goto nospc;
802 if (res->options & RES_USE_INET6) {
803 map_v4v6_address(buf, buf);
804 af = AF_INET6;
805 len = NS_IN6ADDRSZ;
806 } else {
807 af = AF_INET;
808 len = NS_INADDRSZ;
809 }
810 __res_put_state(res);
811 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900812
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900813 /* if this is not something we're looking for, skip it. */
814 if (hent->h_addrtype != 0 && hent->h_addrtype != af) continue;
815 if (hent->h_length != 0 && hent->h_length != len) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900816
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900817 while (*cp == ' ' || *cp == '\t') cp++;
818 if ((cp = strpbrk(name = cp, " \t")) != NULL) *cp++ = '\0';
819 q = aliases;
820 while (cp && *cp) {
821 if (*cp == ' ' || *cp == '\t') {
822 cp++;
823 continue;
824 }
825 addalias(q, cp, aliases, maxaliases);
826 if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0';
827 }
828 break;
829 }
830 hent->h_length = len;
831 hent->h_addrtype = af;
832 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
833 anum = (size_t)(q - aliases);
834 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
835 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, buflen);
836 hent->h_addr_list[1] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900837
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900838 HENT_SCOPY(hent->h_name, name, buf, buflen);
839 for (size_t i = 0; i < anum; i++) HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
840 hent->h_aliases[anum] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900841
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900842 *he = NETDB_SUCCESS;
843 free(p);
844 free(aliases);
845 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900846nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900847 free(p);
848 free(aliases);
849 errno = ENOSPC;
850 *he = NETDB_INTERNAL;
851 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900852}
853
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900854static void map_v4v6_address(const char* src, char* dst) {
855 u_char* p = (u_char*) dst;
856 char tmp[NS_INADDRSZ];
857 int i;
Bernie Innocenti55864192018-08-30 04:05:20 +0900858
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900859 _DIAGASSERT(src != NULL);
860 _DIAGASSERT(dst != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900861
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900862 /* Stash a temporary copy so our caller can update in place. */
863 (void) memcpy(tmp, src, NS_INADDRSZ);
864 /* Mark this ipv6 addr as a mapped ipv4. */
865 for (i = 0; i < 10; i++) *p++ = 0x00;
866 *p++ = 0xff;
867 *p++ = 0xff;
868 /* Retrieve the saved copy and we're done. */
869 (void) memcpy(p, tmp, NS_INADDRSZ);
Bernie Innocenti55864192018-08-30 04:05:20 +0900870}
871
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900872static void map_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) {
873 char** ap;
Bernie Innocenti55864192018-08-30 04:05:20 +0900874
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900875 _DIAGASSERT(hp != NULL);
876 _DIAGASSERT(bpp != NULL);
877 _DIAGASSERT(ep != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900878
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900879 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return;
880 hp->h_addrtype = AF_INET6;
881 hp->h_length = NS_IN6ADDRSZ;
882 for (ap = hp->h_addr_list; *ap; ap++) {
883 int i = (int) (sizeof(align) - (size_t)((u_long) *bpp % sizeof(align)));
Bernie Innocenti55864192018-08-30 04:05:20 +0900884
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900885 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
886 /* Out of memory. Truncate address list here. XXX */
887 *ap = NULL;
888 return;
889 }
890 *bpp += i;
891 map_v4v6_address(*ap, *bpp);
892 *ap = *bpp;
893 *bpp += NS_IN6ADDRSZ;
894 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900895}
896
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900897static void addrsort(char** ap, int num, res_state res) {
898 int i, j;
899 char** p;
900 short aval[MAXADDRS];
901 int needsort = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900902
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900903 _DIAGASSERT(ap != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900904
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900905 p = ap;
906 for (i = 0; i < num; i++, p++) {
907 for (j = 0; (unsigned) j < res->nsort; j++)
908 if (res->sort_list[j].addr.s_addr ==
909 (((struct in_addr*) (void*) (*p))->s_addr & res->sort_list[j].mask))
910 break;
911 aval[i] = j;
912 if (needsort == 0 && i > 0 && j < aval[i - 1]) needsort = i;
913 }
914 if (!needsort) return;
Bernie Innocenti55864192018-08-30 04:05:20 +0900915
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900916 while (needsort < num) {
917 for (j = needsort - 1; j >= 0; j--) {
918 if (aval[j] > aval[j + 1]) {
919 char* hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900920
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900921 i = aval[j];
922 aval[j] = aval[j + 1];
923 aval[j + 1] = i;
Bernie Innocenti55864192018-08-30 04:05:20 +0900924
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900925 hp = ap[j];
926 ap[j] = ap[j + 1];
927 ap[j + 1] = hp;
928 } else
929 break;
930 }
931 needsort++;
932 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900933}
934
935/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900936static int _dns_gethtbyname(void* rv, void* cb_data, va_list ap) {
937 querybuf* buf;
938 int n, type;
939 struct hostent* hp;
940 const char* name;
941 res_state res;
942 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +0900943
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900944 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900945
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900946 name = va_arg(ap, char*);
947 /* NOSTRICT skip string len */ (void) va_arg(ap, int);
948 info->hp->h_addrtype = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +0900949
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900950 switch (info->hp->h_addrtype) {
951 case AF_INET:
952 info->hp->h_length = NS_INADDRSZ;
953 type = T_A;
954 break;
955 case AF_INET6:
956 info->hp->h_length = NS_IN6ADDRSZ;
957 type = T_AAAA;
958 break;
959 default:
960 return NS_UNAVAIL;
961 }
962 buf = malloc(sizeof(*buf));
963 if (buf == NULL) {
964 *info->he = NETDB_INTERNAL;
965 return NS_NOTFOUND;
966 }
967 res = __res_get_state();
968 if (res == NULL) {
969 free(buf);
970 return NS_NOTFOUND;
971 }
972 n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf));
973 if (n < 0) {
974 free(buf);
975 debugprintf("res_nsearch failed (%d)\n", res, n);
976 __res_put_state(res);
977 return NS_NOTFOUND;
978 }
979 hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, info->he);
980 free(buf);
981 __res_put_state(res);
982 if (hp == NULL) switch (*info->he) {
983 case HOST_NOT_FOUND:
984 return NS_NOTFOUND;
985 case TRY_AGAIN:
986 return NS_TRYAGAIN;
987 default:
988 return NS_UNAVAIL;
989 }
990 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +0900991}
992
993/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900994static int _dns_gethtbyaddr(void* rv, void* cb_data, va_list ap) {
995 char qbuf[MAXDNAME + 1], *qp, *ep;
996 int n;
997 querybuf* buf;
998 struct hostent* hp;
999 const unsigned char* uaddr;
1000 int advance;
1001 res_state res;
1002 char* bf;
1003 size_t blen;
1004 struct getnamaddr* info = rv;
1005 const struct android_net_context* netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +09001006
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001007 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001008
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001009 uaddr = va_arg(ap, unsigned char*);
1010 info->hp->h_length = va_arg(ap, int);
1011 info->hp->h_addrtype = va_arg(ap, int);
1012 netcontext = va_arg(ap, const struct android_net_context*);
Bernie Innocenti55864192018-08-30 04:05:20 +09001013
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001014 switch (info->hp->h_addrtype) {
1015 case AF_INET:
1016 (void) snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
1017 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1018 break;
Bernie Innocenti55864192018-08-30 04:05:20 +09001019
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001020 case AF_INET6:
1021 qp = qbuf;
1022 ep = qbuf + sizeof(qbuf) - 1;
1023 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
1024 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", uaddr[n] & 0xf,
1025 ((unsigned int) uaddr[n] >> 4) & 0xf);
1026 if (advance > 0 && qp + advance < ep)
1027 qp += advance;
1028 else {
1029 *info->he = NETDB_INTERNAL;
1030 return NS_NOTFOUND;
1031 }
1032 }
1033 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
1034 *info->he = NETDB_INTERNAL;
1035 return NS_NOTFOUND;
1036 }
1037 break;
1038 default:
1039 return NS_UNAVAIL;
1040 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001041
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001042 buf = malloc(sizeof(*buf));
1043 if (buf == NULL) {
1044 *info->he = NETDB_INTERNAL;
1045 return NS_NOTFOUND;
1046 }
1047 res = __res_get_state();
1048 if (res == NULL) {
1049 free(buf);
1050 return NS_NOTFOUND;
1051 }
1052 res_setnetcontext(res, netcontext);
1053 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf));
1054 if (n < 0) {
1055 free(buf);
1056 debugprintf("res_nquery failed (%d)\n", res, n);
1057 __res_put_state(res);
1058 return NS_NOTFOUND;
1059 }
1060 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
1061 free(buf);
1062 if (hp == NULL) {
1063 __res_put_state(res);
1064 switch (*info->he) {
1065 case HOST_NOT_FOUND:
1066 return NS_NOTFOUND;
1067 case TRY_AGAIN:
1068 return NS_TRYAGAIN;
1069 default:
1070 return NS_UNAVAIL;
1071 }
1072 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001073
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001074 bf = (void*) (hp->h_addr_list + 2);
1075 blen = (size_t)(bf - info->buf);
1076 if (blen + info->hp->h_length > info->buflen) goto nospc;
1077 hp->h_addr_list[0] = bf;
1078 hp->h_addr_list[1] = NULL;
1079 (void) memcpy(bf, uaddr, (size_t) info->hp->h_length);
1080 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1081 if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
1082 map_v4v6_address(bf, bf);
1083 hp->h_addrtype = AF_INET6;
1084 hp->h_length = NS_IN6ADDRSZ;
1085 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001086
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001087 __res_put_state(res);
1088 *info->he = NETDB_SUCCESS;
1089 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001090nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001091 errno = ENOSPC;
1092 *info->he = NETDB_INTERNAL;
1093 return NS_UNAVAIL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001094}
1095
1096#ifdef YP
1097/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001098static struct hostent* _yp_hostent(char* line, int af, struct getnamaddr* info) {
1099 struct in6_addr host_addrs[MAXADDRS];
1100 char** aliases;
1101 size_t maxaliases;
1102 char* p = line;
1103 char *cp, **q, *ptr;
1104 size_t len, anum, i;
1105 int addrok;
1106 int more;
1107 size_t naddrs;
1108 struct hostent* hp = info->hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001109
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001110 _DIAGASSERT(line != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001111
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001112 hp->h_name = NULL;
1113 hp->h_addrtype = af;
1114 switch (af) {
1115 case AF_INET:
1116 hp->h_length = NS_INADDRSZ;
1117 break;
1118 case AF_INET6:
1119 hp->h_length = NS_IN6ADDRSZ;
1120 break;
1121 default:
1122 return NULL;
1123 }
1124 setup(aliases, maxaliases);
1125 naddrs = 0;
1126 q = aliases;
Bernie Innocenti55864192018-08-30 04:05:20 +09001127
1128nextline:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001129 /* check for host_addrs overflow */
1130 if (naddrs >= __arraycount(host_addrs)) goto done;
Bernie Innocenti55864192018-08-30 04:05:20 +09001131
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001132 more = 0;
1133 cp = strpbrk(p, " \t");
1134 if (cp == NULL) goto done;
1135 *cp++ = '\0';
Bernie Innocenti55864192018-08-30 04:05:20 +09001136
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001137 /* p has should have an address */
1138 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1139 if (addrok != 1) {
1140 /* skip to the next line */
1141 while (cp && *cp) {
1142 if (*cp == '\n') {
1143 cp++;
1144 goto nextline;
1145 }
1146 cp++;
1147 }
1148 goto done;
1149 }
1150 naddrs++;
Bernie Innocenti55864192018-08-30 04:05:20 +09001151
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001152 while (*cp == ' ' || *cp == '\t') cp++;
1153 p = cp;
1154 cp = strpbrk(p, " \t\n");
1155 if (cp != NULL) {
1156 if (*cp == '\n') more = 1;
1157 *cp++ = '\0';
1158 }
1159 if (!hp->h_name)
1160 hp->h_name = p;
1161 else if (strcmp(hp->h_name, p) == 0)
1162 ;
1163 else
1164 addalias(q, p, aliases, maxaliases);
1165 p = cp;
1166 if (more) goto nextline;
Bernie Innocenti55864192018-08-30 04:05:20 +09001167
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001168 while (cp && *cp) {
1169 if (*cp == ' ' || *cp == '\t') {
1170 cp++;
1171 continue;
1172 }
1173 if (*cp == '\n') {
1174 cp++;
1175 goto nextline;
1176 }
1177 addalias(q, cp, aliases, maxaliases);
1178 cp = strpbrk(cp, " \t");
1179 if (cp != NULL) *cp++ = '\0';
1180 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001181
1182done:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001183 if (hp->h_name == NULL) {
1184 free(aliases);
1185 return NULL;
1186 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001187
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001188 ptr = info->buf;
1189 len = info->buflen;
Bernie Innocenti55864192018-08-30 04:05:20 +09001190
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001191 anum = (size_t)(q - aliases);
1192 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1193 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
Bernie Innocenti55864192018-08-30 04:05:20 +09001194
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001195 for (i = 0; i < naddrs; i++)
1196 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, ptr, len);
1197 hp->h_addr_list[naddrs] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001198
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001199 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
Bernie Innocenti55864192018-08-30 04:05:20 +09001200
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001201 for (i = 0; i < anum; i++) HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1202 hp->h_aliases[anum] = NULL;
1203 free(aliases);
Bernie Innocenti55864192018-08-30 04:05:20 +09001204
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001205 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001206nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001207 free(aliases);
1208 *info->he = NETDB_INTERNAL;
1209 errno = ENOSPC;
1210 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001211}
1212
1213/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001214int _yp_gethtbyaddr(void* rv, void* cb_data, va_list ap) {
1215 struct hostent* hp = NULL;
1216 char* ypcurrent;
1217 int ypcurrentlen, r;
1218 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1219 const unsigned char* uaddr;
1220 int af;
1221 const char* map;
1222 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +09001223
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001224 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001225
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001226 uaddr = va_arg(ap, unsigned char*);
1227 /* NOSTRICT skip len */ (void) va_arg(ap, int);
1228 af = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +09001229
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001230 if (!__ypdomain) {
1231 if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL;
1232 }
1233 /*
1234 * XXX unfortunately, we cannot support IPv6 extended scoped address
1235 * notation here. gethostbyaddr() is not scope-aware. too bad.
1236 */
1237 if (inet_ntop(af, uaddr, name, (socklen_t) sizeof(name)) == NULL) return NS_UNAVAIL;
1238 switch (af) {
1239 case AF_INET:
1240 map = "hosts.byaddr";
1241 break;
1242 default:
1243 map = "ipnodes.byaddr";
1244 break;
1245 }
1246 ypcurrent = NULL;
1247 r = yp_match(__ypdomain, map, name, (int) strlen(name), &ypcurrent, &ypcurrentlen);
1248 if (r == 0)
1249 hp = _yp_hostent(ypcurrent, af, info);
1250 else
1251 hp = NULL;
1252 free(ypcurrent);
1253 if (hp == NULL) {
1254 *info->he = HOST_NOT_FOUND;
1255 return NS_NOTFOUND;
1256 }
1257 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001258}
1259
1260/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001261int _yp_gethtbyname(void* rv, void* cb_data, va_list ap) {
1262 struct hostent* hp;
1263 char* ypcurrent;
1264 int ypcurrentlen, r;
1265 const char* name;
1266 int af;
1267 const char* map;
1268 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +09001269
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001270 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001271
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001272 name = va_arg(ap, char*);
1273 /* NOSTRICT skip string len */ (void) va_arg(ap, int);
1274 af = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +09001275
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001276 if (!__ypdomain) {
1277 if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL;
1278 }
1279 switch (af) {
1280 case AF_INET:
1281 map = "hosts.byname";
1282 break;
1283 default:
1284 map = "ipnodes.byname";
1285 break;
1286 }
1287 ypcurrent = NULL;
1288 r = yp_match(__ypdomain, map, name, (int) strlen(name), &ypcurrent, &ypcurrentlen);
1289 if (r == 0)
1290 hp = _yp_hostent(ypcurrent, af, info);
1291 else
1292 hp = NULL;
1293 free(ypcurrent);
1294 if (hp == NULL) {
1295 *info->he = HOST_NOT_FOUND;
1296 return NS_NOTFOUND;
1297 }
1298 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001299}
1300#endif
1301
1302/*
1303 * Non-reentrant versions.
1304 */
1305
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001306struct hostent* gethostbyname(const char* name) {
1307 struct hostent* result = NULL;
1308 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Bernie Innocenti55864192018-08-30 04:05:20 +09001309
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001310 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1311 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001312}
1313
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001314struct hostent* gethostbyname2(const char* name, int af) {
1315 struct hostent* result = NULL;
1316 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Bernie Innocenti55864192018-08-30 04:05:20 +09001317
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001318 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1319 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001320}
1321
1322// android_gethostby*fornet can be called in two different contexts.
1323// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1324// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1325// The netcontext is constructed before checking which context we are in.
1326// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1327// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1328static struct android_net_context make_context(unsigned netid, unsigned mark) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001329 struct android_net_context netcontext = NETCONTEXT_UNSET;
1330 netcontext.app_netid = netid;
1331 netcontext.app_mark = mark;
1332 netcontext.dns_netid = netid;
1333 netcontext.dns_mark = mark;
1334 return netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +09001335}
1336
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001337struct hostent* android_gethostbynamefornet(const char* name, int af, unsigned netid,
1338 unsigned mark) {
1339 const struct android_net_context netcontext = make_context(netid, mark);
1340 return android_gethostbynamefornetcontext(name, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001341}
1342
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001343struct hostent* android_gethostbynamefornetcontext(const char* name, int af,
1344 const struct android_net_context* netcontext) {
1345 struct hostent* hp;
1346 res_state res = __res_get_state();
1347 if (res == NULL) return NULL;
1348 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1349 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
1350 &h_errno, netcontext);
1351 __res_put_state(res);
1352 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001353}
1354
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001355struct hostent* gethostbyaddr(const void* addr, socklen_t len, int af) {
1356 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Bernie Innocenti55864192018-08-30 04:05:20 +09001357}
1358
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001359struct hostent* android_gethostbyaddrfornet(const void* addr, socklen_t len, int af, unsigned netid,
1360 unsigned mark) {
1361 const struct android_net_context netcontext = make_context(netid, mark);
1362 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001363}
1364
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001365struct hostent* android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
1366 const struct android_net_context* netcontext) {
1367 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001368}
1369
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001370__LIBC_HIDDEN__ struct hostent* android_gethostbyaddrfornetcontext_proxy(
1371 const void* addr, socklen_t len, int af, const struct android_net_context* netcontext) {
1372 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1373 return android_gethostbyaddrfornetcontext_proxy_internal(
1374 addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001375}
1376
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001377struct hostent* gethostent(void) {
1378 res_static rs = __res_get_static();
1379 if (!rs->hostf) {
1380 sethostent_r(&rs->hostf);
1381 if (!rs->hostf) {
1382 h_errno = NETDB_INTERNAL;
1383 return NULL;
1384 }
1385 }
1386 memset(&rs->host, 0, sizeof(rs->host));
1387 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno);
Bernie Innocenti55864192018-08-30 04:05:20 +09001388}