blob: 59245401fcc3ac28a023021868f1bebe10443545 [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
54#include <sys/cdefs.h>
55#include <sys/types.h>
56
Bernie Innocenti55864192018-08-30 04:05:20 +090057#include <arpa/inet.h>
58#include <arpa/nameser.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090059#include <assert.h>
60#include <ctype.h>
61#include <errno.h>
62#include <netdb.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090063#include <netinet/in.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090064#include <stdarg.h>
65#include <stdbool.h>
66#include <stdio.h>
67#include <strings.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090068#include <sys/param.h>
69#include <sys/socket.h>
70#include <sys/un.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090071#include <syslog.h>
72#include <unistd.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090073#include "NetdClientDispatch.h"
74#include "resolv_cache.h"
75#include "resolv_netid.h"
76#include "resolv_private.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090077
78#define ALIGNBYTES (sizeof(uintptr_t) - 1)
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090079#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
Bernie Innocenti55864192018-08-30 04:05:20 +090080
81#ifndef LOG_AUTH
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090082#define LOG_AUTH 0
Bernie Innocenti55864192018-08-30 04:05:20 +090083#endif
84
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090085#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
Bernie Innocenti55864192018-08-30 04:05:20 +090086
Bernie Innocenti55864192018-08-30 04:05:20 +090087#include <stdlib.h>
88#include <string.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090089#include "nsswitch.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090090
91#include "hostent.h"
92
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090093#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || (ok)(nm) != 0)
Bernie Innocenti55864192018-08-30 04:05:20 +090094#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
95#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
96
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090097#define addalias(d, s, arr, siz) \
98 do { \
99 if (d >= &arr[siz]) { \
100 char** xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
101 if (xptr == NULL) goto nospc; \
102 d = xptr + (d - arr); \
103 arr = xptr; \
104 siz += 10; \
105 } \
106 *d++ = s; \
107 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900108
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900109#define setup(arr, siz) \
110 do { \
111 arr = malloc((siz = 10) * sizeof(*arr)); \
112 if (arr == NULL) goto nospc; \
113 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900114
115// This should be synchronized to ResponseCode.h
116static const int DnsProxyQueryResult = 222;
117
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 Innocentif12d5bb2018-08-31 14:09:46 +0900164 {NSSRC_FILES, NS_SUCCESS}, {NSSRC_DNS, NS_SUCCESS}, {0, 0}};
Bernie Innocenti55864192018-08-30 04:05:20 +0900165
166static int h_errno_to_result(int* herrno_p) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900167 // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
168 if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
169 errno = ERANGE;
170 return errno;
171 }
172 // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
173 return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900174}
175
176#ifdef DEBUG
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900177static void debugprintf(const char* msg, res_state res, ...) {
178 _DIAGASSERT(msg != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900179
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900180 if (res->options & RES_DEBUG) {
181 int save = errno;
182 va_list ap;
Bernie Innocenti55864192018-08-30 04:05:20 +0900183
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900184 va_start(ap, res);
185 vprintf(msg, ap);
186 va_end(ap);
Bernie Innocenti55864192018-08-30 04:05:20 +0900187
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900188 errno = save;
189 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900190}
191#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900192#define debugprintf(msg, res, num) /*nada*/
Bernie Innocenti55864192018-08-30 04:05:20 +0900193#endif
194
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900195#define BOUNDED_INCR(x) \
196 do { \
197 BOUNDS_CHECK(cp, x); \
198 cp += (x); \
199 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900200
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900201#define BOUNDS_CHECK(ptr, count) \
202 do { \
203 if (eom - (ptr) < (count)) goto no_recovery; \
204 } while (/*CONSTCOND*/ 0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900205
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900206static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
207 res_state res, struct hostent* hent, char* buf, size_t buflen,
208 int* he) {
209 const HEADER* hp;
210 const u_char* cp;
211 int n;
212 size_t qlen;
213 const u_char *eom, *erdata;
214 char *bp, **ap, **hap, *ep;
215 int type, class, ancount, qdcount;
216 int haveanswer, had_error;
217 int toobig = 0;
218 char tbuf[MAXDNAME];
219 char** aliases;
220 size_t maxaliases;
221 char* addr_ptrs[MAXADDRS];
222 const char* tname;
223 int (*name_ok)(const char*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900224
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900225 _DIAGASSERT(answer != NULL);
226 _DIAGASSERT(qname != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900227
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900228 tname = qname;
229 hent->h_name = NULL;
230 eom = answer->buf + anslen;
231 switch (qtype) {
232 case T_A:
233 case T_AAAA:
234 name_ok = res_hnok;
235 break;
236 case T_PTR:
237 name_ok = res_dnok;
238 break;
239 default:
240 *he = NO_RECOVERY;
241 return NULL; /* XXX should be abort(); */
242 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900243
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900244 setup(aliases, maxaliases);
245 /*
246 * find first satisfactory answer
247 */
248 hp = &answer->hdr;
249 ancount = ntohs(hp->ancount);
250 qdcount = ntohs(hp->qdcount);
251 bp = buf;
252 ep = buf + buflen;
253 cp = answer->buf;
254 BOUNDED_INCR(HFIXEDSZ);
255 if (qdcount != 1) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900256
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900257 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
258 if ((n < 0) || !maybe_ok(res, bp, name_ok)) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900259
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900260 BOUNDED_INCR(n + QFIXEDSZ);
261 if (qtype == T_A || qtype == T_AAAA) {
262 /* res_send() has already verified that the query name is the
263 * same as the one we sent; this just gets the expanded name
264 * (i.e., with the succeeding search-domain tacked on).
265 */
266 n = (int) strlen(bp) + 1; /* for the \0 */
267 if (n >= MAXHOSTNAMELEN) goto no_recovery;
268 hent->h_name = bp;
269 bp += n;
270 /* The qname can be abbreviated, but h_name is now absolute. */
271 qname = hent->h_name;
272 }
273 hent->h_aliases = ap = aliases;
274 hent->h_addr_list = hap = addr_ptrs;
275 *ap = NULL;
276 *hap = NULL;
277 haveanswer = 0;
278 had_error = 0;
279 while (ancount-- > 0 && cp < eom && !had_error) {
280 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
281 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
282 had_error++;
283 continue;
284 }
285 cp += n; /* name */
286 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
287 type = _getshort(cp);
288 cp += INT16SZ; /* type */
289 class = _getshort(cp);
290 cp += INT16SZ + INT32SZ; /* class, TTL */
291 n = _getshort(cp);
292 cp += INT16SZ; /* len */
293 BOUNDS_CHECK(cp, n);
294 erdata = cp + n;
295 if (class != C_IN) {
296 /* XXX - debug? syslog? */
297 cp += n;
298 continue; /* XXX - had_error++ ? */
299 }
300 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
301 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
302 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
303 had_error++;
304 continue;
305 }
306 cp += n;
307 if (cp != erdata) goto no_recovery;
308 /* Store alias. */
309 addalias(ap, bp, aliases, maxaliases);
310 n = (int) strlen(bp) + 1; /* for the \0 */
311 if (n >= MAXHOSTNAMELEN) {
312 had_error++;
313 continue;
314 }
315 bp += n;
316 /* Get canonical name. */
317 n = (int) strlen(tbuf) + 1; /* for the \0 */
318 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
319 had_error++;
320 continue;
321 }
322 strlcpy(bp, tbuf, (size_t)(ep - bp));
323 hent->h_name = bp;
324 bp += n;
325 continue;
326 }
327 if (qtype == T_PTR && type == T_CNAME) {
328 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
329 if (n < 0 || !maybe_dnok(res, tbuf)) {
330 had_error++;
331 continue;
332 }
333 cp += n;
334 if (cp != erdata) goto no_recovery;
335 /* Get canonical name. */
336 n = (int) strlen(tbuf) + 1; /* for the \0 */
337 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
338 had_error++;
339 continue;
340 }
341 strlcpy(bp, tbuf, (size_t)(ep - bp));
342 tname = bp;
343 bp += n;
344 continue;
345 }
346 if (type != qtype) {
347 if (type != T_KEY && type != T_SIG)
348 syslog(LOG_NOTICE | LOG_AUTH,
349 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname,
350 p_class(C_IN), p_type(qtype), p_type(type));
351 cp += n;
352 continue; /* XXX - had_error++ ? */
353 }
354 switch (type) {
355 case T_PTR:
356 if (strcasecmp(tname, bp) != 0) {
357 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
358 cp += n;
359 continue; /* XXX - had_error++ ? */
360 }
361 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
362 if ((n < 0) || !maybe_hnok(res, bp)) {
363 had_error++;
364 break;
365 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900366#if MULTI_PTRS_ARE_ALIASES
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900367 cp += n;
368 if (cp != erdata) goto no_recovery;
369 if (!haveanswer)
370 hent->h_name = bp;
371 else
372 addalias(ap, bp, aliases, maxaliases);
373 if (n != -1) {
374 n = (int) strlen(bp) + 1; /* for the \0 */
375 if (n >= MAXHOSTNAMELEN) {
376 had_error++;
377 break;
378 }
379 bp += n;
380 }
381 break;
Bernie Innocenti55864192018-08-30 04:05:20 +0900382#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900383 hent->h_name = bp;
384 if (res->options & RES_USE_INET6) {
385 n = strlen(bp) + 1; /* for the \0 */
386 if (n >= MAXHOSTNAMELEN) {
387 had_error++;
388 break;
389 }
390 bp += n;
391 map_v4v6_hostent(hent, &bp, ep);
392 }
393 goto success;
Bernie Innocenti55864192018-08-30 04:05:20 +0900394#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900395 case T_A:
396 case T_AAAA:
397 if (strcasecmp(hent->h_name, bp) != 0) {
398 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, hent->h_name, bp);
399 cp += n;
400 continue; /* XXX - had_error++ ? */
401 }
402 if (n != hent->h_length) {
403 cp += n;
404 continue;
405 }
406 if (type == T_AAAA) {
407 struct in6_addr in6;
408 memcpy(&in6, cp, NS_IN6ADDRSZ);
409 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
410 cp += n;
411 continue;
412 }
413 }
414 if (!haveanswer) {
415 int nn;
Bernie Innocenti55864192018-08-30 04:05:20 +0900416
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900417 hent->h_name = bp;
418 nn = (int) strlen(bp) + 1; /* for the \0 */
419 bp += nn;
420 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900421
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900422 bp += sizeof(align) - (size_t)((u_long) bp % sizeof(align));
Bernie Innocenti55864192018-08-30 04:05:20 +0900423
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900424 if (bp + n >= ep) {
425 debugprintf("size (%d) too big\n", res, n);
426 had_error++;
427 continue;
428 }
429 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
430 if (!toobig++) {
431 debugprintf("Too many addresses (%d)\n", res, MAXADDRS);
432 }
433 cp += n;
434 continue;
435 }
436 (void) memcpy(*hap++ = bp, cp, (size_t) n);
437 bp += n;
438 cp += n;
439 if (cp != erdata) goto no_recovery;
440 break;
441 default:
442 abort();
443 }
444 if (!had_error) haveanswer++;
445 }
446 if (haveanswer) {
447 *ap = NULL;
448 *hap = NULL;
449 /*
450 * Note: we sort even if host can take only one address
451 * in its return structures - should give it the "best"
452 * address in that case, not some random one
453 */
454 if (res->nsort && haveanswer > 1 && qtype == T_A) addrsort(addr_ptrs, haveanswer, res);
455 if (!hent->h_name) {
456 n = (int) strlen(qname) + 1; /* for the \0 */
457 if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery;
458 strlcpy(bp, qname, (size_t)(ep - bp));
459 hent->h_name = bp;
460 bp += n;
461 }
462 if (res->options & RES_USE_INET6) map_v4v6_hostent(hent, &bp, ep);
463 goto success;
464 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900465no_recovery:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900466 free(aliases);
467 *he = NO_RECOVERY;
468 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900469success:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900470 bp = (char*) ALIGN(bp);
471 n = (int) (ap - aliases);
472 qlen = (n + 1) * sizeof(*hent->h_aliases);
473 if ((size_t)(ep - bp) < qlen) goto nospc;
474 hent->h_aliases = (void*) bp;
475 memcpy(bp, aliases, qlen);
476 free(aliases);
477 aliases = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900478
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900479 bp += qlen;
480 n = (int) (hap - addr_ptrs);
481 qlen = (n + 1) * sizeof(*hent->h_addr_list);
482 if ((size_t)(ep - bp) < qlen) goto nospc;
483 hent->h_addr_list = (void*) bp;
484 memcpy(bp, addr_ptrs, qlen);
485 *he = NETDB_SUCCESS;
486 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900487nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900488 free(aliases);
489 errno = ENOSPC;
490 *he = NETDB_INTERNAL;
491 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900492}
493
494/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900495int gethostbyname_r(const char* name, struct hostent* hp, char* buf, size_t buflen,
496 struct hostent** result, int* errorp) {
497 res_state res = __res_get_state();
498 if (res == NULL) {
499 *result = NULL;
500 *errorp = NETDB_INTERNAL;
501 return -1;
502 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900503
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900504 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900505
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900506 if (res->options & RES_USE_INET6) {
507 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
508 &NETCONTEXT_UNSET);
509 if (*result) {
510 __res_put_state(res);
511 return 0;
512 }
513 }
514 *result =
515 gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
516 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900517}
518
519/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900520int gethostbyname2_r(const char* name, int af, struct hostent* hp, char* buf, size_t buflen,
521 struct hostent** result, int* errorp) {
522 res_state res = __res_get_state();
523 if (res == NULL) {
524 *result = NULL;
525 *errorp = NETDB_INTERNAL;
526 return -1;
527 }
528 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
529 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900530}
531
532__LIBC_HIDDEN__ FILE* android_open_proxy() {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900533 const char* cache_mode = getenv("ANDROID_DNS_MODE");
534 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
535 if (!use_proxy) {
536 return NULL;
537 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900538
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900539 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
540 if (s == -1) {
541 return NULL;
542 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900543
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900544 const int one = 1;
545 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
Bernie Innocenti55864192018-08-30 04:05:20 +0900546
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900547 struct sockaddr_un proxy_addr;
548 memset(&proxy_addr, 0, sizeof(proxy_addr));
549 proxy_addr.sun_family = AF_UNIX;
550 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Bernie Innocenti55864192018-08-30 04:05:20 +0900551
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900552 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) !=
553 0) {
554 close(s);
555 return NULL;
556 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900557
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900558 return fdopen(s, "r+");
Bernie Innocenti55864192018-08-30 04:05:20 +0900559}
560
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900561static struct hostent* android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf,
562 size_t hbuflen, int* he) {
563 uint32_t size;
564 char buf[4];
565 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900566
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900567 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp
568 // and changes here need to be matched there.
569 int result_code = strtol(buf, NULL, 10);
570 if (result_code != DnsProxyQueryResult) {
571 fread(&size, 1, sizeof(size), proxy);
572 *he = HOST_NOT_FOUND;
573 return NULL;
574 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900575
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900576 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
577 size = ntohl(size);
Bernie Innocenti55864192018-08-30 04:05:20 +0900578
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900579 memset(hp, 0, sizeof(*hp));
580 char* ptr = hbuf;
581 char* hbuf_end = hbuf + hbuflen;
Bernie Innocenti55864192018-08-30 04:05:20 +0900582
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900583 if (ptr + size > hbuf_end) {
584 goto nospc;
585 }
586 if (fread(ptr, 1, size, proxy) != size) return NULL;
587 hp->h_name = ptr;
588 ptr += size;
Bernie Innocenti55864192018-08-30 04:05:20 +0900589
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900590 char* aliases_ptrs[MAXALIASES];
591 char** aliases = &aliases_ptrs[0];
Bernie Innocenti55864192018-08-30 04:05:20 +0900592
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900593 while (1) {
594 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
595 size = ntohl(size);
Bernie Innocenti55864192018-08-30 04:05:20 +0900596
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900597 if (size == 0) {
598 *aliases = NULL;
599 break;
600 }
601 if (ptr + size > hbuf_end) {
602 goto nospc;
603 }
604 if (fread(ptr, 1, size, proxy) != size) return NULL;
605 if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
606 *aliases++ = ptr;
607 }
608 ptr += size;
609 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900610
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900611 // Fix alignment after variable-length data.
612 ptr = (char*) ALIGN(ptr);
Bernie Innocenti55864192018-08-30 04:05:20 +0900613
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900614 int aliases_len = ((int) (aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
615 if (ptr + aliases_len > hbuf_end) {
616 goto nospc;
617 }
618 hp->h_aliases = (void*) ptr;
619 memcpy(ptr, aliases_ptrs, aliases_len);
620 ptr += aliases_len;
Bernie Innocenti55864192018-08-30 04:05:20 +0900621
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900622 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
623 hp->h_addrtype = ntohl(size);
Bernie Innocenti55864192018-08-30 04:05:20 +0900624
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900625 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
626 hp->h_length = ntohl(size);
Bernie Innocenti55864192018-08-30 04:05:20 +0900627
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900628 char* addr_ptrs[MAXADDRS];
629 char** addr_p = &addr_ptrs[0];
Bernie Innocenti55864192018-08-30 04:05:20 +0900630
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900631 while (1) {
632 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
633 size = ntohl(size);
634 if (size == 0) {
635 *addr_p = NULL;
636 break;
637 }
638 if (ptr + size > hbuf_end) {
639 goto nospc;
640 }
641 if (fread(ptr, 1, size, proxy) != size) return NULL;
642 if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
643 *addr_p++ = ptr;
644 }
645 ptr += size;
646 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900647
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900648 // Fix alignment after variable-length data.
649 ptr = (char*) ALIGN(ptr);
Bernie Innocenti55864192018-08-30 04:05:20 +0900650
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900651 int addrs_len = ((int) (addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
652 if (ptr + addrs_len > hbuf_end) {
653 goto nospc;
654 }
655 hp->h_addr_list = (void*) ptr;
656 memcpy(ptr, addr_ptrs, addrs_len);
657 *he = NETDB_SUCCESS;
658 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900659
660nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900661 *he = NETDB_INTERNAL;
662 errno = ENOSPC;
663 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900664}
665
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900666static struct hostent* gethostbyname_internal_real(const char* name, int af, res_state res,
667 struct hostent* hp, char* buf, size_t buflen,
668 int* he) {
669 const char* cp;
670 struct getnamaddr info;
671 char hbuf[MAXHOSTNAMELEN];
672 size_t size;
673 static const ns_dtab dtab[] = {NS_FILES_CB(_hf_gethtbyname, NULL){NSSRC_DNS, _dns_gethtbyname,
674 NULL}, /* force -DHESIOD */
675 NS_NIS_CB(_yp_gethtbyname, NULL) NS_NULL_CB};
Bernie Innocenti55864192018-08-30 04:05:20 +0900676
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900677 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900678
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900679 switch (af) {
680 case AF_INET:
681 size = NS_INADDRSZ;
682 break;
683 case AF_INET6:
684 size = NS_IN6ADDRSZ;
685 break;
686 default:
687 *he = NETDB_INTERNAL;
688 errno = EAFNOSUPPORT;
689 return NULL;
690 }
691 if (buflen < size) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900692
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900693 hp->h_addrtype = af;
694 hp->h_length = (int) size;
Bernie Innocenti55864192018-08-30 04:05:20 +0900695
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900696 /*
697 * if there aren't any dots, it could be a user-level alias.
698 * this is also done in res_nquery() since we are not the only
699 * function that looks up host names.
700 */
701 if (!strchr(name, '.') && (cp = res_hostalias(res, name, hbuf, sizeof(hbuf)))) name = cp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900702
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900703 /*
704 * disallow names consisting only of digits/dots, unless
705 * they end in a dot.
706 */
707 if (isdigit((u_char) name[0]))
708 for (cp = name;; ++cp) {
709 if (!*cp) {
710 if (*--cp == '.') break;
711 /*
712 * All-numeric, no dot at the end.
713 * Fake up a hostent as if we'd actually
714 * done a lookup.
715 */
716 goto fake;
717 }
718 if (!isdigit((u_char) *cp) && *cp != '.') break;
719 }
720 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || name[0] == ':')
721 for (cp = name;; ++cp) {
722 if (!*cp) {
723 if (*--cp == '.') break;
724 /*
725 * All-IPv6-legal, no dot at the end.
726 * Fake up a hostent as if we'd actually
727 * done a lookup.
728 */
729 goto fake;
730 }
731 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') break;
732 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900733
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900734 *he = NETDB_INTERNAL;
735 info.hp = hp;
736 info.buf = buf;
737 info.buflen = buflen;
738 info.he = he;
739 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname", default_dns_files, name, strlen(name),
740 af) != NS_SUCCESS)
741 return NULL;
742 *he = NETDB_SUCCESS;
743 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900744nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900745 *he = NETDB_INTERNAL;
746 errno = ENOSPC;
747 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900748fake:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900749 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
750 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900751
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900752 hp->h_aliases[0] = NULL;
753 if (size > buflen) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900754
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900755 if (inet_pton(af, name, buf) <= 0) {
756 *he = HOST_NOT_FOUND;
757 return NULL;
758 }
759 hp->h_addr_list[0] = buf;
760 hp->h_addr_list[1] = NULL;
761 buf += size;
762 buflen -= size;
763 HENT_SCOPY(hp->h_name, name, buf, buflen);
764 if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
765 *he = NETDB_SUCCESS;
766 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900767}
768
769// very similar in proxy-ness to android_getaddrinfo_proxy
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900770static struct hostent* gethostbyname_internal(const char* name, int af, res_state res,
771 struct hostent* hp, char* hbuf, size_t hbuflen,
772 int* errorp,
773 const struct android_net_context* netcontext) {
774 FILE* proxy = android_open_proxy();
775 if (proxy == NULL) {
776 // Either we're not supposed to be using the proxy or the proxy is unavailable.
777 res_setnetcontext(res, netcontext);
778 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
779 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900780
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900781 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Bernie Innocenti55864192018-08-30 04:05:20 +0900782
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900783 // This is writing to system/netd/server/DnsProxyListener.cpp and changes
784 // here need to be matched there.
785 if (fprintf(proxy, "gethostbyname %u %s %d", netid, name == NULL ? "^" : name, af) < 0) {
786 fclose(proxy);
787 return NULL;
788 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900789
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900790 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
791 fclose(proxy);
792 return NULL;
793 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900794
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900795 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
796 fclose(proxy);
797 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +0900798}
799
800/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900801int gethostbyaddr_r(const void* addr, socklen_t len, int af, struct hostent* hp, char* buf,
802 size_t buflen, struct hostent** result, int* h_errnop) {
803 *result = android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, hp, buf, buflen,
804 h_errnop, &NETCONTEXT_UNSET);
805 return h_errno_to_result(h_errnop);
Bernie Innocenti55864192018-08-30 04:05:20 +0900806}
807
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900808static struct hostent* android_gethostbyaddrfornetcontext_real(
809 const void* addr, socklen_t len, int af, struct hostent* hp, char* buf, size_t buflen,
810 int* he, const struct android_net_context* netcontext) {
811 const u_char* uaddr = (const u_char*) addr;
812 socklen_t size;
813 struct getnamaddr info;
814 static const ns_dtab dtab[] = {NS_FILES_CB(_hf_gethtbyaddr, NULL){NSSRC_DNS, _dns_gethtbyaddr,
815 NULL}, /* force -DHESIOD */
816 NS_NIS_CB(_yp_gethtbyaddr, NULL) NS_NULL_CB};
Bernie Innocenti55864192018-08-30 04:05:20 +0900817
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900818 _DIAGASSERT(addr != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900819
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900820 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
821 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
822 IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
823 *he = HOST_NOT_FOUND;
824 return NULL;
825 }
826 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
827 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr*) addr) ||
828 IN6_IS_ADDR_V4COMPAT((const struct in6_addr*) addr))) {
829 /* Unmap. */
830 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
831 addr = uaddr;
832 af = AF_INET;
833 len = NS_INADDRSZ;
834 }
835 switch (af) {
836 case AF_INET:
837 size = NS_INADDRSZ;
838 break;
839 case AF_INET6:
840 size = NS_IN6ADDRSZ;
841 break;
842 default:
843 errno = EAFNOSUPPORT;
844 *he = NETDB_INTERNAL;
845 return NULL;
846 }
847 if (size != len) {
848 errno = EINVAL;
849 *he = NETDB_INTERNAL;
850 return NULL;
851 }
852 info.hp = hp;
853 info.buf = buf;
854 info.buflen = buflen;
855 info.he = he;
856 *he = NETDB_INTERNAL;
857 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", default_dns_files, uaddr, len, af,
858 netcontext) != NS_SUCCESS)
859 return NULL;
860 *he = NETDB_SUCCESS;
861 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900862}
863
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900864static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
865 const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
866 int* he, const struct android_net_context* netcontext) {
867 FILE* proxy = android_open_proxy();
868 if (proxy == NULL) {
869 // Either we're not supposed to be using the proxy or the proxy is unavailable.
870 return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
871 netcontext);
872 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900873
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900874 char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6
875 const char* addrStr = inet_ntop(af, addr, buf, sizeof(buf));
876 if (addrStr == NULL) {
877 fclose(proxy);
878 return NULL;
879 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900880
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900881 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Bernie Innocenti55864192018-08-30 04:05:20 +0900882
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900883 if (fprintf(proxy, "gethostbyaddr %s %d %d %u", addrStr, len, af, netid) < 0) {
884 fclose(proxy);
885 return NULL;
886 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900887
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900888 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
889 fclose(proxy);
890 return NULL;
891 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900892
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900893 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
894 fclose(proxy);
895 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +0900896}
897
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900898struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
899 int* he) {
900 char *p, *name;
901 char *cp, **q;
902 int af, len;
903 size_t anum;
904 char** aliases;
905 size_t maxaliases;
906 struct in6_addr host_addr;
Bernie Innocenti55864192018-08-30 04:05:20 +0900907
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900908 if (hf == NULL) {
909 *he = NETDB_INTERNAL;
910 errno = EINVAL;
911 return NULL;
912 }
913 p = NULL;
914 setup(aliases, maxaliases);
Bernie Innocenti55864192018-08-30 04:05:20 +0900915
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900916 /* Allocate a new space to read file lines like upstream does.
917 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
918 * as the buffer may be used to store content for a previous hostent
919 * returned by non-reentrant functions like gethostbyname().
920 */
921 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
922 if ((p = malloc(line_buf_size)) == NULL) {
923 goto nospc;
924 }
925 for (;;) {
926 if (!fgets(p, line_buf_size, hf)) {
927 free(p);
928 free(aliases);
929 *he = HOST_NOT_FOUND;
930 return NULL;
931 }
932 if (*p == '#') {
933 continue;
934 }
935 if (!(cp = strpbrk(p, "#\n"))) {
936 continue;
937 }
938 *cp = '\0';
939 if (!(cp = strpbrk(p, " \t"))) continue;
940 *cp++ = '\0';
941 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
942 af = AF_INET6;
943 len = NS_IN6ADDRSZ;
944 } else {
945 if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900946
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900947 res_state res = __res_get_state();
948 if (res == NULL) goto nospc;
949 if (res->options & RES_USE_INET6) {
950 map_v4v6_address(buf, buf);
951 af = AF_INET6;
952 len = NS_IN6ADDRSZ;
953 } else {
954 af = AF_INET;
955 len = NS_INADDRSZ;
956 }
957 __res_put_state(res);
958 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900959
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900960 /* if this is not something we're looking for, skip it. */
961 if (hent->h_addrtype != 0 && hent->h_addrtype != af) continue;
962 if (hent->h_length != 0 && hent->h_length != len) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900963
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900964 while (*cp == ' ' || *cp == '\t') cp++;
965 if ((cp = strpbrk(name = cp, " \t")) != NULL) *cp++ = '\0';
966 q = aliases;
967 while (cp && *cp) {
968 if (*cp == ' ' || *cp == '\t') {
969 cp++;
970 continue;
971 }
972 addalias(q, cp, aliases, maxaliases);
973 if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0';
974 }
975 break;
976 }
977 hent->h_length = len;
978 hent->h_addrtype = af;
979 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
980 anum = (size_t)(q - aliases);
981 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
982 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, buflen);
983 hent->h_addr_list[1] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900984
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900985 HENT_SCOPY(hent->h_name, name, buf, buflen);
986 for (size_t i = 0; i < anum; i++) HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
987 hent->h_aliases[anum] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900988
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900989 *he = NETDB_SUCCESS;
990 free(p);
991 free(aliases);
992 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900993nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900994 free(p);
995 free(aliases);
996 errno = ENOSPC;
997 *he = NETDB_INTERNAL;
998 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900999}
1000
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001001static void map_v4v6_address(const char* src, char* dst) {
1002 u_char* p = (u_char*) dst;
1003 char tmp[NS_INADDRSZ];
1004 int i;
Bernie Innocenti55864192018-08-30 04:05:20 +09001005
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001006 _DIAGASSERT(src != NULL);
1007 _DIAGASSERT(dst != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001008
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001009 /* Stash a temporary copy so our caller can update in place. */
1010 (void) memcpy(tmp, src, NS_INADDRSZ);
1011 /* Mark this ipv6 addr as a mapped ipv4. */
1012 for (i = 0; i < 10; i++) *p++ = 0x00;
1013 *p++ = 0xff;
1014 *p++ = 0xff;
1015 /* Retrieve the saved copy and we're done. */
1016 (void) memcpy(p, tmp, NS_INADDRSZ);
Bernie Innocenti55864192018-08-30 04:05:20 +09001017}
1018
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001019static void map_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) {
1020 char** ap;
Bernie Innocenti55864192018-08-30 04:05:20 +09001021
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001022 _DIAGASSERT(hp != NULL);
1023 _DIAGASSERT(bpp != NULL);
1024 _DIAGASSERT(ep != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001025
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001026 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return;
1027 hp->h_addrtype = AF_INET6;
1028 hp->h_length = NS_IN6ADDRSZ;
1029 for (ap = hp->h_addr_list; *ap; ap++) {
1030 int i = (int) (sizeof(align) - (size_t)((u_long) *bpp % sizeof(align)));
Bernie Innocenti55864192018-08-30 04:05:20 +09001031
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001032 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
1033 /* Out of memory. Truncate address list here. XXX */
1034 *ap = NULL;
1035 return;
1036 }
1037 *bpp += i;
1038 map_v4v6_address(*ap, *bpp);
1039 *ap = *bpp;
1040 *bpp += NS_IN6ADDRSZ;
1041 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001042}
1043
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001044static void addrsort(char** ap, int num, res_state res) {
1045 int i, j;
1046 char** p;
1047 short aval[MAXADDRS];
1048 int needsort = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +09001049
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001050 _DIAGASSERT(ap != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001051
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001052 p = ap;
1053 for (i = 0; i < num; i++, p++) {
1054 for (j = 0; (unsigned) j < res->nsort; j++)
1055 if (res->sort_list[j].addr.s_addr ==
1056 (((struct in_addr*) (void*) (*p))->s_addr & res->sort_list[j].mask))
1057 break;
1058 aval[i] = j;
1059 if (needsort == 0 && i > 0 && j < aval[i - 1]) needsort = i;
1060 }
1061 if (!needsort) return;
Bernie Innocenti55864192018-08-30 04:05:20 +09001062
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001063 while (needsort < num) {
1064 for (j = needsort - 1; j >= 0; j--) {
1065 if (aval[j] > aval[j + 1]) {
1066 char* hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001067
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001068 i = aval[j];
1069 aval[j] = aval[j + 1];
1070 aval[j + 1] = i;
Bernie Innocenti55864192018-08-30 04:05:20 +09001071
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001072 hp = ap[j];
1073 ap[j] = ap[j + 1];
1074 ap[j + 1] = hp;
1075 } else
1076 break;
1077 }
1078 needsort++;
1079 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001080}
1081
1082/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001083static int _dns_gethtbyname(void* rv, void* cb_data, va_list ap) {
1084 querybuf* buf;
1085 int n, type;
1086 struct hostent* hp;
1087 const char* name;
1088 res_state res;
1089 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +09001090
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001091 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001092
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001093 name = va_arg(ap, char*);
1094 /* NOSTRICT skip string len */ (void) va_arg(ap, int);
1095 info->hp->h_addrtype = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +09001096
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001097 switch (info->hp->h_addrtype) {
1098 case AF_INET:
1099 info->hp->h_length = NS_INADDRSZ;
1100 type = T_A;
1101 break;
1102 case AF_INET6:
1103 info->hp->h_length = NS_IN6ADDRSZ;
1104 type = T_AAAA;
1105 break;
1106 default:
1107 return NS_UNAVAIL;
1108 }
1109 buf = malloc(sizeof(*buf));
1110 if (buf == NULL) {
1111 *info->he = NETDB_INTERNAL;
1112 return NS_NOTFOUND;
1113 }
1114 res = __res_get_state();
1115 if (res == NULL) {
1116 free(buf);
1117 return NS_NOTFOUND;
1118 }
1119 n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf));
1120 if (n < 0) {
1121 free(buf);
1122 debugprintf("res_nsearch failed (%d)\n", res, n);
1123 __res_put_state(res);
1124 return NS_NOTFOUND;
1125 }
1126 hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, info->he);
1127 free(buf);
1128 __res_put_state(res);
1129 if (hp == NULL) switch (*info->he) {
1130 case HOST_NOT_FOUND:
1131 return NS_NOTFOUND;
1132 case TRY_AGAIN:
1133 return NS_TRYAGAIN;
1134 default:
1135 return NS_UNAVAIL;
1136 }
1137 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001138}
1139
1140/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001141static int _dns_gethtbyaddr(void* rv, void* cb_data, va_list ap) {
1142 char qbuf[MAXDNAME + 1], *qp, *ep;
1143 int n;
1144 querybuf* buf;
1145 struct hostent* hp;
1146 const unsigned char* uaddr;
1147 int advance;
1148 res_state res;
1149 char* bf;
1150 size_t blen;
1151 struct getnamaddr* info = rv;
1152 const struct android_net_context* netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +09001153
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001154 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001155
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001156 uaddr = va_arg(ap, unsigned char*);
1157 info->hp->h_length = va_arg(ap, int);
1158 info->hp->h_addrtype = va_arg(ap, int);
1159 netcontext = va_arg(ap, const struct android_net_context*);
Bernie Innocenti55864192018-08-30 04:05:20 +09001160
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001161 switch (info->hp->h_addrtype) {
1162 case AF_INET:
1163 (void) snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
1164 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1165 break;
Bernie Innocenti55864192018-08-30 04:05:20 +09001166
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001167 case AF_INET6:
1168 qp = qbuf;
1169 ep = qbuf + sizeof(qbuf) - 1;
1170 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
1171 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", uaddr[n] & 0xf,
1172 ((unsigned int) uaddr[n] >> 4) & 0xf);
1173 if (advance > 0 && qp + advance < ep)
1174 qp += advance;
1175 else {
1176 *info->he = NETDB_INTERNAL;
1177 return NS_NOTFOUND;
1178 }
1179 }
1180 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
1181 *info->he = NETDB_INTERNAL;
1182 return NS_NOTFOUND;
1183 }
1184 break;
1185 default:
1186 return NS_UNAVAIL;
1187 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001188
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001189 buf = malloc(sizeof(*buf));
1190 if (buf == NULL) {
1191 *info->he = NETDB_INTERNAL;
1192 return NS_NOTFOUND;
1193 }
1194 res = __res_get_state();
1195 if (res == NULL) {
1196 free(buf);
1197 return NS_NOTFOUND;
1198 }
1199 res_setnetcontext(res, netcontext);
1200 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf));
1201 if (n < 0) {
1202 free(buf);
1203 debugprintf("res_nquery failed (%d)\n", res, n);
1204 __res_put_state(res);
1205 return NS_NOTFOUND;
1206 }
1207 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
1208 free(buf);
1209 if (hp == NULL) {
1210 __res_put_state(res);
1211 switch (*info->he) {
1212 case HOST_NOT_FOUND:
1213 return NS_NOTFOUND;
1214 case TRY_AGAIN:
1215 return NS_TRYAGAIN;
1216 default:
1217 return NS_UNAVAIL;
1218 }
1219 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001220
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001221 bf = (void*) (hp->h_addr_list + 2);
1222 blen = (size_t)(bf - info->buf);
1223 if (blen + info->hp->h_length > info->buflen) goto nospc;
1224 hp->h_addr_list[0] = bf;
1225 hp->h_addr_list[1] = NULL;
1226 (void) memcpy(bf, uaddr, (size_t) info->hp->h_length);
1227 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1228 if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
1229 map_v4v6_address(bf, bf);
1230 hp->h_addrtype = AF_INET6;
1231 hp->h_length = NS_IN6ADDRSZ;
1232 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001233
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001234 __res_put_state(res);
1235 *info->he = NETDB_SUCCESS;
1236 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001237nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001238 errno = ENOSPC;
1239 *info->he = NETDB_INTERNAL;
1240 return NS_UNAVAIL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001241}
1242
1243#ifdef YP
1244/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001245static struct hostent* _yp_hostent(char* line, int af, struct getnamaddr* info) {
1246 struct in6_addr host_addrs[MAXADDRS];
1247 char** aliases;
1248 size_t maxaliases;
1249 char* p = line;
1250 char *cp, **q, *ptr;
1251 size_t len, anum, i;
1252 int addrok;
1253 int more;
1254 size_t naddrs;
1255 struct hostent* hp = info->hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001256
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001257 _DIAGASSERT(line != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001258
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001259 hp->h_name = NULL;
1260 hp->h_addrtype = af;
1261 switch (af) {
1262 case AF_INET:
1263 hp->h_length = NS_INADDRSZ;
1264 break;
1265 case AF_INET6:
1266 hp->h_length = NS_IN6ADDRSZ;
1267 break;
1268 default:
1269 return NULL;
1270 }
1271 setup(aliases, maxaliases);
1272 naddrs = 0;
1273 q = aliases;
Bernie Innocenti55864192018-08-30 04:05:20 +09001274
1275nextline:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001276 /* check for host_addrs overflow */
1277 if (naddrs >= __arraycount(host_addrs)) goto done;
Bernie Innocenti55864192018-08-30 04:05:20 +09001278
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001279 more = 0;
1280 cp = strpbrk(p, " \t");
1281 if (cp == NULL) goto done;
1282 *cp++ = '\0';
Bernie Innocenti55864192018-08-30 04:05:20 +09001283
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001284 /* p has should have an address */
1285 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1286 if (addrok != 1) {
1287 /* skip to the next line */
1288 while (cp && *cp) {
1289 if (*cp == '\n') {
1290 cp++;
1291 goto nextline;
1292 }
1293 cp++;
1294 }
1295 goto done;
1296 }
1297 naddrs++;
Bernie Innocenti55864192018-08-30 04:05:20 +09001298
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001299 while (*cp == ' ' || *cp == '\t') cp++;
1300 p = cp;
1301 cp = strpbrk(p, " \t\n");
1302 if (cp != NULL) {
1303 if (*cp == '\n') more = 1;
1304 *cp++ = '\0';
1305 }
1306 if (!hp->h_name)
1307 hp->h_name = p;
1308 else if (strcmp(hp->h_name, p) == 0)
1309 ;
1310 else
1311 addalias(q, p, aliases, maxaliases);
1312 p = cp;
1313 if (more) goto nextline;
Bernie Innocenti55864192018-08-30 04:05:20 +09001314
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001315 while (cp && *cp) {
1316 if (*cp == ' ' || *cp == '\t') {
1317 cp++;
1318 continue;
1319 }
1320 if (*cp == '\n') {
1321 cp++;
1322 goto nextline;
1323 }
1324 addalias(q, cp, aliases, maxaliases);
1325 cp = strpbrk(cp, " \t");
1326 if (cp != NULL) *cp++ = '\0';
1327 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001328
1329done:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001330 if (hp->h_name == NULL) {
1331 free(aliases);
1332 return NULL;
1333 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001334
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001335 ptr = info->buf;
1336 len = info->buflen;
Bernie Innocenti55864192018-08-30 04:05:20 +09001337
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001338 anum = (size_t)(q - aliases);
1339 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1340 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
Bernie Innocenti55864192018-08-30 04:05:20 +09001341
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001342 for (i = 0; i < naddrs; i++)
1343 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length, ptr, len);
1344 hp->h_addr_list[naddrs] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001345
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001346 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
Bernie Innocenti55864192018-08-30 04:05:20 +09001347
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001348 for (i = 0; i < anum; i++) HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1349 hp->h_aliases[anum] = NULL;
1350 free(aliases);
Bernie Innocenti55864192018-08-30 04:05:20 +09001351
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001352 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001353nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001354 free(aliases);
1355 *info->he = NETDB_INTERNAL;
1356 errno = ENOSPC;
1357 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001358}
1359
1360/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001361int _yp_gethtbyaddr(void* rv, void* cb_data, va_list ap) {
1362 struct hostent* hp = NULL;
1363 char* ypcurrent;
1364 int ypcurrentlen, r;
1365 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1366 const unsigned char* uaddr;
1367 int af;
1368 const char* map;
1369 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +09001370
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001371 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001372
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001373 uaddr = va_arg(ap, unsigned char*);
1374 /* NOSTRICT skip len */ (void) va_arg(ap, int);
1375 af = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +09001376
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001377 if (!__ypdomain) {
1378 if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL;
1379 }
1380 /*
1381 * XXX unfortunately, we cannot support IPv6 extended scoped address
1382 * notation here. gethostbyaddr() is not scope-aware. too bad.
1383 */
1384 if (inet_ntop(af, uaddr, name, (socklen_t) sizeof(name)) == NULL) return NS_UNAVAIL;
1385 switch (af) {
1386 case AF_INET:
1387 map = "hosts.byaddr";
1388 break;
1389 default:
1390 map = "ipnodes.byaddr";
1391 break;
1392 }
1393 ypcurrent = NULL;
1394 r = yp_match(__ypdomain, map, name, (int) strlen(name), &ypcurrent, &ypcurrentlen);
1395 if (r == 0)
1396 hp = _yp_hostent(ypcurrent, af, info);
1397 else
1398 hp = NULL;
1399 free(ypcurrent);
1400 if (hp == NULL) {
1401 *info->he = HOST_NOT_FOUND;
1402 return NS_NOTFOUND;
1403 }
1404 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001405}
1406
1407/*ARGSUSED*/
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001408int _yp_gethtbyname(void* rv, void* cb_data, va_list ap) {
1409 struct hostent* hp;
1410 char* ypcurrent;
1411 int ypcurrentlen, r;
1412 const char* name;
1413 int af;
1414 const char* map;
1415 struct getnamaddr* info = rv;
Bernie Innocenti55864192018-08-30 04:05:20 +09001416
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001417 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +09001418
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001419 name = va_arg(ap, char*);
1420 /* NOSTRICT skip string len */ (void) va_arg(ap, int);
1421 af = va_arg(ap, int);
Bernie Innocenti55864192018-08-30 04:05:20 +09001422
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001423 if (!__ypdomain) {
1424 if (_yp_check(&__ypdomain) == 0) return NS_UNAVAIL;
1425 }
1426 switch (af) {
1427 case AF_INET:
1428 map = "hosts.byname";
1429 break;
1430 default:
1431 map = "ipnodes.byname";
1432 break;
1433 }
1434 ypcurrent = NULL;
1435 r = yp_match(__ypdomain, map, name, (int) strlen(name), &ypcurrent, &ypcurrentlen);
1436 if (r == 0)
1437 hp = _yp_hostent(ypcurrent, af, info);
1438 else
1439 hp = NULL;
1440 free(ypcurrent);
1441 if (hp == NULL) {
1442 *info->he = HOST_NOT_FOUND;
1443 return NS_NOTFOUND;
1444 }
1445 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +09001446}
1447#endif
1448
1449/*
1450 * Non-reentrant versions.
1451 */
1452
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001453struct hostent* gethostbyname(const char* name) {
1454 struct hostent* result = NULL;
1455 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Bernie Innocenti55864192018-08-30 04:05:20 +09001456
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001457 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1458 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001459}
1460
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001461struct hostent* gethostbyname2(const char* name, int af) {
1462 struct hostent* result = NULL;
1463 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Bernie Innocenti55864192018-08-30 04:05:20 +09001464
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001465 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1466 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001467}
1468
1469// android_gethostby*fornet can be called in two different contexts.
1470// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1471// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1472// The netcontext is constructed before checking which context we are in.
1473// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1474// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1475static struct android_net_context make_context(unsigned netid, unsigned mark) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001476 struct android_net_context netcontext = NETCONTEXT_UNSET;
1477 netcontext.app_netid = netid;
1478 netcontext.app_mark = mark;
1479 netcontext.dns_netid = netid;
1480 netcontext.dns_mark = mark;
1481 return netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +09001482}
1483
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001484struct hostent* android_gethostbynamefornet(const char* name, int af, unsigned netid,
1485 unsigned mark) {
1486 const struct android_net_context netcontext = make_context(netid, mark);
1487 return android_gethostbynamefornetcontext(name, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001488}
1489
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001490struct hostent* android_gethostbynamefornetcontext(const char* name, int af,
1491 const struct android_net_context* netcontext) {
1492 struct hostent* hp;
1493 res_state res = __res_get_state();
1494 if (res == NULL) return NULL;
1495 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1496 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
1497 &h_errno, netcontext);
1498 __res_put_state(res);
1499 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001500}
1501
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001502struct hostent* gethostbyaddr(const void* addr, socklen_t len, int af) {
1503 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Bernie Innocenti55864192018-08-30 04:05:20 +09001504}
1505
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001506struct hostent* android_gethostbyaddrfornet(const void* addr, socklen_t len, int af, unsigned netid,
1507 unsigned mark) {
1508 const struct android_net_context netcontext = make_context(netid, mark);
1509 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001510}
1511
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001512struct hostent* android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
1513 const struct android_net_context* netcontext) {
1514 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001515}
1516
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001517__LIBC_HIDDEN__ struct hostent* android_gethostbyaddrfornetcontext_proxy(
1518 const void* addr, socklen_t len, int af, const struct android_net_context* netcontext) {
1519 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1520 return android_gethostbyaddrfornetcontext_proxy_internal(
1521 addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001522}
1523
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001524struct hostent* gethostent(void) {
1525 res_static rs = __res_get_static();
1526 if (!rs->hostf) {
1527 sethostent_r(&rs->hostf);
1528 if (!rs->hostf) {
1529 h_errno = NETDB_INTERNAL;
1530 return NULL;
1531 }
1532 }
1533 memset(&rs->host, 0, sizeof(rs->host));
1534 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno);
Bernie Innocenti55864192018-08-30 04:05:20 +09001535}