blob: add124f52ef8d1f504cdb5004d0fe437ac7eba13 [file] [log] [blame]
Yabin Cui58d33a52014-12-16 17:03:44 -08001/* $NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $ */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002
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
57#include <sys/param.h>
58#include <sys/socket.h>
Mattias Falkc63e5902011-08-23 14:34:14 +020059#include <sys/un.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080060#include <netinet/in.h>
61#include <arpa/inet.h>
Calin Juravle569fb982014-03-04 15:01:29 +000062#include <arpa/nameser.h>
Paul Jensen5240b562014-05-15 14:43:07 -040063#include "NetdClientDispatch.h"
Szymon Jakubczakea9bf672014-02-14 17:07:23 -050064#include "resolv_netid.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080065#include "resolv_private.h"
66#include "resolv_cache.h"
67#include <assert.h>
68#include <ctype.h>
69#include <errno.h>
70#include <netdb.h>
71#include <stdarg.h>
Elliott Hughes9773fa32014-12-10 14:56:46 -080072#include <stdbool.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080073#include <stdio.h>
Carl Shapiro2cc2b2b2011-03-21 20:01:03 -070074#include <strings.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080075#include <syslog.h>
Mattias Falkc63e5902011-08-23 14:34:14 +020076#include <unistd.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080077
78#ifndef LOG_AUTH
79# define LOG_AUTH 0
80#endif
81
82#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
83
84#include "nsswitch.h"
85#include <stdlib.h>
86#include <string.h>
87
Yabin Cui58d33a52014-12-16 17:03:44 -080088#include "hostent.h"
89
Lev Rumyantsev814f38f2020-10-12 17:33:06 -070090#include "private/bionic_defs.h"
91
Yabin Cui58d33a52014-12-16 17:03:44 -080092#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
93 (ok)(nm) != 0)
94#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
95#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
96
97#define addalias(d, s, arr, siz) do { \
98 if (d >= &arr[siz]) { \
99 char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
100 if (xptr == NULL) \
101 goto nospc; \
102 d = xptr + (d - arr); \
103 arr = xptr; \
104 siz += 10; \
105 } \
106 *d++ = s; \
107} while (/*CONSTCOND*/0)
108
109#define setup(arr, siz) do { \
110 arr = malloc((siz = 10) * sizeof(*arr)); \
111 if (arr == NULL) \
112 goto nospc; \
113} while (/*CONSTCOND*/0)
114
Mattias Falkc63e5902011-08-23 14:34:14 +0200115// This should be synchronized to ResponseCode.h
116static const int DnsProxyQueryResult = 222;
117
Elliott Hughes68c27552014-07-07 09:44:17 -0700118static const char AskedForGot[] =
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800119 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
120
Ben Schwartz50178052017-04-24 17:57:11 -0400121static const struct android_net_context NETCONTEXT_UNSET = {
122 .app_mark = MARK_UNSET,
123 .app_netid = NETID_UNSET,
124 .dns_mark = MARK_UNSET,
125 .dns_netid = NETID_UNSET,
126 .uid = NET_CONTEXT_INVALID_UID
127};
128
Ben Schwartz47fb0e82018-01-31 13:35:03 -0500129#define MAXPACKET (8*1024)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800130
131typedef union {
132 HEADER hdr;
133 u_char buf[MAXPACKET];
134} querybuf;
135
136typedef union {
137 int32_t al;
138 char ac;
139} align;
140
141#ifdef DEBUG
Yabin Cui58d33a52014-12-16 17:03:44 -0800142static void debugprintf(const char *, res_state, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800143 __attribute__((__format__(__printf__, 1, 3)));
144#endif
145static struct hostent *getanswer(const querybuf *, int, const char *, int,
Yabin Cui58d33a52014-12-16 17:03:44 -0800146 res_state, struct hostent *, char *, size_t, int *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800147static void map_v4v6_address(const char *, char *);
148static void map_v4v6_hostent(struct hostent *, char **, char *);
149static void addrsort(char **, int, res_state);
150
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800151void ht_sethostent(int);
152void ht_endhostent(void);
153struct hostent *ht_gethostbyname(char *);
154struct hostent *ht_gethostbyaddr(const char *, int, int);
155void dns_service(void);
156#undef dn_skipname
157int dn_skipname(const u_char *, const u_char *);
Jim Huange5c35e02010-09-27 23:37:10 +0800158static int _dns_gethtbyaddr(void *, void *, va_list);
159static int _dns_gethtbyname(void *, void *, va_list);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800160
Yabin Cui58d33a52014-12-16 17:03:44 -0800161static struct hostent *gethostbyname_internal(const char *, int, res_state,
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400162 struct hostent *, char *, size_t, int *, const struct android_net_context *);
Ben Schwartz50178052017-04-24 17:57:11 -0400163static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t,
164 int, struct hostent *, char *, size_t, int *, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800165
166static const ns_src default_dns_files[] = {
167 { NSSRC_FILES, NS_SUCCESS },
168 { NSSRC_DNS, NS_SUCCESS },
169 { 0, 0 }
170};
171
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700172static int h_errno_to_result(int* herrno_p) {
173 // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
174 if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
175 errno = ERANGE;
176 return errno;
177 }
178 // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
179 return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
180}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800181
182#ifdef DEBUG
183static void
Yabin Cui58d33a52014-12-16 17:03:44 -0800184debugprintf(const char *msg, res_state res, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800185{
Yabin Cui58d33a52014-12-16 17:03:44 -0800186 _DIAGASSERT(msg != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800187
188 if (res->options & RES_DEBUG) {
189 int save = errno;
190 va_list ap;
191
192 va_start (ap, res);
193 vprintf(msg, ap);
194 va_end (ap);
195
196 errno = save;
197 }
198}
199#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800200# define debugprintf(msg, res, num) /*nada*/
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800201#endif
202
203#define BOUNDED_INCR(x) \
204 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800205 BOUNDS_CHECK(cp, x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800206 cp += (x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800207 } while (/*CONSTCOND*/0)
208
209#define BOUNDS_CHECK(ptr, count) \
210 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800211 if (eom - (ptr) < (count)) \
Yabin Cui58d33a52014-12-16 17:03:44 -0800212 goto no_recovery; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800213 } while (/*CONSTCOND*/0)
214
215static struct hostent *
216getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
Yabin Cui58d33a52014-12-16 17:03:44 -0800217 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800218{
219 const HEADER *hp;
220 const u_char *cp;
221 int n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800222 size_t qlen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800223 const u_char *eom, *erdata;
224 char *bp, **ap, **hap, *ep;
225 int type, class, ancount, qdcount;
226 int haveanswer, had_error;
227 int toobig = 0;
228 char tbuf[MAXDNAME];
Yabin Cui58d33a52014-12-16 17:03:44 -0800229 char **aliases;
230 size_t maxaliases;
231 char *addr_ptrs[MAXADDRS];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800232 const char *tname;
233 int (*name_ok)(const char *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800234
Yabin Cui58d33a52014-12-16 17:03:44 -0800235 _DIAGASSERT(answer != NULL);
236 _DIAGASSERT(qname != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800237
238 tname = qname;
Yabin Cui58d33a52014-12-16 17:03:44 -0800239 hent->h_name = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800240 eom = answer->buf + anslen;
241 switch (qtype) {
242 case T_A:
243 case T_AAAA:
244 name_ok = res_hnok;
245 break;
246 case T_PTR:
247 name_ok = res_dnok;
248 break;
249 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800250 *he = NO_RECOVERY;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800251 return NULL; /* XXX should be abort(); */
252 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800253
254 setup(aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800255 /*
256 * find first satisfactory answer
257 */
258 hp = &answer->hdr;
259 ancount = ntohs(hp->ancount);
260 qdcount = ntohs(hp->qdcount);
Yabin Cui58d33a52014-12-16 17:03:44 -0800261 bp = buf;
262 ep = buf + buflen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800263 cp = answer->buf;
264 BOUNDED_INCR(HFIXEDSZ);
Yabin Cui58d33a52014-12-16 17:03:44 -0800265 if (qdcount != 1)
266 goto no_recovery;
267
268 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
269 if ((n < 0) || !maybe_ok(res, bp, name_ok))
270 goto no_recovery;
271
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800272 BOUNDED_INCR(n + QFIXEDSZ);
273 if (qtype == T_A || qtype == T_AAAA) {
274 /* res_send() has already verified that the query name is the
275 * same as the one we sent; this just gets the expanded name
276 * (i.e., with the succeeding search-domain tacked on).
277 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800278 n = (int)strlen(bp) + 1; /* for the \0 */
279 if (n >= MAXHOSTNAMELEN)
280 goto no_recovery;
281 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800282 bp += n;
283 /* The qname can be abbreviated, but h_name is now absolute. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800284 qname = hent->h_name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800285 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800286 hent->h_aliases = ap = aliases;
287 hent->h_addr_list = hap = addr_ptrs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800288 *ap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800289 *hap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800290 haveanswer = 0;
291 had_error = 0;
292 while (ancount-- > 0 && cp < eom && !had_error) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800293 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
294 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800295 had_error++;
296 continue;
297 }
298 cp += n; /* name */
299 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
300 type = _getshort(cp);
301 cp += INT16SZ; /* type */
302 class = _getshort(cp);
303 cp += INT16SZ + INT32SZ; /* class, TTL */
304 n = _getshort(cp);
305 cp += INT16SZ; /* len */
306 BOUNDS_CHECK(cp, n);
307 erdata = cp + n;
308 if (class != C_IN) {
309 /* XXX - debug? syslog? */
310 cp += n;
311 continue; /* XXX - had_error++ ? */
312 }
313 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800314 n = dn_expand(answer->buf, eom, cp, tbuf,
315 (int)sizeof tbuf);
316 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800317 had_error++;
318 continue;
319 }
320 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800321 if (cp != erdata)
322 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800323 /* Store alias. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800324 addalias(ap, bp, aliases, maxaliases);
325 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800326 if (n >= MAXHOSTNAMELEN) {
327 had_error++;
328 continue;
329 }
330 bp += n;
331 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800332 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800333 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
334 had_error++;
335 continue;
336 }
337 strlcpy(bp, tbuf, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800338 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800339 bp += n;
340 continue;
341 }
342 if (qtype == T_PTR && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800343 n = dn_expand(answer->buf, eom, cp, tbuf,
344 (int)sizeof tbuf);
345 if (n < 0 || !maybe_dnok(res, tbuf)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800346 had_error++;
347 continue;
348 }
349 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800350 if (cp != erdata)
351 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800352 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800353 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800354 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
355 had_error++;
356 continue;
357 }
358 strlcpy(bp, tbuf, (size_t)(ep - bp));
359 tname = bp;
360 bp += n;
361 continue;
362 }
363 if (type != qtype) {
364 if (type != T_KEY && type != T_SIG)
365 syslog(LOG_NOTICE|LOG_AUTH,
366 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
367 qname, p_class(C_IN), p_type(qtype),
368 p_type(type));
369 cp += n;
370 continue; /* XXX - had_error++ ? */
371 }
372 switch (type) {
373 case T_PTR:
374 if (strcasecmp(tname, bp) != 0) {
375 syslog(LOG_NOTICE|LOG_AUTH,
376 AskedForGot, qname, bp);
377 cp += n;
378 continue; /* XXX - had_error++ ? */
379 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800380 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
381 if ((n < 0) || !maybe_hnok(res, bp)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800382 had_error++;
383 break;
384 }
385#if MULTI_PTRS_ARE_ALIASES
386 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800387 if (cp != erdata)
388 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800389 if (!haveanswer)
Yabin Cui58d33a52014-12-16 17:03:44 -0800390 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800391 else
Yabin Cui58d33a52014-12-16 17:03:44 -0800392 addalias(ap, bp, aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800393 if (n != -1) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800394 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800395 if (n >= MAXHOSTNAMELEN) {
396 had_error++;
397 break;
398 }
399 bp += n;
400 }
401 break;
402#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800403 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800404 if (res->options & RES_USE_INET6) {
405 n = strlen(bp) + 1; /* for the \0 */
406 if (n >= MAXHOSTNAMELEN) {
407 had_error++;
408 break;
409 }
410 bp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800411 map_v4v6_hostent(hent, &bp, ep);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800412 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800413 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800414#endif
415 case T_A:
416 case T_AAAA:
Yabin Cui58d33a52014-12-16 17:03:44 -0800417 if (strcasecmp(hent->h_name, bp) != 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800418 syslog(LOG_NOTICE|LOG_AUTH,
Yabin Cui58d33a52014-12-16 17:03:44 -0800419 AskedForGot, hent->h_name, bp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800420 cp += n;
421 continue; /* XXX - had_error++ ? */
422 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800423 if (n != hent->h_length) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800424 cp += n;
425 continue;
426 }
427 if (type == T_AAAA) {
428 struct in6_addr in6;
Yabin Cui58d33a52014-12-16 17:03:44 -0800429 memcpy(&in6, cp, NS_IN6ADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800430 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
431 cp += n;
432 continue;
433 }
434 }
435 if (!haveanswer) {
436 int nn;
437
Yabin Cui58d33a52014-12-16 17:03:44 -0800438 hent->h_name = bp;
439 nn = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800440 bp += nn;
441 }
442
443 bp += sizeof(align) -
444 (size_t)((u_long)bp % sizeof(align));
445
Yabin Cui58d33a52014-12-16 17:03:44 -0800446 if (bp + n >= ep) {
447 debugprintf("size (%d) too big\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800448 had_error++;
449 continue;
450 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800451 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
452 if (!toobig++) {
453 debugprintf("Too many addresses (%d)\n",
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800454 res, MAXADDRS);
Yabin Cui58d33a52014-12-16 17:03:44 -0800455 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800456 cp += n;
457 continue;
458 }
459 (void)memcpy(*hap++ = bp, cp, (size_t)n);
460 bp += n;
461 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800462 if (cp != erdata)
463 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800464 break;
465 default:
466 abort();
467 }
468 if (!had_error)
469 haveanswer++;
470 }
471 if (haveanswer) {
472 *ap = NULL;
473 *hap = NULL;
474 /*
475 * Note: we sort even if host can take only one address
476 * in its return structures - should give it the "best"
477 * address in that case, not some random one
478 */
479 if (res->nsort && haveanswer > 1 && qtype == T_A)
Yabin Cui58d33a52014-12-16 17:03:44 -0800480 addrsort(addr_ptrs, haveanswer, res);
481 if (!hent->h_name) {
482 n = (int)strlen(qname) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800483 if (n > ep - bp || n >= MAXHOSTNAMELEN)
484 goto no_recovery;
485 strlcpy(bp, qname, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800486 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800487 bp += n;
488 }
489 if (res->options & RES_USE_INET6)
Yabin Cui58d33a52014-12-16 17:03:44 -0800490 map_v4v6_hostent(hent, &bp, ep);
491 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800492 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800493no_recovery:
494 free(aliases);
495 *he = NO_RECOVERY;
496 return NULL;
497success:
498 bp = (char *)ALIGN(bp);
499 n = (int)(ap - aliases);
500 qlen = (n + 1) * sizeof(*hent->h_aliases);
501 if ((size_t)(ep - bp) < qlen)
502 goto nospc;
503 hent->h_aliases = (void *)bp;
504 memcpy(bp, aliases, qlen);
505 free(aliases);
506 aliases = NULL;
507
508 bp += qlen;
509 n = (int)(hap - addr_ptrs);
510 qlen = (n + 1) * sizeof(*hent->h_addr_list);
511 if ((size_t)(ep - bp) < qlen)
512 goto nospc;
513 hent->h_addr_list = (void *)bp;
514 memcpy(bp, addr_ptrs, qlen);
515 *he = NETDB_SUCCESS;
516 return hent;
517nospc:
518 free(aliases);
519 errno = ENOSPC;
520 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800521 return NULL;
522}
523
Yabin Cui58d33a52014-12-16 17:03:44 -0800524/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800525int
526gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
Yabin Cui58d33a52014-12-16 17:03:44 -0800527 struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800528{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800529 res_state res = __res_get_state();
Yabin Cui58d33a52014-12-16 17:03:44 -0800530 if (res == NULL) {
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700531 *result = NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800532 *errorp = NETDB_INTERNAL;
533 return -1;
534 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800535
Yabin Cui58d33a52014-12-16 17:03:44 -0800536 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800537
538 if (res->options & RES_USE_INET6) {
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400539 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
540 &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -0800541 if (*result) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800542 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800543 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800544 }
545 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400546 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp,
547 &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700548 return h_errno_to_result(errorp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800549}
550
Yabin Cui58d33a52014-12-16 17:03:44 -0800551/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
552int
553gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
554 size_t buflen, struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800555{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800556 res_state res = __res_get_state();
Yabin Cui58d33a52014-12-16 17:03:44 -0800557 if (res == NULL) {
558 *result = NULL;
559 *errorp = NETDB_INTERNAL;
560 return -1;
561 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400562 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp,
563 &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700564 return h_errno_to_result(errorp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800565}
566
567static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800568android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200569{
570 uint32_t size;
571 char buf[4];
572 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
573
Elliott Hughes9773fa32014-12-10 14:56:46 -0800574 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp
575 // and changes here need to be matched there.
Mattias Falkc63e5902011-08-23 14:34:14 +0200576 int result_code = strtol(buf, NULL, 10);
577 if (result_code != DnsProxyQueryResult) {
578 fread(&size, 1, sizeof(size), proxy);
Yabin Cui58d33a52014-12-16 17:03:44 -0800579 *he = HOST_NOT_FOUND;
Mattias Falkc63e5902011-08-23 14:34:14 +0200580 return NULL;
581 }
582
583 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
584 size = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200585
Yabin Cui58d33a52014-12-16 17:03:44 -0800586 memset(hp, 0, sizeof(*hp));
587 char *ptr = hbuf;
588 char *hbuf_end = hbuf + hbuflen;
589
590 if (ptr + size > hbuf_end) {
591 goto nospc;
592 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200593 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800594 hp->h_name = ptr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200595 ptr += size;
Mattias Falkc63e5902011-08-23 14:34:14 +0200596
Yabin Cui58d33a52014-12-16 17:03:44 -0800597 char *aliases_ptrs[MAXALIASES];
598 char **aliases = &aliases_ptrs[0];
599
Mattias Falkc63e5902011-08-23 14:34:14 +0200600 while (1) {
601 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
602 size = ntohl(size);
603
604 if (size == 0) {
605 *aliases = NULL;
606 break;
607 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800608 if (ptr + size > hbuf_end) {
609 goto nospc;
610 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200611 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800612 if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
613 *aliases++ = ptr;
614 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200615 ptr += size;
616 }
617
Elliott Hughes65dd8582015-07-06 14:16:12 -0700618 // Fix alignment after variable-length data.
619 ptr = (char*)ALIGN(ptr);
620
Yabin Cui58d33a52014-12-16 17:03:44 -0800621 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
622 if (ptr + aliases_len > hbuf_end) {
623 goto nospc;
624 }
625 hp->h_aliases = (void*)ptr;
626 memcpy(ptr, aliases_ptrs, aliases_len);
627 ptr += aliases_len;
Mattias Falkc63e5902011-08-23 14:34:14 +0200628
629 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800630 hp->h_addrtype = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200631
Yabin Cui58d33a52014-12-16 17:03:44 -0800632 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
633 hp->h_length = ntohl(size);
634
635 char *addr_ptrs[MAXADDRS];
636 char **addr_p = &addr_ptrs[0];
637
Mattias Falkc63e5902011-08-23 14:34:14 +0200638 while (1) {
639 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
640 size = ntohl(size);
641 if (size == 0) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800642 *addr_p = NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200643 break;
644 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800645 if (ptr + size > hbuf_end) {
646 goto nospc;
647 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200648 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800649 if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
650 *addr_p++ = ptr;
651 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200652 ptr += size;
653 }
654
Elliott Hughes65dd8582015-07-06 14:16:12 -0700655 // Fix alignment after variable-length data.
656 ptr = (char*)ALIGN(ptr);
657
Yabin Cui58d33a52014-12-16 17:03:44 -0800658 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
659 if (ptr + addrs_len > hbuf_end) {
660 goto nospc;
661 }
662 hp->h_addr_list = (void*)ptr;
663 memcpy(ptr, addr_ptrs, addrs_len);
664 *he = NETDB_SUCCESS;
665 return hp;
666
667nospc:
668 *he = NETDB_INTERNAL;
669 errno = ENOSPC;
670 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200671}
672
Mattias Falkc63e5902011-08-23 14:34:14 +0200673static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800674gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf,
675 size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800676{
677 const char *cp;
Yabin Cui58d33a52014-12-16 17:03:44 -0800678 struct getnamaddr info;
679 char hbuf[MAXHOSTNAMELEN];
680 size_t size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800681 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800682 NS_FILES_CB(_hf_gethtbyname, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800683 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800684 NS_NIS_CB(_yp_gethtbyname, NULL)
685 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800686 };
687
Yabin Cui58d33a52014-12-16 17:03:44 -0800688 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800689
690 switch (af) {
691 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -0800692 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800693 break;
694 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -0800695 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800696 break;
697 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800698 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800699 errno = EAFNOSUPPORT;
700 return NULL;
701 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800702 if (buflen < size)
703 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800704
Yabin Cui58d33a52014-12-16 17:03:44 -0800705 hp->h_addrtype = af;
706 hp->h_length = (int)size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800707
708 /*
709 * if there aren't any dots, it could be a user-level alias.
710 * this is also done in res_nquery() since we are not the only
711 * function that looks up host names.
712 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800713 if (!strchr(name, '.') && (cp = res_hostalias(res, name,
714 hbuf, sizeof(hbuf))))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800715 name = cp;
716
717 /*
718 * disallow names consisting only of digits/dots, unless
719 * they end in a dot.
720 */
721 if (isdigit((u_char) name[0]))
722 for (cp = name;; ++cp) {
723 if (!*cp) {
724 if (*--cp == '.')
725 break;
726 /*
727 * All-numeric, no dot at the end.
728 * Fake up a hostent as if we'd actually
729 * done a lookup.
730 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800731 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800732 }
733 if (!isdigit((u_char) *cp) && *cp != '.')
734 break;
735 }
736 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
737 name[0] == ':')
738 for (cp = name;; ++cp) {
739 if (!*cp) {
740 if (*--cp == '.')
741 break;
742 /*
743 * All-IPv6-legal, no dot at the end.
744 * Fake up a hostent as if we'd actually
745 * done a lookup.
746 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800747 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800748 }
749 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
750 break;
751 }
752
Yabin Cui58d33a52014-12-16 17:03:44 -0800753 *he = NETDB_INTERNAL;
754 info.hp = hp;
755 info.buf = buf;
756 info.buflen = buflen;
757 info.he = he;
758 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
759 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
760 return NULL;
761 *he = NETDB_SUCCESS;
762 return hp;
763nospc:
764 *he = NETDB_INTERNAL;
765 errno = ENOSPC;
766 return NULL;
767fake:
768 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
769 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
770
771 hp->h_aliases[0] = NULL;
772 if (size > buflen)
773 goto nospc;
774
775 if (inet_pton(af, name, buf) <= 0) {
776 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800777 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200778 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800779 hp->h_addr_list[0] = buf;
780 hp->h_addr_list[1] = NULL;
781 buf += size;
782 buflen -= size;
783 HENT_SCOPY(hp->h_name, name, buf, buflen);
784 if (res->options & RES_USE_INET6)
785 map_v4v6_hostent(hp, &buf, buf + buflen);
786 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800787 return hp;
788}
789
Mattias Falkc63e5902011-08-23 14:34:14 +0200790static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800791gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400792 size_t hbuflen, int *errorp, const struct android_net_context *netcontext)
Mattias Falkc63e5902011-08-23 14:34:14 +0200793{
Luke Huange3ed8922018-11-19 16:59:08 +0800794 FILE* proxy = fdopen(__netdClientDispatch.dnsOpenProxy(), "r+");
Elliott Hughes9773fa32014-12-10 14:56:46 -0800795 if (proxy == NULL) {
796 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartz90a83be2017-04-24 17:57:11 -0400797 res_setnetcontext(res, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -0800798 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Mattias Falkc63e5902011-08-23 14:34:14 +0200799 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400800 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Paul Jensen5240b562014-05-15 14:43:07 -0400801
Elliott Hughes9773fa32014-12-10 14:56:46 -0800802 // This is writing to system/netd/server/DnsProxyListener.cpp and changes
803 // here need to be matched there.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500804 if (fprintf(proxy, "gethostbyname %u %s %d",
805 netid,
Mattias Falkc63e5902011-08-23 14:34:14 +0200806 name == NULL ? "^" : name,
807 af) < 0) {
Elliott Hughes9773fa32014-12-10 14:56:46 -0800808 fclose(proxy);
809 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200810 }
811
812 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200813 fclose(proxy);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800814 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200815 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800816
Yabin Cui58d33a52014-12-16 17:03:44 -0800817 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800818 fclose(proxy);
Mattias Falkc63e5902011-08-23 14:34:14 +0200819 return result;
820}
821
Yabin Cui58d33a52014-12-16 17:03:44 -0800822/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
823int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
824 size_t buflen, struct hostent **result, int *h_errnop)
825{
Ben Schwartz50178052017-04-24 17:57:11 -0400826 *result = android_gethostbyaddrfornetcontext_proxy_internal(
827 addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700828 return h_errno_to_result(h_errnop);
Yabin Cui58d33a52014-12-16 17:03:44 -0800829}
Mattias Falkc63e5902011-08-23 14:34:14 +0200830
Elliott Hughes9773fa32014-12-10 14:56:46 -0800831static struct hostent *
Ben Schwartz50178052017-04-24 17:57:11 -0400832android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
833 char *buf, size_t buflen, int *he,
834 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800835{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800836 const u_char *uaddr = (const u_char *)addr;
837 socklen_t size;
Yabin Cui58d33a52014-12-16 17:03:44 -0800838 struct getnamaddr info;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800839 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800840 NS_FILES_CB(_hf_gethtbyaddr, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800841 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800842 NS_NIS_CB(_yp_gethtbyaddr, NULL)
843 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800844 };
845
Yabin Cui58d33a52014-12-16 17:03:44 -0800846 _DIAGASSERT(addr != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800847
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700848 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
849 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
850 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800851 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800852 return NULL;
853 }
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700854 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
855 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
856 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800857 /* Unmap. */
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700858 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
859 addr = uaddr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800860 af = AF_INET;
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700861 len = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800862 }
863 switch (af) {
864 case AF_INET:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700865 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800866 break;
867 case AF_INET6:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700868 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800869 break;
870 default:
871 errno = EAFNOSUPPORT;
Yabin Cui58d33a52014-12-16 17:03:44 -0800872 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800873 return NULL;
874 }
875 if (size != len) {
876 errno = EINVAL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800877 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800878 return NULL;
879 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800880 info.hp = hp;
881 info.buf = buf;
882 info.buflen = buflen;
883 info.he = he;
884 *he = NETDB_INTERNAL;
885 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
Ben Schwartz50178052017-04-24 17:57:11 -0400886 default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800887 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800888 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800889 return hp;
890}
891
Yabin Cui58d33a52014-12-16 17:03:44 -0800892static struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -0400893android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
Yabin Cui58d33a52014-12-16 17:03:44 -0800894 struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
Ben Schwartz50178052017-04-24 17:57:11 -0400895 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800896{
Luke Huange3ed8922018-11-19 16:59:08 +0800897 FILE* proxy = fdopen(__netdClientDispatch.dnsOpenProxy(), "r+");
Elliott Hughes9773fa32014-12-10 14:56:46 -0800898 if (proxy == NULL) {
899 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartz50178052017-04-24 17:57:11 -0400900 return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800901 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800902 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6
903 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
904 if (addrStr == NULL) {
905 fclose(proxy);
906 return NULL;
907 }
908
Ben Schwartz50178052017-04-24 17:57:11 -0400909 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800910
911 if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
912 addrStr, len, af, netid) < 0) {
913 fclose(proxy);
914 return NULL;
915 }
916
917 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
918 fclose(proxy);
919 return NULL;
920 }
921
Yabin Cui58d33a52014-12-16 17:03:44 -0800922 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800923 fclose(proxy);
924 return result;
925}
926
Yabin Cui58d33a52014-12-16 17:03:44 -0800927struct hostent*
928netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200929{
Yabin Cui58d33a52014-12-16 17:03:44 -0800930 char *p, *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800931 char *cp, **q;
932 int af, len;
Yabin Cui58d33a52014-12-16 17:03:44 -0800933 size_t anum;
934 char **aliases;
935 size_t maxaliases;
936 struct in6_addr host_addr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800937
Yabin Cui58d33a52014-12-16 17:03:44 -0800938 if (hf == NULL) {
939 *he = NETDB_INTERNAL;
940 errno = EINVAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800941 return NULL;
942 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800943 p = NULL;
944 setup(aliases, maxaliases);
945
946 /* Allocate a new space to read file lines like upstream does.
947 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
948 * as the buffer may be used to store content for a previous hostent
949 * returned by non-reentrant functions like gethostbyname().
950 */
951 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
952 if ((p = malloc(line_buf_size)) == NULL) {
953 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800954 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800955 for (;;) {
956 if (!fgets(p, line_buf_size, hf)) {
957 free(p);
958 free(aliases);
959 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800960 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800961 }
962 if (*p == '#') {
963 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800964 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800965 if (!(cp = strpbrk(p, "#\n"))) {
966 continue;
967 }
968 *cp = '\0';
969 if (!(cp = strpbrk(p, " \t")))
970 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800971 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -0800972 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
973 af = AF_INET6;
974 len = NS_IN6ADDRSZ;
975 } else {
976 if (inet_pton(AF_INET, p, &host_addr) <= 0)
977 continue;
978
979 res_state res = __res_get_state();
980 if (res == NULL)
981 goto nospc;
982 if (res->options & RES_USE_INET6) {
983 map_v4v6_address(buf, buf);
984 af = AF_INET6;
985 len = NS_IN6ADDRSZ;
986 } else {
987 af = AF_INET;
988 len = NS_INADDRSZ;
989 }
990 __res_put_state(res);
991 }
992
993 /* if this is not something we're looking for, skip it. */
994 if (hent->h_addrtype != 0 && hent->h_addrtype != af)
995 continue;
996 if (hent->h_length != 0 && hent->h_length != len)
997 continue;
998
999 while (*cp == ' ' || *cp == '\t')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001000 cp++;
Yabin Cui58d33a52014-12-16 17:03:44 -08001001 if ((cp = strpbrk(name = cp, " \t")) != NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001002 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001003 q = aliases;
1004 while (cp && *cp) {
1005 if (*cp == ' ' || *cp == '\t') {
1006 cp++;
1007 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001008 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001009 addalias(q, cp, aliases, maxaliases);
1010 if ((cp = strpbrk(cp, " \t")) != NULL)
1011 *cp++ = '\0';
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001012 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001013 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001014 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001015 hent->h_length = len;
1016 hent->h_addrtype = af;
1017 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1018 anum = (size_t)(q - aliases);
1019 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
1020 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
1021 buflen);
1022 hent->h_addr_list[1] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001023
Yabin Cui58d33a52014-12-16 17:03:44 -08001024 HENT_SCOPY(hent->h_name, name, buf, buflen);
1025 for (size_t i = 0; i < anum; i++)
1026 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1027 hent->h_aliases[anum] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001028
Yabin Cui58d33a52014-12-16 17:03:44 -08001029 *he = NETDB_SUCCESS;
1030 free(p);
1031 free(aliases);
1032 return hent;
1033nospc:
1034 free(p);
1035 free(aliases);
1036 errno = ENOSPC;
1037 *he = NETDB_INTERNAL;
1038 return NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001039}
1040
1041static void
1042map_v4v6_address(const char *src, char *dst)
1043{
1044 u_char *p = (u_char *)dst;
Yabin Cui58d33a52014-12-16 17:03:44 -08001045 char tmp[NS_INADDRSZ];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001046 int i;
1047
Yabin Cui58d33a52014-12-16 17:03:44 -08001048 _DIAGASSERT(src != NULL);
1049 _DIAGASSERT(dst != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001050
1051 /* Stash a temporary copy so our caller can update in place. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001052 (void)memcpy(tmp, src, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001053 /* Mark this ipv6 addr as a mapped ipv4. */
1054 for (i = 0; i < 10; i++)
1055 *p++ = 0x00;
1056 *p++ = 0xff;
1057 *p++ = 0xff;
1058 /* Retrieve the saved copy and we're done. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001059 (void)memcpy(p, tmp, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001060}
1061
1062static void
1063map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1064{
1065 char **ap;
1066
Yabin Cui58d33a52014-12-16 17:03:44 -08001067 _DIAGASSERT(hp != NULL);
1068 _DIAGASSERT(bpp != NULL);
1069 _DIAGASSERT(ep != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001070
Yabin Cui58d33a52014-12-16 17:03:44 -08001071 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001072 return;
1073 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001074 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001075 for (ap = hp->h_addr_list; *ap; ap++) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001076 int i = (int)(sizeof(align) -
1077 (size_t)((u_long)*bpp % sizeof(align)));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001078
Yabin Cui58d33a52014-12-16 17:03:44 -08001079 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001080 /* Out of memory. Truncate address list here. XXX */
1081 *ap = NULL;
1082 return;
1083 }
1084 *bpp += i;
1085 map_v4v6_address(*ap, *bpp);
1086 *ap = *bpp;
Yabin Cui58d33a52014-12-16 17:03:44 -08001087 *bpp += NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001088 }
1089}
1090
1091static void
1092addrsort(char **ap, int num, res_state res)
1093{
1094 int i, j;
1095 char **p;
1096 short aval[MAXADDRS];
1097 int needsort = 0;
1098
Yabin Cui58d33a52014-12-16 17:03:44 -08001099 _DIAGASSERT(ap != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001100
1101 p = ap;
1102 for (i = 0; i < num; i++, p++) {
1103 for (j = 0 ; (unsigned)j < res->nsort; j++)
1104 if (res->sort_list[j].addr.s_addr ==
1105 (((struct in_addr *)(void *)(*p))->s_addr &
1106 res->sort_list[j].mask))
1107 break;
1108 aval[i] = j;
1109 if (needsort == 0 && i > 0 && j < aval[i-1])
1110 needsort = i;
1111 }
1112 if (!needsort)
1113 return;
1114
1115 while (needsort < num) {
1116 for (j = needsort - 1; j >= 0; j--) {
1117 if (aval[j] > aval[j+1]) {
1118 char *hp;
1119
1120 i = aval[j];
1121 aval[j] = aval[j+1];
1122 aval[j+1] = i;
1123
1124 hp = ap[j];
1125 ap[j] = ap[j+1];
1126 ap[j+1] = hp;
1127 } else
1128 break;
1129 }
1130 needsort++;
1131 }
1132}
1133
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001134/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001135static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001136_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1137{
1138 querybuf *buf;
1139 int n, type;
1140 struct hostent *hp;
1141 const char *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001142 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001143 struct getnamaddr *info = rv;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001144
Yabin Cui58d33a52014-12-16 17:03:44 -08001145 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001146
1147 name = va_arg(ap, char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001148 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1149 info->hp->h_addrtype = va_arg(ap, int);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001150
Yabin Cui58d33a52014-12-16 17:03:44 -08001151 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001152 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -08001153 info->hp->h_length = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001154 type = T_A;
1155 break;
1156 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -08001157 info->hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001158 type = T_AAAA;
1159 break;
1160 default:
1161 return NS_UNAVAIL;
1162 }
1163 buf = malloc(sizeof(*buf));
1164 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001165 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001166 return NS_NOTFOUND;
1167 }
1168 res = __res_get_state();
1169 if (res == NULL) {
1170 free(buf);
1171 return NS_NOTFOUND;
1172 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001173 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001174 if (n < 0) {
1175 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001176 debugprintf("res_nsearch failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001177 __res_put_state(res);
1178 return NS_NOTFOUND;
1179 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001180 hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
1181 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001182 free(buf);
1183 __res_put_state(res);
1184 if (hp == NULL)
Yabin Cui70692562014-12-19 10:10:04 -08001185 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001186 case HOST_NOT_FOUND:
1187 return NS_NOTFOUND;
1188 case TRY_AGAIN:
1189 return NS_TRYAGAIN;
1190 default:
1191 return NS_UNAVAIL;
1192 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001193 return NS_SUCCESS;
1194}
1195
1196/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001197static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001198_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1199{
1200 char qbuf[MAXDNAME + 1], *qp, *ep;
1201 int n;
1202 querybuf *buf;
1203 struct hostent *hp;
1204 const unsigned char *uaddr;
Yabin Cui58d33a52014-12-16 17:03:44 -08001205 int advance;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001206 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001207 char *bf;
1208 size_t blen;
1209 struct getnamaddr *info = rv;
Ben Schwartz50178052017-04-24 17:57:11 -04001210 const struct android_net_context *netcontext;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001211
Yabin Cui58d33a52014-12-16 17:03:44 -08001212 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001213
1214 uaddr = va_arg(ap, unsigned char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001215 info->hp->h_length = va_arg(ap, int);
1216 info->hp->h_addrtype = va_arg(ap, int);
Ben Schwartz50178052017-04-24 17:57:11 -04001217 netcontext = va_arg(ap, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001218
Yabin Cui58d33a52014-12-16 17:03:44 -08001219 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001220 case AF_INET:
1221 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1222 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1223 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1224 break;
1225
1226 case AF_INET6:
1227 qp = qbuf;
1228 ep = qbuf + sizeof(qbuf) - 1;
Yabin Cui58d33a52014-12-16 17:03:44 -08001229 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001230 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1231 uaddr[n] & 0xf,
1232 ((unsigned int)uaddr[n] >> 4) & 0xf);
1233 if (advance > 0 && qp + advance < ep)
1234 qp += advance;
1235 else {
Yabin Cui58d33a52014-12-16 17:03:44 -08001236 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001237 return NS_NOTFOUND;
1238 }
1239 }
1240 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001241 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001242 return NS_NOTFOUND;
1243 }
1244 break;
1245 default:
Yabin Cui58d33a52014-12-16 17:03:44 -08001246 return NS_UNAVAIL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001247 }
1248
1249 buf = malloc(sizeof(*buf));
1250 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001251 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001252 return NS_NOTFOUND;
1253 }
1254 res = __res_get_state();
1255 if (res == NULL) {
1256 free(buf);
1257 return NS_NOTFOUND;
1258 }
Ben Schwartz90a83be2017-04-24 17:57:11 -04001259 res_setnetcontext(res, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001260 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001261 if (n < 0) {
1262 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001263 debugprintf("res_nquery failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001264 __res_put_state(res);
1265 return NS_NOTFOUND;
1266 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001267 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1268 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001269 free(buf);
1270 if (hp == NULL) {
1271 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001272 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001273 case HOST_NOT_FOUND:
1274 return NS_NOTFOUND;
1275 case TRY_AGAIN:
1276 return NS_TRYAGAIN;
1277 default:
1278 return NS_UNAVAIL;
1279 }
1280 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001281
1282 bf = (void *)(hp->h_addr_list + 2);
1283 blen = (size_t)(bf - info->buf);
1284 if (blen + info->hp->h_length > info->buflen)
1285 goto nospc;
1286 hp->h_addr_list[0] = bf;
1287 hp->h_addr_list[1] = NULL;
1288 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1289 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1290 if (blen + NS_IN6ADDRSZ > info->buflen)
1291 goto nospc;
1292 map_v4v6_address(bf, bf);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001293 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001294 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001295 }
1296
1297 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001298 *info->he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001299 return NS_SUCCESS;
Yabin Cui58d33a52014-12-16 17:03:44 -08001300nospc:
Yabin Cui70692562014-12-19 10:10:04 -08001301 errno = ENOSPC;
Yabin Cui58d33a52014-12-16 17:03:44 -08001302 *info->he = NETDB_INTERNAL;
1303 return NS_UNAVAIL;
1304}
1305
1306#ifdef YP
1307/*ARGSUSED*/
1308static struct hostent *
1309_yp_hostent(char *line, int af, struct getnamaddr *info)
1310{
1311 struct in6_addr host_addrs[MAXADDRS];
1312 char **aliases;
1313 size_t maxaliases;
1314 char *p = line;
1315 char *cp, **q, *ptr;
1316 size_t len, anum, i;
1317 int addrok;
1318 int more;
1319 size_t naddrs;
1320 struct hostent *hp = info->hp;
1321
1322 _DIAGASSERT(line != NULL);
1323
1324 hp->h_name = NULL;
1325 hp->h_addrtype = af;
1326 switch (af) {
1327 case AF_INET:
1328 hp->h_length = NS_INADDRSZ;
1329 break;
1330 case AF_INET6:
1331 hp->h_length = NS_IN6ADDRSZ;
1332 break;
1333 default:
1334 return NULL;
1335 }
1336 setup(aliases, maxaliases);
1337 naddrs = 0;
1338 q = aliases;
1339
1340nextline:
1341 /* check for host_addrs overflow */
1342 if (naddrs >= __arraycount(host_addrs))
1343 goto done;
1344
1345 more = 0;
1346 cp = strpbrk(p, " \t");
1347 if (cp == NULL)
1348 goto done;
1349 *cp++ = '\0';
1350
1351 /* p has should have an address */
1352 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1353 if (addrok != 1) {
1354 /* skip to the next line */
1355 while (cp && *cp) {
1356 if (*cp == '\n') {
1357 cp++;
1358 goto nextline;
1359 }
1360 cp++;
1361 }
1362 goto done;
1363 }
1364 naddrs++;
1365
1366 while (*cp == ' ' || *cp == '\t')
1367 cp++;
1368 p = cp;
1369 cp = strpbrk(p, " \t\n");
1370 if (cp != NULL) {
1371 if (*cp == '\n')
1372 more = 1;
1373 *cp++ = '\0';
1374 }
1375 if (!hp->h_name)
1376 hp->h_name = p;
1377 else if (strcmp(hp->h_name, p) == 0)
1378 ;
1379 else
1380 addalias(q, p, aliases, maxaliases);
1381 p = cp;
1382 if (more)
1383 goto nextline;
1384
1385 while (cp && *cp) {
1386 if (*cp == ' ' || *cp == '\t') {
1387 cp++;
1388 continue;
1389 }
1390 if (*cp == '\n') {
1391 cp++;
1392 goto nextline;
1393 }
1394 addalias(q, cp, aliases, maxaliases);
1395 cp = strpbrk(cp, " \t");
1396 if (cp != NULL)
1397 *cp++ = '\0';
1398 }
1399
1400done:
1401 if (hp->h_name == NULL) {
1402 free(aliases);
1403 return NULL;
1404 }
1405
1406 ptr = info->buf;
1407 len = info->buflen;
1408
1409 anum = (size_t)(q - aliases);
1410 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1411 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1412
1413 for (i = 0; i < naddrs; i++)
1414 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1415 ptr, len);
1416 hp->h_addr_list[naddrs] = NULL;
1417
1418 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1419
1420 for (i = 0; i < anum; i++)
1421 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1422 hp->h_aliases[anum] = NULL;
1423 free(aliases);
1424
1425 return hp;
1426nospc:
1427 free(aliases);
1428 *info->he = NETDB_INTERNAL;
1429 errno = ENOSPC;
1430 return NULL;
1431}
1432
1433/*ARGSUSED*/
1434int
1435_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1436{
1437 struct hostent *hp = NULL;
1438 char *ypcurrent;
1439 int ypcurrentlen, r;
1440 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1441 const unsigned char *uaddr;
1442 int af;
1443 const char *map;
1444 struct getnamaddr *info = rv;
1445
1446 _DIAGASSERT(rv != NULL);
1447
1448 uaddr = va_arg(ap, unsigned char *);
1449 /* NOSTRICT skip len */(void)va_arg(ap, int);
1450 af = va_arg(ap, int);
1451
1452 if (!__ypdomain) {
1453 if (_yp_check(&__ypdomain) == 0)
1454 return NS_UNAVAIL;
1455 }
1456 /*
1457 * XXX unfortunately, we cannot support IPv6 extended scoped address
1458 * notation here. gethostbyaddr() is not scope-aware. too bad.
1459 */
1460 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1461 return NS_UNAVAIL;
1462 switch (af) {
1463 case AF_INET:
1464 map = "hosts.byaddr";
1465 break;
1466 default:
1467 map = "ipnodes.byaddr";
1468 break;
1469 }
1470 ypcurrent = NULL;
1471 r = yp_match(__ypdomain, map, name,
1472 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1473 if (r == 0)
1474 hp = _yp_hostent(ypcurrent, af, info);
1475 else
1476 hp = NULL;
1477 free(ypcurrent);
1478 if (hp == NULL) {
1479 *info->he = HOST_NOT_FOUND;
1480 return NS_NOTFOUND;
1481 }
1482 return NS_SUCCESS;
1483}
1484
1485/*ARGSUSED*/
1486int
1487_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1488{
1489 struct hostent *hp;
1490 char *ypcurrent;
1491 int ypcurrentlen, r;
1492 const char *name;
1493 int af;
1494 const char *map;
1495 struct getnamaddr *info = rv;
1496
1497 _DIAGASSERT(rv != NULL);
1498
1499 name = va_arg(ap, char *);
1500 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1501 af = va_arg(ap, int);
1502
1503 if (!__ypdomain) {
1504 if (_yp_check(&__ypdomain) == 0)
1505 return NS_UNAVAIL;
1506 }
1507 switch (af) {
1508 case AF_INET:
1509 map = "hosts.byname";
1510 break;
1511 default:
1512 map = "ipnodes.byname";
1513 break;
1514 }
1515 ypcurrent = NULL;
1516 r = yp_match(__ypdomain, map, name,
1517 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1518 if (r == 0)
1519 hp = _yp_hostent(ypcurrent, af, info);
1520 else
1521 hp = NULL;
1522 free(ypcurrent);
1523 if (hp == NULL) {
1524 *info->he = HOST_NOT_FOUND;
1525 return NS_NOTFOUND;
1526 }
1527 return NS_SUCCESS;
1528}
1529#endif
1530
1531/*
1532 * Non-reentrant versions.
1533 */
1534
Lev Rumyantsev814f38f2020-10-12 17:33:06 -07001535__BIONIC_WEAK_FOR_NATIVE_BRIDGE
Yabin Cui58d33a52014-12-16 17:03:44 -08001536struct hostent *
1537gethostbyname(const char *name)
1538{
1539 struct hostent *result = NULL;
Elliott Hughesd0bbfa82021-04-08 11:58:51 -07001540 struct res_static* rs = __res_get_static();
Yabin Cui58d33a52014-12-16 17:03:44 -08001541
1542 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1543 return result;
1544}
1545
1546struct hostent *
1547gethostbyname2(const char *name, int af)
1548{
1549 struct hostent *result = NULL;
Elliott Hughesd0bbfa82021-04-08 11:58:51 -07001550 struct res_static* rs = __res_get_static();
Yabin Cui58d33a52014-12-16 17:03:44 -08001551
1552 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1553 return result;
1554}
1555
Ben Schwartz50178052017-04-24 17:57:11 -04001556// android_gethostby*fornet can be called in two different contexts.
1557// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1558// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1559// The netcontext is constructed before checking which context we are in.
1560// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1561// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1562static struct android_net_context make_context(unsigned netid, unsigned mark) {
1563 struct android_net_context netcontext = NETCONTEXT_UNSET;
1564 netcontext.app_netid = netid;
1565 netcontext.app_mark = mark;
1566 netcontext.dns_netid = netid;
1567 netcontext.dns_mark = mark;
1568 return netcontext;
1569}
1570
Yabin Cui58d33a52014-12-16 17:03:44 -08001571struct hostent *
1572android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
1573{
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001574 const struct android_net_context netcontext = make_context(netid, mark);
1575 return android_gethostbynamefornetcontext(name, af, &netcontext);
1576}
1577
1578struct hostent *
1579android_gethostbynamefornetcontext(const char *name, int af,
1580 const struct android_net_context *netcontext)
1581{
Yabin Cui58d33a52014-12-16 17:03:44 -08001582 struct hostent *hp;
1583 res_state res = __res_get_state();
1584 if (res == NULL)
1585 return NULL;
Elliott Hughesd0bbfa82021-04-08 11:58:51 -07001586 struct res_static* rs = __res_get_static();
Yabin Cui58d33a52014-12-16 17:03:44 -08001587 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001588 &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001589 __res_put_state(res);
1590 return hp;
1591}
1592
Lev Rumyantsev814f38f2020-10-12 17:33:06 -07001593__BIONIC_WEAK_FOR_NATIVE_BRIDGE
Yabin Cui58d33a52014-12-16 17:03:44 -08001594struct hostent *
1595gethostbyaddr(const void *addr, socklen_t len, int af)
1596{
Ben Schwartz50178052017-04-24 17:57:11 -04001597 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -08001598}
1599
1600struct hostent *
1601android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
1602{
Ben Schwartz50178052017-04-24 17:57:11 -04001603 const struct android_net_context netcontext = make_context(netid, mark);
1604 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
1605}
1606
1607struct hostent *
1608android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
1609 const struct android_net_context *netcontext)
1610{
1611 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001612}
1613
1614__LIBC_HIDDEN__ struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -04001615android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
1616 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -08001617{
Elliott Hughesd0bbfa82021-04-08 11:58:51 -07001618 struct res_static* rs = __res_get_static();
Ben Schwartz50178052017-04-24 17:57:11 -04001619 return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
1620 sizeof(rs->hostbuf), &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001621}
1622
1623struct hostent *
1624gethostent(void)
1625{
Elliott Hughesd0bbfa82021-04-08 11:58:51 -07001626 struct res_static* rs = __res_get_static();
Yabin Cui58d33a52014-12-16 17:03:44 -08001627 if (!rs->hostf) {
1628 sethostent_r(&rs->hostf);
1629 if (!rs->hostf) {
1630 h_errno = NETDB_INTERNAL;
1631 return NULL;
1632 }
1633 }
1634 memset(&rs->host, 0, sizeof(rs->host));
1635 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001636}