blob: 7118a2934f4d960e7df663fd69f59945db278e94 [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
Calin Juravlec20de902014-03-20 15:21:32 +000078#define ALIGNBYTES (sizeof(uintptr_t) - 1)
79#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
80
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080081#ifndef LOG_AUTH
82# define LOG_AUTH 0
83#endif
84
85#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
86
87#include "nsswitch.h"
88#include <stdlib.h>
89#include <string.h>
90
Yabin Cui58d33a52014-12-16 17:03:44 -080091#include "hostent.h"
92
93#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
94 (ok)(nm) != 0)
95#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
96#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
97
98#define addalias(d, s, arr, siz) do { \
99 if (d >= &arr[siz]) { \
100 char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
101 if (xptr == NULL) \
102 goto nospc; \
103 d = xptr + (d - arr); \
104 arr = xptr; \
105 siz += 10; \
106 } \
107 *d++ = s; \
108} while (/*CONSTCOND*/0)
109
110#define setup(arr, siz) do { \
111 arr = malloc((siz = 10) * sizeof(*arr)); \
112 if (arr == NULL) \
113 goto nospc; \
114} while (/*CONSTCOND*/0)
115
Mattias Falkc63e5902011-08-23 14:34:14 +0200116// This should be synchronized to ResponseCode.h
117static const int DnsProxyQueryResult = 222;
118
Elliott Hughes68c27552014-07-07 09:44:17 -0700119static const char AskedForGot[] =
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800120 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
121
Ben Schwartz50178052017-04-24 17:57:11 -0400122static const struct android_net_context NETCONTEXT_UNSET = {
123 .app_mark = MARK_UNSET,
124 .app_netid = NETID_UNSET,
125 .dns_mark = MARK_UNSET,
126 .dns_netid = NETID_UNSET,
127 .uid = NET_CONTEXT_INVALID_UID
128};
129
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800130#define MAXPACKET (64*1024)
131
132typedef union {
133 HEADER hdr;
134 u_char buf[MAXPACKET];
135} querybuf;
136
137typedef union {
138 int32_t al;
139 char ac;
140} align;
141
142#ifdef DEBUG
Yabin Cui58d33a52014-12-16 17:03:44 -0800143static void debugprintf(const char *, res_state, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800144 __attribute__((__format__(__printf__, 1, 3)));
145#endif
146static struct hostent *getanswer(const querybuf *, int, const char *, int,
Yabin Cui58d33a52014-12-16 17:03:44 -0800147 res_state, struct hostent *, char *, size_t, int *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800148static void map_v4v6_address(const char *, char *);
149static void map_v4v6_hostent(struct hostent *, char **, char *);
150static void addrsort(char **, int, res_state);
151
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800152void ht_sethostent(int);
153void ht_endhostent(void);
154struct hostent *ht_gethostbyname(char *);
155struct hostent *ht_gethostbyaddr(const char *, int, int);
156void dns_service(void);
157#undef dn_skipname
158int dn_skipname(const u_char *, const u_char *);
Jim Huange5c35e02010-09-27 23:37:10 +0800159static int _dns_gethtbyaddr(void *, void *, va_list);
160static int _dns_gethtbyname(void *, void *, va_list);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800161
Yabin Cui58d33a52014-12-16 17:03:44 -0800162static struct hostent *gethostbyname_internal(const char *, int, res_state,
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400163 struct hostent *, char *, size_t, int *, const struct android_net_context *);
Ben Schwartz50178052017-04-24 17:57:11 -0400164static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t,
165 int, struct hostent *, char *, size_t, int *, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800166
167static const ns_src default_dns_files[] = {
168 { NSSRC_FILES, NS_SUCCESS },
169 { NSSRC_DNS, NS_SUCCESS },
170 { 0, 0 }
171};
172
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700173static int h_errno_to_result(int* herrno_p) {
174 // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
175 if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
176 errno = ERANGE;
177 return errno;
178 }
179 // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
180 return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
181}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800182
183#ifdef DEBUG
184static void
Yabin Cui58d33a52014-12-16 17:03:44 -0800185debugprintf(const char *msg, res_state res, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800186{
Yabin Cui58d33a52014-12-16 17:03:44 -0800187 _DIAGASSERT(msg != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800188
189 if (res->options & RES_DEBUG) {
190 int save = errno;
191 va_list ap;
192
193 va_start (ap, res);
194 vprintf(msg, ap);
195 va_end (ap);
196
197 errno = save;
198 }
199}
200#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800201# define debugprintf(msg, res, num) /*nada*/
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800202#endif
203
204#define BOUNDED_INCR(x) \
205 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800206 BOUNDS_CHECK(cp, x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800207 cp += (x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800208 } while (/*CONSTCOND*/0)
209
210#define BOUNDS_CHECK(ptr, count) \
211 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800212 if (eom - (ptr) < (count)) \
Yabin Cui58d33a52014-12-16 17:03:44 -0800213 goto no_recovery; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800214 } while (/*CONSTCOND*/0)
215
216static struct hostent *
217getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
Yabin Cui58d33a52014-12-16 17:03:44 -0800218 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800219{
220 const HEADER *hp;
221 const u_char *cp;
222 int n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800223 size_t qlen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800224 const u_char *eom, *erdata;
225 char *bp, **ap, **hap, *ep;
226 int type, class, ancount, qdcount;
227 int haveanswer, had_error;
228 int toobig = 0;
229 char tbuf[MAXDNAME];
Yabin Cui58d33a52014-12-16 17:03:44 -0800230 char **aliases;
231 size_t maxaliases;
232 char *addr_ptrs[MAXADDRS];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800233 const char *tname;
234 int (*name_ok)(const char *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800235
Yabin Cui58d33a52014-12-16 17:03:44 -0800236 _DIAGASSERT(answer != NULL);
237 _DIAGASSERT(qname != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800238
239 tname = qname;
Yabin Cui58d33a52014-12-16 17:03:44 -0800240 hent->h_name = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800241 eom = answer->buf + anslen;
242 switch (qtype) {
243 case T_A:
244 case T_AAAA:
245 name_ok = res_hnok;
246 break;
247 case T_PTR:
248 name_ok = res_dnok;
249 break;
250 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800251 *he = NO_RECOVERY;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800252 return NULL; /* XXX should be abort(); */
253 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800254
255 setup(aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800256 /*
257 * find first satisfactory answer
258 */
259 hp = &answer->hdr;
260 ancount = ntohs(hp->ancount);
261 qdcount = ntohs(hp->qdcount);
Yabin Cui58d33a52014-12-16 17:03:44 -0800262 bp = buf;
263 ep = buf + buflen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800264 cp = answer->buf;
265 BOUNDED_INCR(HFIXEDSZ);
Yabin Cui58d33a52014-12-16 17:03:44 -0800266 if (qdcount != 1)
267 goto no_recovery;
268
269 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
270 if ((n < 0) || !maybe_ok(res, bp, name_ok))
271 goto no_recovery;
272
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800273 BOUNDED_INCR(n + QFIXEDSZ);
274 if (qtype == T_A || qtype == T_AAAA) {
275 /* res_send() has already verified that the query name is the
276 * same as the one we sent; this just gets the expanded name
277 * (i.e., with the succeeding search-domain tacked on).
278 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800279 n = (int)strlen(bp) + 1; /* for the \0 */
280 if (n >= MAXHOSTNAMELEN)
281 goto no_recovery;
282 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800283 bp += n;
284 /* The qname can be abbreviated, but h_name is now absolute. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800285 qname = hent->h_name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800286 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800287 hent->h_aliases = ap = aliases;
288 hent->h_addr_list = hap = addr_ptrs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800289 *ap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800290 *hap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800291 haveanswer = 0;
292 had_error = 0;
293 while (ancount-- > 0 && cp < eom && !had_error) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800294 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
295 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800296 had_error++;
297 continue;
298 }
299 cp += n; /* name */
300 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
301 type = _getshort(cp);
302 cp += INT16SZ; /* type */
303 class = _getshort(cp);
304 cp += INT16SZ + INT32SZ; /* class, TTL */
305 n = _getshort(cp);
306 cp += INT16SZ; /* len */
307 BOUNDS_CHECK(cp, n);
308 erdata = cp + n;
309 if (class != C_IN) {
310 /* XXX - debug? syslog? */
311 cp += n;
312 continue; /* XXX - had_error++ ? */
313 }
314 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800315 n = dn_expand(answer->buf, eom, cp, tbuf,
316 (int)sizeof tbuf);
317 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800318 had_error++;
319 continue;
320 }
321 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800322 if (cp != erdata)
323 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800324 /* Store alias. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800325 addalias(ap, bp, aliases, maxaliases);
326 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800327 if (n >= MAXHOSTNAMELEN) {
328 had_error++;
329 continue;
330 }
331 bp += n;
332 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800333 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800334 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
335 had_error++;
336 continue;
337 }
338 strlcpy(bp, tbuf, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800339 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800340 bp += n;
341 continue;
342 }
343 if (qtype == T_PTR && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800344 n = dn_expand(answer->buf, eom, cp, tbuf,
345 (int)sizeof tbuf);
346 if (n < 0 || !maybe_dnok(res, tbuf)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800347 had_error++;
348 continue;
349 }
350 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800351 if (cp != erdata)
352 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800353 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800354 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800355 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
356 had_error++;
357 continue;
358 }
359 strlcpy(bp, tbuf, (size_t)(ep - bp));
360 tname = bp;
361 bp += n;
362 continue;
363 }
364 if (type != qtype) {
365 if (type != T_KEY && type != T_SIG)
366 syslog(LOG_NOTICE|LOG_AUTH,
367 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
368 qname, p_class(C_IN), p_type(qtype),
369 p_type(type));
370 cp += n;
371 continue; /* XXX - had_error++ ? */
372 }
373 switch (type) {
374 case T_PTR:
375 if (strcasecmp(tname, bp) != 0) {
376 syslog(LOG_NOTICE|LOG_AUTH,
377 AskedForGot, qname, bp);
378 cp += n;
379 continue; /* XXX - had_error++ ? */
380 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800381 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
382 if ((n < 0) || !maybe_hnok(res, bp)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800383 had_error++;
384 break;
385 }
386#if MULTI_PTRS_ARE_ALIASES
387 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800388 if (cp != erdata)
389 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800390 if (!haveanswer)
Yabin Cui58d33a52014-12-16 17:03:44 -0800391 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800392 else
Yabin Cui58d33a52014-12-16 17:03:44 -0800393 addalias(ap, bp, aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800394 if (n != -1) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800395 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800396 if (n >= MAXHOSTNAMELEN) {
397 had_error++;
398 break;
399 }
400 bp += n;
401 }
402 break;
403#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800404 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800405 if (res->options & RES_USE_INET6) {
406 n = strlen(bp) + 1; /* for the \0 */
407 if (n >= MAXHOSTNAMELEN) {
408 had_error++;
409 break;
410 }
411 bp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800412 map_v4v6_hostent(hent, &bp, ep);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800413 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800414 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800415#endif
416 case T_A:
417 case T_AAAA:
Yabin Cui58d33a52014-12-16 17:03:44 -0800418 if (strcasecmp(hent->h_name, bp) != 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800419 syslog(LOG_NOTICE|LOG_AUTH,
Yabin Cui58d33a52014-12-16 17:03:44 -0800420 AskedForGot, hent->h_name, bp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800421 cp += n;
422 continue; /* XXX - had_error++ ? */
423 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800424 if (n != hent->h_length) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800425 cp += n;
426 continue;
427 }
428 if (type == T_AAAA) {
429 struct in6_addr in6;
Yabin Cui58d33a52014-12-16 17:03:44 -0800430 memcpy(&in6, cp, NS_IN6ADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800431 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
432 cp += n;
433 continue;
434 }
435 }
436 if (!haveanswer) {
437 int nn;
438
Yabin Cui58d33a52014-12-16 17:03:44 -0800439 hent->h_name = bp;
440 nn = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800441 bp += nn;
442 }
443
444 bp += sizeof(align) -
445 (size_t)((u_long)bp % sizeof(align));
446
Yabin Cui58d33a52014-12-16 17:03:44 -0800447 if (bp + n >= ep) {
448 debugprintf("size (%d) too big\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800449 had_error++;
450 continue;
451 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800452 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
453 if (!toobig++) {
454 debugprintf("Too many addresses (%d)\n",
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800455 res, MAXADDRS);
Yabin Cui58d33a52014-12-16 17:03:44 -0800456 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800457 cp += n;
458 continue;
459 }
460 (void)memcpy(*hap++ = bp, cp, (size_t)n);
461 bp += n;
462 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800463 if (cp != erdata)
464 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800465 break;
466 default:
467 abort();
468 }
469 if (!had_error)
470 haveanswer++;
471 }
472 if (haveanswer) {
473 *ap = NULL;
474 *hap = NULL;
475 /*
476 * Note: we sort even if host can take only one address
477 * in its return structures - should give it the "best"
478 * address in that case, not some random one
479 */
480 if (res->nsort && haveanswer > 1 && qtype == T_A)
Yabin Cui58d33a52014-12-16 17:03:44 -0800481 addrsort(addr_ptrs, haveanswer, res);
482 if (!hent->h_name) {
483 n = (int)strlen(qname) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800484 if (n > ep - bp || n >= MAXHOSTNAMELEN)
485 goto no_recovery;
486 strlcpy(bp, qname, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800487 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800488 bp += n;
489 }
490 if (res->options & RES_USE_INET6)
Yabin Cui58d33a52014-12-16 17:03:44 -0800491 map_v4v6_hostent(hent, &bp, ep);
492 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800493 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800494no_recovery:
495 free(aliases);
496 *he = NO_RECOVERY;
497 return NULL;
498success:
499 bp = (char *)ALIGN(bp);
500 n = (int)(ap - aliases);
501 qlen = (n + 1) * sizeof(*hent->h_aliases);
502 if ((size_t)(ep - bp) < qlen)
503 goto nospc;
504 hent->h_aliases = (void *)bp;
505 memcpy(bp, aliases, qlen);
506 free(aliases);
507 aliases = NULL;
508
509 bp += qlen;
510 n = (int)(hap - addr_ptrs);
511 qlen = (n + 1) * sizeof(*hent->h_addr_list);
512 if ((size_t)(ep - bp) < qlen)
513 goto nospc;
514 hent->h_addr_list = (void *)bp;
515 memcpy(bp, addr_ptrs, qlen);
516 *he = NETDB_SUCCESS;
517 return hent;
518nospc:
519 free(aliases);
520 errno = ENOSPC;
521 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800522 return NULL;
523}
524
Yabin Cui58d33a52014-12-16 17:03:44 -0800525/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800526int
527gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
Yabin Cui58d33a52014-12-16 17:03:44 -0800528 struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800529{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800530 res_state res = __res_get_state();
Yabin Cui58d33a52014-12-16 17:03:44 -0800531 if (res == NULL) {
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700532 *result = NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800533 *errorp = NETDB_INTERNAL;
534 return -1;
535 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800536
Yabin Cui58d33a52014-12-16 17:03:44 -0800537 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800538
539 if (res->options & RES_USE_INET6) {
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400540 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
541 &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -0800542 if (*result) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800543 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800544 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800545 }
546 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400547 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp,
548 &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700549 return h_errno_to_result(errorp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800550}
551
Yabin Cui58d33a52014-12-16 17:03:44 -0800552/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
553int
554gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
555 size_t buflen, struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800556{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800557 res_state res = __res_get_state();
Yabin Cui58d33a52014-12-16 17:03:44 -0800558 if (res == NULL) {
559 *result = NULL;
560 *errorp = NETDB_INTERNAL;
561 return -1;
562 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400563 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp,
564 &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700565 return h_errno_to_result(errorp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800566}
567
Elliott Hughes9773fa32014-12-10 14:56:46 -0800568__LIBC_HIDDEN__ FILE* android_open_proxy() {
569 const char* cache_mode = getenv("ANDROID_DNS_MODE");
570 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
571 if (!use_proxy) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200572 return NULL;
573 }
574
Elliott Hughes9773fa32014-12-10 14:56:46 -0800575 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
576 if (s == -1) {
577 return NULL;
578 }
579
580 const int one = 1;
581 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
582
583 struct sockaddr_un proxy_addr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200584 memset(&proxy_addr, 0, sizeof(proxy_addr));
585 proxy_addr.sun_family = AF_UNIX;
586 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Elliott Hughes9773fa32014-12-10 14:56:46 -0800587
588 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
589 close(s);
Mattias Falkc63e5902011-08-23 14:34:14 +0200590 return NULL;
591 }
592
Elliott Hughes9773fa32014-12-10 14:56:46 -0800593 return fdopen(s, "r+");
Mattias Falkc63e5902011-08-23 14:34:14 +0200594}
595
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800596static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800597android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200598{
599 uint32_t size;
600 char buf[4];
601 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
602
Elliott Hughes9773fa32014-12-10 14:56:46 -0800603 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp
604 // and changes here need to be matched there.
Mattias Falkc63e5902011-08-23 14:34:14 +0200605 int result_code = strtol(buf, NULL, 10);
606 if (result_code != DnsProxyQueryResult) {
607 fread(&size, 1, sizeof(size), proxy);
Yabin Cui58d33a52014-12-16 17:03:44 -0800608 *he = HOST_NOT_FOUND;
Mattias Falkc63e5902011-08-23 14:34:14 +0200609 return NULL;
610 }
611
612 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
613 size = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200614
Yabin Cui58d33a52014-12-16 17:03:44 -0800615 memset(hp, 0, sizeof(*hp));
616 char *ptr = hbuf;
617 char *hbuf_end = hbuf + hbuflen;
618
619 if (ptr + size > hbuf_end) {
620 goto nospc;
621 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200622 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800623 hp->h_name = ptr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200624 ptr += size;
Mattias Falkc63e5902011-08-23 14:34:14 +0200625
Yabin Cui58d33a52014-12-16 17:03:44 -0800626 char *aliases_ptrs[MAXALIASES];
627 char **aliases = &aliases_ptrs[0];
628
Mattias Falkc63e5902011-08-23 14:34:14 +0200629 while (1) {
630 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
631 size = ntohl(size);
632
633 if (size == 0) {
634 *aliases = NULL;
635 break;
636 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800637 if (ptr + size > hbuf_end) {
638 goto nospc;
639 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200640 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800641 if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
642 *aliases++ = ptr;
643 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200644 ptr += size;
645 }
646
Elliott Hughes65dd8582015-07-06 14:16:12 -0700647 // Fix alignment after variable-length data.
648 ptr = (char*)ALIGN(ptr);
649
Yabin Cui58d33a52014-12-16 17:03:44 -0800650 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
651 if (ptr + aliases_len > hbuf_end) {
652 goto nospc;
653 }
654 hp->h_aliases = (void*)ptr;
655 memcpy(ptr, aliases_ptrs, aliases_len);
656 ptr += aliases_len;
Mattias Falkc63e5902011-08-23 14:34:14 +0200657
658 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800659 hp->h_addrtype = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200660
Yabin Cui58d33a52014-12-16 17:03:44 -0800661 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
662 hp->h_length = ntohl(size);
663
664 char *addr_ptrs[MAXADDRS];
665 char **addr_p = &addr_ptrs[0];
666
Mattias Falkc63e5902011-08-23 14:34:14 +0200667 while (1) {
668 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
669 size = ntohl(size);
670 if (size == 0) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800671 *addr_p = NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200672 break;
673 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800674 if (ptr + size > hbuf_end) {
675 goto nospc;
676 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200677 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800678 if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
679 *addr_p++ = ptr;
680 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200681 ptr += size;
682 }
683
Elliott Hughes65dd8582015-07-06 14:16:12 -0700684 // Fix alignment after variable-length data.
685 ptr = (char*)ALIGN(ptr);
686
Yabin Cui58d33a52014-12-16 17:03:44 -0800687 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
688 if (ptr + addrs_len > hbuf_end) {
689 goto nospc;
690 }
691 hp->h_addr_list = (void*)ptr;
692 memcpy(ptr, addr_ptrs, addrs_len);
693 *he = NETDB_SUCCESS;
694 return hp;
695
696nospc:
697 *he = NETDB_INTERNAL;
698 errno = ENOSPC;
699 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200700}
701
Mattias Falkc63e5902011-08-23 14:34:14 +0200702static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800703gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf,
704 size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800705{
706 const char *cp;
Yabin Cui58d33a52014-12-16 17:03:44 -0800707 struct getnamaddr info;
708 char hbuf[MAXHOSTNAMELEN];
709 size_t size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800710 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800711 NS_FILES_CB(_hf_gethtbyname, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800712 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800713 NS_NIS_CB(_yp_gethtbyname, NULL)
714 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800715 };
716
Yabin Cui58d33a52014-12-16 17:03:44 -0800717 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800718
719 switch (af) {
720 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -0800721 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800722 break;
723 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -0800724 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800725 break;
726 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800727 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800728 errno = EAFNOSUPPORT;
729 return NULL;
730 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800731 if (buflen < size)
732 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800733
Yabin Cui58d33a52014-12-16 17:03:44 -0800734 hp->h_addrtype = af;
735 hp->h_length = (int)size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800736
737 /*
738 * if there aren't any dots, it could be a user-level alias.
739 * this is also done in res_nquery() since we are not the only
740 * function that looks up host names.
741 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800742 if (!strchr(name, '.') && (cp = res_hostalias(res, name,
743 hbuf, sizeof(hbuf))))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800744 name = cp;
745
746 /*
747 * disallow names consisting only of digits/dots, unless
748 * they end in a dot.
749 */
750 if (isdigit((u_char) name[0]))
751 for (cp = name;; ++cp) {
752 if (!*cp) {
753 if (*--cp == '.')
754 break;
755 /*
756 * All-numeric, no dot at the end.
757 * Fake up a hostent as if we'd actually
758 * done a lookup.
759 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800760 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800761 }
762 if (!isdigit((u_char) *cp) && *cp != '.')
763 break;
764 }
765 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
766 name[0] == ':')
767 for (cp = name;; ++cp) {
768 if (!*cp) {
769 if (*--cp == '.')
770 break;
771 /*
772 * All-IPv6-legal, no dot at the end.
773 * Fake up a hostent as if we'd actually
774 * done a lookup.
775 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800776 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800777 }
778 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
779 break;
780 }
781
Yabin Cui58d33a52014-12-16 17:03:44 -0800782 *he = NETDB_INTERNAL;
783 info.hp = hp;
784 info.buf = buf;
785 info.buflen = buflen;
786 info.he = he;
787 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
788 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
789 return NULL;
790 *he = NETDB_SUCCESS;
791 return hp;
792nospc:
793 *he = NETDB_INTERNAL;
794 errno = ENOSPC;
795 return NULL;
796fake:
797 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
798 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
799
800 hp->h_aliases[0] = NULL;
801 if (size > buflen)
802 goto nospc;
803
804 if (inet_pton(af, name, buf) <= 0) {
805 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800806 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200807 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800808 hp->h_addr_list[0] = buf;
809 hp->h_addr_list[1] = NULL;
810 buf += size;
811 buflen -= size;
812 HENT_SCOPY(hp->h_name, name, buf, buflen);
813 if (res->options & RES_USE_INET6)
814 map_v4v6_hostent(hp, &buf, buf + buflen);
815 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800816 return hp;
817}
818
Mattias Falkc63e5902011-08-23 14:34:14 +0200819// very similar in proxy-ness to android_getaddrinfo_proxy
820static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800821gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400822 size_t hbuflen, int *errorp, const struct android_net_context *netcontext)
Mattias Falkc63e5902011-08-23 14:34:14 +0200823{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800824 FILE* proxy = android_open_proxy();
825 if (proxy == NULL) {
826 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartz90a83be2017-04-24 17:57:11 -0400827 res_setnetcontext(res, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -0800828 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Mattias Falkc63e5902011-08-23 14:34:14 +0200829 }
830
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400831 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Paul Jensen5240b562014-05-15 14:43:07 -0400832
Elliott Hughes9773fa32014-12-10 14:56:46 -0800833 // This is writing to system/netd/server/DnsProxyListener.cpp and changes
834 // here need to be matched there.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500835 if (fprintf(proxy, "gethostbyname %u %s %d",
836 netid,
Mattias Falkc63e5902011-08-23 14:34:14 +0200837 name == NULL ? "^" : name,
838 af) < 0) {
Elliott Hughes9773fa32014-12-10 14:56:46 -0800839 fclose(proxy);
840 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200841 }
842
843 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200844 fclose(proxy);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800845 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200846 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800847
Yabin Cui58d33a52014-12-16 17:03:44 -0800848 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800849 fclose(proxy);
Mattias Falkc63e5902011-08-23 14:34:14 +0200850 return result;
851}
852
Yabin Cui58d33a52014-12-16 17:03:44 -0800853/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
854int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
855 size_t buflen, struct hostent **result, int *h_errnop)
856{
Ben Schwartz50178052017-04-24 17:57:11 -0400857 *result = android_gethostbyaddrfornetcontext_proxy_internal(
858 addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
Elliott Hughesbb7d9fb2017-10-23 17:38:35 -0700859 return h_errno_to_result(h_errnop);
Yabin Cui58d33a52014-12-16 17:03:44 -0800860}
Mattias Falkc63e5902011-08-23 14:34:14 +0200861
Elliott Hughes9773fa32014-12-10 14:56:46 -0800862static struct hostent *
Ben Schwartz50178052017-04-24 17:57:11 -0400863android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
864 char *buf, size_t buflen, int *he,
865 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800866{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800867 const u_char *uaddr = (const u_char *)addr;
868 socklen_t size;
Yabin Cui58d33a52014-12-16 17:03:44 -0800869 struct getnamaddr info;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800870 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800871 NS_FILES_CB(_hf_gethtbyaddr, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800872 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800873 NS_NIS_CB(_yp_gethtbyaddr, NULL)
874 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800875 };
876
Yabin Cui58d33a52014-12-16 17:03:44 -0800877 _DIAGASSERT(addr != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800878
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700879 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
880 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
881 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800882 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800883 return NULL;
884 }
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700885 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
886 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
887 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800888 /* Unmap. */
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700889 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
890 addr = uaddr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800891 af = AF_INET;
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700892 len = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800893 }
894 switch (af) {
895 case AF_INET:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700896 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800897 break;
898 case AF_INET6:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700899 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800900 break;
901 default:
902 errno = EAFNOSUPPORT;
Yabin Cui58d33a52014-12-16 17:03:44 -0800903 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800904 return NULL;
905 }
906 if (size != len) {
907 errno = EINVAL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800908 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800909 return NULL;
910 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800911 info.hp = hp;
912 info.buf = buf;
913 info.buflen = buflen;
914 info.he = he;
915 *he = NETDB_INTERNAL;
916 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
Ben Schwartz50178052017-04-24 17:57:11 -0400917 default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800918 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800919 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800920 return hp;
921}
922
Yabin Cui58d33a52014-12-16 17:03:44 -0800923static struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -0400924android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
Yabin Cui58d33a52014-12-16 17:03:44 -0800925 struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
Ben Schwartz50178052017-04-24 17:57:11 -0400926 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800927{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800928 FILE* proxy = android_open_proxy();
929 if (proxy == NULL) {
930 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartz50178052017-04-24 17:57:11 -0400931 return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800932 }
933
934 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6
935 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
936 if (addrStr == NULL) {
937 fclose(proxy);
938 return NULL;
939 }
940
Ben Schwartz50178052017-04-24 17:57:11 -0400941 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800942
943 if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
944 addrStr, len, af, netid) < 0) {
945 fclose(proxy);
946 return NULL;
947 }
948
949 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
950 fclose(proxy);
951 return NULL;
952 }
953
Yabin Cui58d33a52014-12-16 17:03:44 -0800954 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800955 fclose(proxy);
956 return result;
957}
958
Yabin Cui58d33a52014-12-16 17:03:44 -0800959struct hostent*
960netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200961{
Yabin Cui58d33a52014-12-16 17:03:44 -0800962 char *p, *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800963 char *cp, **q;
964 int af, len;
Yabin Cui58d33a52014-12-16 17:03:44 -0800965 size_t anum;
966 char **aliases;
967 size_t maxaliases;
968 struct in6_addr host_addr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800969
Yabin Cui58d33a52014-12-16 17:03:44 -0800970 if (hf == NULL) {
971 *he = NETDB_INTERNAL;
972 errno = EINVAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800973 return NULL;
974 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800975 p = NULL;
976 setup(aliases, maxaliases);
977
978 /* Allocate a new space to read file lines like upstream does.
979 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
980 * as the buffer may be used to store content for a previous hostent
981 * returned by non-reentrant functions like gethostbyname().
982 */
983 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
984 if ((p = malloc(line_buf_size)) == NULL) {
985 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800986 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800987 for (;;) {
988 if (!fgets(p, line_buf_size, hf)) {
989 free(p);
990 free(aliases);
991 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800992 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800993 }
994 if (*p == '#') {
995 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800996 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800997 if (!(cp = strpbrk(p, "#\n"))) {
998 continue;
999 }
1000 *cp = '\0';
1001 if (!(cp = strpbrk(p, " \t")))
1002 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001003 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001004 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
1005 af = AF_INET6;
1006 len = NS_IN6ADDRSZ;
1007 } else {
1008 if (inet_pton(AF_INET, p, &host_addr) <= 0)
1009 continue;
1010
1011 res_state res = __res_get_state();
1012 if (res == NULL)
1013 goto nospc;
1014 if (res->options & RES_USE_INET6) {
1015 map_v4v6_address(buf, buf);
1016 af = AF_INET6;
1017 len = NS_IN6ADDRSZ;
1018 } else {
1019 af = AF_INET;
1020 len = NS_INADDRSZ;
1021 }
1022 __res_put_state(res);
1023 }
1024
1025 /* if this is not something we're looking for, skip it. */
1026 if (hent->h_addrtype != 0 && hent->h_addrtype != af)
1027 continue;
1028 if (hent->h_length != 0 && hent->h_length != len)
1029 continue;
1030
1031 while (*cp == ' ' || *cp == '\t')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001032 cp++;
Yabin Cui58d33a52014-12-16 17:03:44 -08001033 if ((cp = strpbrk(name = cp, " \t")) != NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001034 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001035 q = aliases;
1036 while (cp && *cp) {
1037 if (*cp == ' ' || *cp == '\t') {
1038 cp++;
1039 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001040 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001041 addalias(q, cp, aliases, maxaliases);
1042 if ((cp = strpbrk(cp, " \t")) != NULL)
1043 *cp++ = '\0';
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001044 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001045 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001046 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001047 hent->h_length = len;
1048 hent->h_addrtype = af;
1049 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1050 anum = (size_t)(q - aliases);
1051 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
1052 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
1053 buflen);
1054 hent->h_addr_list[1] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001055
Yabin Cui58d33a52014-12-16 17:03:44 -08001056 HENT_SCOPY(hent->h_name, name, buf, buflen);
1057 for (size_t i = 0; i < anum; i++)
1058 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1059 hent->h_aliases[anum] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001060
Yabin Cui58d33a52014-12-16 17:03:44 -08001061 *he = NETDB_SUCCESS;
1062 free(p);
1063 free(aliases);
1064 return hent;
1065nospc:
1066 free(p);
1067 free(aliases);
1068 errno = ENOSPC;
1069 *he = NETDB_INTERNAL;
1070 return NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001071}
1072
1073static void
1074map_v4v6_address(const char *src, char *dst)
1075{
1076 u_char *p = (u_char *)dst;
Yabin Cui58d33a52014-12-16 17:03:44 -08001077 char tmp[NS_INADDRSZ];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001078 int i;
1079
Yabin Cui58d33a52014-12-16 17:03:44 -08001080 _DIAGASSERT(src != NULL);
1081 _DIAGASSERT(dst != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001082
1083 /* Stash a temporary copy so our caller can update in place. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001084 (void)memcpy(tmp, src, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001085 /* Mark this ipv6 addr as a mapped ipv4. */
1086 for (i = 0; i < 10; i++)
1087 *p++ = 0x00;
1088 *p++ = 0xff;
1089 *p++ = 0xff;
1090 /* Retrieve the saved copy and we're done. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001091 (void)memcpy(p, tmp, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001092}
1093
1094static void
1095map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1096{
1097 char **ap;
1098
Yabin Cui58d33a52014-12-16 17:03:44 -08001099 _DIAGASSERT(hp != NULL);
1100 _DIAGASSERT(bpp != NULL);
1101 _DIAGASSERT(ep != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001102
Yabin Cui58d33a52014-12-16 17:03:44 -08001103 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001104 return;
1105 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001106 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001107 for (ap = hp->h_addr_list; *ap; ap++) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001108 int i = (int)(sizeof(align) -
1109 (size_t)((u_long)*bpp % sizeof(align)));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001110
Yabin Cui58d33a52014-12-16 17:03:44 -08001111 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001112 /* Out of memory. Truncate address list here. XXX */
1113 *ap = NULL;
1114 return;
1115 }
1116 *bpp += i;
1117 map_v4v6_address(*ap, *bpp);
1118 *ap = *bpp;
Yabin Cui58d33a52014-12-16 17:03:44 -08001119 *bpp += NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001120 }
1121}
1122
1123static void
1124addrsort(char **ap, int num, res_state res)
1125{
1126 int i, j;
1127 char **p;
1128 short aval[MAXADDRS];
1129 int needsort = 0;
1130
Yabin Cui58d33a52014-12-16 17:03:44 -08001131 _DIAGASSERT(ap != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001132
1133 p = ap;
1134 for (i = 0; i < num; i++, p++) {
1135 for (j = 0 ; (unsigned)j < res->nsort; j++)
1136 if (res->sort_list[j].addr.s_addr ==
1137 (((struct in_addr *)(void *)(*p))->s_addr &
1138 res->sort_list[j].mask))
1139 break;
1140 aval[i] = j;
1141 if (needsort == 0 && i > 0 && j < aval[i-1])
1142 needsort = i;
1143 }
1144 if (!needsort)
1145 return;
1146
1147 while (needsort < num) {
1148 for (j = needsort - 1; j >= 0; j--) {
1149 if (aval[j] > aval[j+1]) {
1150 char *hp;
1151
1152 i = aval[j];
1153 aval[j] = aval[j+1];
1154 aval[j+1] = i;
1155
1156 hp = ap[j];
1157 ap[j] = ap[j+1];
1158 ap[j+1] = hp;
1159 } else
1160 break;
1161 }
1162 needsort++;
1163 }
1164}
1165
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001166/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001167static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001168_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1169{
1170 querybuf *buf;
1171 int n, type;
1172 struct hostent *hp;
1173 const char *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001174 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001175 struct getnamaddr *info = rv;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001176
Yabin Cui58d33a52014-12-16 17:03:44 -08001177 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001178
1179 name = va_arg(ap, char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001180 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1181 info->hp->h_addrtype = va_arg(ap, int);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001182
Yabin Cui58d33a52014-12-16 17:03:44 -08001183 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001184 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -08001185 info->hp->h_length = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001186 type = T_A;
1187 break;
1188 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -08001189 info->hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001190 type = T_AAAA;
1191 break;
1192 default:
1193 return NS_UNAVAIL;
1194 }
1195 buf = malloc(sizeof(*buf));
1196 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001197 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001198 return NS_NOTFOUND;
1199 }
1200 res = __res_get_state();
1201 if (res == NULL) {
1202 free(buf);
1203 return NS_NOTFOUND;
1204 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001205 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001206 if (n < 0) {
1207 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001208 debugprintf("res_nsearch failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001209 __res_put_state(res);
1210 return NS_NOTFOUND;
1211 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001212 hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
1213 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001214 free(buf);
1215 __res_put_state(res);
1216 if (hp == NULL)
Yabin Cui70692562014-12-19 10:10:04 -08001217 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001218 case HOST_NOT_FOUND:
1219 return NS_NOTFOUND;
1220 case TRY_AGAIN:
1221 return NS_TRYAGAIN;
1222 default:
1223 return NS_UNAVAIL;
1224 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001225 return NS_SUCCESS;
1226}
1227
1228/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001229static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001230_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1231{
1232 char qbuf[MAXDNAME + 1], *qp, *ep;
1233 int n;
1234 querybuf *buf;
1235 struct hostent *hp;
1236 const unsigned char *uaddr;
Yabin Cui58d33a52014-12-16 17:03:44 -08001237 int advance;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001238 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001239 char *bf;
1240 size_t blen;
1241 struct getnamaddr *info = rv;
Ben Schwartz50178052017-04-24 17:57:11 -04001242 const struct android_net_context *netcontext;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001243
Yabin Cui58d33a52014-12-16 17:03:44 -08001244 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001245
1246 uaddr = va_arg(ap, unsigned char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001247 info->hp->h_length = va_arg(ap, int);
1248 info->hp->h_addrtype = va_arg(ap, int);
Ben Schwartz50178052017-04-24 17:57:11 -04001249 netcontext = va_arg(ap, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001250
Yabin Cui58d33a52014-12-16 17:03:44 -08001251 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001252 case AF_INET:
1253 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1254 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1255 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1256 break;
1257
1258 case AF_INET6:
1259 qp = qbuf;
1260 ep = qbuf + sizeof(qbuf) - 1;
Yabin Cui58d33a52014-12-16 17:03:44 -08001261 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001262 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1263 uaddr[n] & 0xf,
1264 ((unsigned int)uaddr[n] >> 4) & 0xf);
1265 if (advance > 0 && qp + advance < ep)
1266 qp += advance;
1267 else {
Yabin Cui58d33a52014-12-16 17:03:44 -08001268 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001269 return NS_NOTFOUND;
1270 }
1271 }
1272 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001273 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001274 return NS_NOTFOUND;
1275 }
1276 break;
1277 default:
Yabin Cui58d33a52014-12-16 17:03:44 -08001278 return NS_UNAVAIL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001279 }
1280
1281 buf = malloc(sizeof(*buf));
1282 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001283 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001284 return NS_NOTFOUND;
1285 }
1286 res = __res_get_state();
1287 if (res == NULL) {
1288 free(buf);
1289 return NS_NOTFOUND;
1290 }
Ben Schwartz90a83be2017-04-24 17:57:11 -04001291 res_setnetcontext(res, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001292 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 -08001293 if (n < 0) {
1294 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001295 debugprintf("res_nquery failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001296 __res_put_state(res);
1297 return NS_NOTFOUND;
1298 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001299 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1300 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001301 free(buf);
1302 if (hp == NULL) {
1303 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001304 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001305 case HOST_NOT_FOUND:
1306 return NS_NOTFOUND;
1307 case TRY_AGAIN:
1308 return NS_TRYAGAIN;
1309 default:
1310 return NS_UNAVAIL;
1311 }
1312 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001313
1314 bf = (void *)(hp->h_addr_list + 2);
1315 blen = (size_t)(bf - info->buf);
1316 if (blen + info->hp->h_length > info->buflen)
1317 goto nospc;
1318 hp->h_addr_list[0] = bf;
1319 hp->h_addr_list[1] = NULL;
1320 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1321 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1322 if (blen + NS_IN6ADDRSZ > info->buflen)
1323 goto nospc;
1324 map_v4v6_address(bf, bf);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001325 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001326 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001327 }
1328
1329 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001330 *info->he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001331 return NS_SUCCESS;
Yabin Cui58d33a52014-12-16 17:03:44 -08001332nospc:
Yabin Cui70692562014-12-19 10:10:04 -08001333 errno = ENOSPC;
Yabin Cui58d33a52014-12-16 17:03:44 -08001334 *info->he = NETDB_INTERNAL;
1335 return NS_UNAVAIL;
1336}
1337
1338#ifdef YP
1339/*ARGSUSED*/
1340static struct hostent *
1341_yp_hostent(char *line, int af, struct getnamaddr *info)
1342{
1343 struct in6_addr host_addrs[MAXADDRS];
1344 char **aliases;
1345 size_t maxaliases;
1346 char *p = line;
1347 char *cp, **q, *ptr;
1348 size_t len, anum, i;
1349 int addrok;
1350 int more;
1351 size_t naddrs;
1352 struct hostent *hp = info->hp;
1353
1354 _DIAGASSERT(line != NULL);
1355
1356 hp->h_name = NULL;
1357 hp->h_addrtype = af;
1358 switch (af) {
1359 case AF_INET:
1360 hp->h_length = NS_INADDRSZ;
1361 break;
1362 case AF_INET6:
1363 hp->h_length = NS_IN6ADDRSZ;
1364 break;
1365 default:
1366 return NULL;
1367 }
1368 setup(aliases, maxaliases);
1369 naddrs = 0;
1370 q = aliases;
1371
1372nextline:
1373 /* check for host_addrs overflow */
1374 if (naddrs >= __arraycount(host_addrs))
1375 goto done;
1376
1377 more = 0;
1378 cp = strpbrk(p, " \t");
1379 if (cp == NULL)
1380 goto done;
1381 *cp++ = '\0';
1382
1383 /* p has should have an address */
1384 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1385 if (addrok != 1) {
1386 /* skip to the next line */
1387 while (cp && *cp) {
1388 if (*cp == '\n') {
1389 cp++;
1390 goto nextline;
1391 }
1392 cp++;
1393 }
1394 goto done;
1395 }
1396 naddrs++;
1397
1398 while (*cp == ' ' || *cp == '\t')
1399 cp++;
1400 p = cp;
1401 cp = strpbrk(p, " \t\n");
1402 if (cp != NULL) {
1403 if (*cp == '\n')
1404 more = 1;
1405 *cp++ = '\0';
1406 }
1407 if (!hp->h_name)
1408 hp->h_name = p;
1409 else if (strcmp(hp->h_name, p) == 0)
1410 ;
1411 else
1412 addalias(q, p, aliases, maxaliases);
1413 p = cp;
1414 if (more)
1415 goto nextline;
1416
1417 while (cp && *cp) {
1418 if (*cp == ' ' || *cp == '\t') {
1419 cp++;
1420 continue;
1421 }
1422 if (*cp == '\n') {
1423 cp++;
1424 goto nextline;
1425 }
1426 addalias(q, cp, aliases, maxaliases);
1427 cp = strpbrk(cp, " \t");
1428 if (cp != NULL)
1429 *cp++ = '\0';
1430 }
1431
1432done:
1433 if (hp->h_name == NULL) {
1434 free(aliases);
1435 return NULL;
1436 }
1437
1438 ptr = info->buf;
1439 len = info->buflen;
1440
1441 anum = (size_t)(q - aliases);
1442 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1443 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1444
1445 for (i = 0; i < naddrs; i++)
1446 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1447 ptr, len);
1448 hp->h_addr_list[naddrs] = NULL;
1449
1450 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1451
1452 for (i = 0; i < anum; i++)
1453 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1454 hp->h_aliases[anum] = NULL;
1455 free(aliases);
1456
1457 return hp;
1458nospc:
1459 free(aliases);
1460 *info->he = NETDB_INTERNAL;
1461 errno = ENOSPC;
1462 return NULL;
1463}
1464
1465/*ARGSUSED*/
1466int
1467_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1468{
1469 struct hostent *hp = NULL;
1470 char *ypcurrent;
1471 int ypcurrentlen, r;
1472 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1473 const unsigned char *uaddr;
1474 int af;
1475 const char *map;
1476 struct getnamaddr *info = rv;
1477
1478 _DIAGASSERT(rv != NULL);
1479
1480 uaddr = va_arg(ap, unsigned char *);
1481 /* NOSTRICT skip len */(void)va_arg(ap, int);
1482 af = va_arg(ap, int);
1483
1484 if (!__ypdomain) {
1485 if (_yp_check(&__ypdomain) == 0)
1486 return NS_UNAVAIL;
1487 }
1488 /*
1489 * XXX unfortunately, we cannot support IPv6 extended scoped address
1490 * notation here. gethostbyaddr() is not scope-aware. too bad.
1491 */
1492 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1493 return NS_UNAVAIL;
1494 switch (af) {
1495 case AF_INET:
1496 map = "hosts.byaddr";
1497 break;
1498 default:
1499 map = "ipnodes.byaddr";
1500 break;
1501 }
1502 ypcurrent = NULL;
1503 r = yp_match(__ypdomain, map, name,
1504 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1505 if (r == 0)
1506 hp = _yp_hostent(ypcurrent, af, info);
1507 else
1508 hp = NULL;
1509 free(ypcurrent);
1510 if (hp == NULL) {
1511 *info->he = HOST_NOT_FOUND;
1512 return NS_NOTFOUND;
1513 }
1514 return NS_SUCCESS;
1515}
1516
1517/*ARGSUSED*/
1518int
1519_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1520{
1521 struct hostent *hp;
1522 char *ypcurrent;
1523 int ypcurrentlen, r;
1524 const char *name;
1525 int af;
1526 const char *map;
1527 struct getnamaddr *info = rv;
1528
1529 _DIAGASSERT(rv != NULL);
1530
1531 name = va_arg(ap, char *);
1532 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1533 af = va_arg(ap, int);
1534
1535 if (!__ypdomain) {
1536 if (_yp_check(&__ypdomain) == 0)
1537 return NS_UNAVAIL;
1538 }
1539 switch (af) {
1540 case AF_INET:
1541 map = "hosts.byname";
1542 break;
1543 default:
1544 map = "ipnodes.byname";
1545 break;
1546 }
1547 ypcurrent = NULL;
1548 r = yp_match(__ypdomain, map, name,
1549 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1550 if (r == 0)
1551 hp = _yp_hostent(ypcurrent, af, info);
1552 else
1553 hp = NULL;
1554 free(ypcurrent);
1555 if (hp == NULL) {
1556 *info->he = HOST_NOT_FOUND;
1557 return NS_NOTFOUND;
1558 }
1559 return NS_SUCCESS;
1560}
1561#endif
1562
1563/*
1564 * Non-reentrant versions.
1565 */
1566
1567struct hostent *
1568gethostbyname(const char *name)
1569{
1570 struct hostent *result = NULL;
1571 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1572
1573 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1574 return result;
1575}
1576
1577struct hostent *
1578gethostbyname2(const char *name, int af)
1579{
1580 struct hostent *result = NULL;
1581 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1582
1583 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1584 return result;
1585}
1586
Ben Schwartz50178052017-04-24 17:57:11 -04001587// android_gethostby*fornet can be called in two different contexts.
1588// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1589// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1590// The netcontext is constructed before checking which context we are in.
1591// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1592// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1593static struct android_net_context make_context(unsigned netid, unsigned mark) {
1594 struct android_net_context netcontext = NETCONTEXT_UNSET;
1595 netcontext.app_netid = netid;
1596 netcontext.app_mark = mark;
1597 netcontext.dns_netid = netid;
1598 netcontext.dns_mark = mark;
1599 return netcontext;
1600}
1601
Yabin Cui58d33a52014-12-16 17:03:44 -08001602struct hostent *
1603android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
1604{
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001605 const struct android_net_context netcontext = make_context(netid, mark);
1606 return android_gethostbynamefornetcontext(name, af, &netcontext);
1607}
1608
1609struct hostent *
1610android_gethostbynamefornetcontext(const char *name, int af,
1611 const struct android_net_context *netcontext)
1612{
Yabin Cui58d33a52014-12-16 17:03:44 -08001613 struct hostent *hp;
1614 res_state res = __res_get_state();
1615 if (res == NULL)
1616 return NULL;
1617 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1618 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001619 &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001620 __res_put_state(res);
1621 return hp;
1622}
1623
1624struct hostent *
1625gethostbyaddr(const void *addr, socklen_t len, int af)
1626{
Ben Schwartz50178052017-04-24 17:57:11 -04001627 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -08001628}
1629
1630struct hostent *
1631android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
1632{
Ben Schwartz50178052017-04-24 17:57:11 -04001633 const struct android_net_context netcontext = make_context(netid, mark);
1634 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
1635}
1636
1637struct hostent *
1638android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
1639 const struct android_net_context *netcontext)
1640{
1641 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001642}
1643
1644__LIBC_HIDDEN__ struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -04001645android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
1646 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -08001647{
1648 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Ben Schwartz50178052017-04-24 17:57:11 -04001649 return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
1650 sizeof(rs->hostbuf), &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001651}
1652
1653struct hostent *
1654gethostent(void)
1655{
1656 res_static rs = __res_get_static();
1657 if (!rs->hostf) {
1658 sethostent_r(&rs->hostf);
1659 if (!rs->hostf) {
1660 h_errno = NETDB_INTERNAL;
1661 return NULL;
1662 }
1663 }
1664 memset(&rs->host, 0, sizeof(rs->host));
1665 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 -08001666}