blob: a22d718f294639b8a0247f5d168c3ddd8df87c2c [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
173
174#ifdef DEBUG
175static void
Yabin Cui58d33a52014-12-16 17:03:44 -0800176debugprintf(const char *msg, res_state res, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800177{
Yabin Cui58d33a52014-12-16 17:03:44 -0800178 _DIAGASSERT(msg != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800179
180 if (res->options & RES_DEBUG) {
181 int save = errno;
182 va_list ap;
183
184 va_start (ap, res);
185 vprintf(msg, ap);
186 va_end (ap);
187
188 errno = save;
189 }
190}
191#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800192# define debugprintf(msg, res, num) /*nada*/
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800193#endif
194
195#define BOUNDED_INCR(x) \
196 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800197 BOUNDS_CHECK(cp, x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800198 cp += (x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800199 } while (/*CONSTCOND*/0)
200
201#define BOUNDS_CHECK(ptr, count) \
202 do { \
Elliott Hughes87c0dba2016-11-14 13:56:32 -0800203 if (eom - (ptr) < (count)) \
Yabin Cui58d33a52014-12-16 17:03:44 -0800204 goto no_recovery; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800205 } while (/*CONSTCOND*/0)
206
207static struct hostent *
208getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
Yabin Cui58d33a52014-12-16 17:03:44 -0800209 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800210{
211 const HEADER *hp;
212 const u_char *cp;
213 int n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800214 size_t qlen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800215 const u_char *eom, *erdata;
216 char *bp, **ap, **hap, *ep;
217 int type, class, ancount, qdcount;
218 int haveanswer, had_error;
219 int toobig = 0;
220 char tbuf[MAXDNAME];
Yabin Cui58d33a52014-12-16 17:03:44 -0800221 char **aliases;
222 size_t maxaliases;
223 char *addr_ptrs[MAXADDRS];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800224 const char *tname;
225 int (*name_ok)(const char *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800226
Yabin Cui58d33a52014-12-16 17:03:44 -0800227 _DIAGASSERT(answer != NULL);
228 _DIAGASSERT(qname != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800229
230 tname = qname;
Yabin Cui58d33a52014-12-16 17:03:44 -0800231 hent->h_name = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800232 eom = answer->buf + anslen;
233 switch (qtype) {
234 case T_A:
235 case T_AAAA:
236 name_ok = res_hnok;
237 break;
238 case T_PTR:
239 name_ok = res_dnok;
240 break;
241 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800242 *he = NO_RECOVERY;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800243 return NULL; /* XXX should be abort(); */
244 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800245
246 setup(aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800247 /*
248 * find first satisfactory answer
249 */
250 hp = &answer->hdr;
251 ancount = ntohs(hp->ancount);
252 qdcount = ntohs(hp->qdcount);
Yabin Cui58d33a52014-12-16 17:03:44 -0800253 bp = buf;
254 ep = buf + buflen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800255 cp = answer->buf;
256 BOUNDED_INCR(HFIXEDSZ);
Yabin Cui58d33a52014-12-16 17:03:44 -0800257 if (qdcount != 1)
258 goto no_recovery;
259
260 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
261 if ((n < 0) || !maybe_ok(res, bp, name_ok))
262 goto no_recovery;
263
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800264 BOUNDED_INCR(n + QFIXEDSZ);
265 if (qtype == T_A || qtype == T_AAAA) {
266 /* res_send() has already verified that the query name is the
267 * same as the one we sent; this just gets the expanded name
268 * (i.e., with the succeeding search-domain tacked on).
269 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800270 n = (int)strlen(bp) + 1; /* for the \0 */
271 if (n >= MAXHOSTNAMELEN)
272 goto no_recovery;
273 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800274 bp += n;
275 /* The qname can be abbreviated, but h_name is now absolute. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800276 qname = hent->h_name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800277 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800278 hent->h_aliases = ap = aliases;
279 hent->h_addr_list = hap = addr_ptrs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800280 *ap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800281 *hap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800282 haveanswer = 0;
283 had_error = 0;
284 while (ancount-- > 0 && cp < eom && !had_error) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800285 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
286 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800287 had_error++;
288 continue;
289 }
290 cp += n; /* name */
291 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
292 type = _getshort(cp);
293 cp += INT16SZ; /* type */
294 class = _getshort(cp);
295 cp += INT16SZ + INT32SZ; /* class, TTL */
296 n = _getshort(cp);
297 cp += INT16SZ; /* len */
298 BOUNDS_CHECK(cp, n);
299 erdata = cp + n;
300 if (class != C_IN) {
301 /* XXX - debug? syslog? */
302 cp += n;
303 continue; /* XXX - had_error++ ? */
304 }
305 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800306 n = dn_expand(answer->buf, eom, cp, tbuf,
307 (int)sizeof tbuf);
308 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800309 had_error++;
310 continue;
311 }
312 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800313 if (cp != erdata)
314 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800315 /* Store alias. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800316 addalias(ap, bp, aliases, maxaliases);
317 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800318 if (n >= MAXHOSTNAMELEN) {
319 had_error++;
320 continue;
321 }
322 bp += n;
323 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800324 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800325 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
326 had_error++;
327 continue;
328 }
329 strlcpy(bp, tbuf, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800330 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800331 bp += n;
332 continue;
333 }
334 if (qtype == T_PTR && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800335 n = dn_expand(answer->buf, eom, cp, tbuf,
336 (int)sizeof tbuf);
337 if (n < 0 || !maybe_dnok(res, tbuf)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800338 had_error++;
339 continue;
340 }
341 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800342 if (cp != erdata)
343 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800344 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800345 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800346 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
347 had_error++;
348 continue;
349 }
350 strlcpy(bp, tbuf, (size_t)(ep - bp));
351 tname = bp;
352 bp += n;
353 continue;
354 }
355 if (type != qtype) {
356 if (type != T_KEY && type != T_SIG)
357 syslog(LOG_NOTICE|LOG_AUTH,
358 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
359 qname, p_class(C_IN), p_type(qtype),
360 p_type(type));
361 cp += n;
362 continue; /* XXX - had_error++ ? */
363 }
364 switch (type) {
365 case T_PTR:
366 if (strcasecmp(tname, bp) != 0) {
367 syslog(LOG_NOTICE|LOG_AUTH,
368 AskedForGot, qname, bp);
369 cp += n;
370 continue; /* XXX - had_error++ ? */
371 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800372 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
373 if ((n < 0) || !maybe_hnok(res, bp)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800374 had_error++;
375 break;
376 }
377#if MULTI_PTRS_ARE_ALIASES
378 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800379 if (cp != erdata)
380 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800381 if (!haveanswer)
Yabin Cui58d33a52014-12-16 17:03:44 -0800382 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800383 else
Yabin Cui58d33a52014-12-16 17:03:44 -0800384 addalias(ap, bp, aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800385 if (n != -1) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800386 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800387 if (n >= MAXHOSTNAMELEN) {
388 had_error++;
389 break;
390 }
391 bp += n;
392 }
393 break;
394#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800395 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800396 if (res->options & RES_USE_INET6) {
397 n = strlen(bp) + 1; /* for the \0 */
398 if (n >= MAXHOSTNAMELEN) {
399 had_error++;
400 break;
401 }
402 bp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800403 map_v4v6_hostent(hent, &bp, ep);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800404 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800405 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800406#endif
407 case T_A:
408 case T_AAAA:
Yabin Cui58d33a52014-12-16 17:03:44 -0800409 if (strcasecmp(hent->h_name, bp) != 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800410 syslog(LOG_NOTICE|LOG_AUTH,
Yabin Cui58d33a52014-12-16 17:03:44 -0800411 AskedForGot, hent->h_name, bp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800412 cp += n;
413 continue; /* XXX - had_error++ ? */
414 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800415 if (n != hent->h_length) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800416 cp += n;
417 continue;
418 }
419 if (type == T_AAAA) {
420 struct in6_addr in6;
Yabin Cui58d33a52014-12-16 17:03:44 -0800421 memcpy(&in6, cp, NS_IN6ADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800422 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
423 cp += n;
424 continue;
425 }
426 }
427 if (!haveanswer) {
428 int nn;
429
Yabin Cui58d33a52014-12-16 17:03:44 -0800430 hent->h_name = bp;
431 nn = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800432 bp += nn;
433 }
434
435 bp += sizeof(align) -
436 (size_t)((u_long)bp % sizeof(align));
437
Yabin Cui58d33a52014-12-16 17:03:44 -0800438 if (bp + n >= ep) {
439 debugprintf("size (%d) too big\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800440 had_error++;
441 continue;
442 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800443 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
444 if (!toobig++) {
445 debugprintf("Too many addresses (%d)\n",
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800446 res, MAXADDRS);
Yabin Cui58d33a52014-12-16 17:03:44 -0800447 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800448 cp += n;
449 continue;
450 }
451 (void)memcpy(*hap++ = bp, cp, (size_t)n);
452 bp += n;
453 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800454 if (cp != erdata)
455 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800456 break;
457 default:
458 abort();
459 }
460 if (!had_error)
461 haveanswer++;
462 }
463 if (haveanswer) {
464 *ap = NULL;
465 *hap = NULL;
466 /*
467 * Note: we sort even if host can take only one address
468 * in its return structures - should give it the "best"
469 * address in that case, not some random one
470 */
471 if (res->nsort && haveanswer > 1 && qtype == T_A)
Yabin Cui58d33a52014-12-16 17:03:44 -0800472 addrsort(addr_ptrs, haveanswer, res);
473 if (!hent->h_name) {
474 n = (int)strlen(qname) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800475 if (n > ep - bp || n >= MAXHOSTNAMELEN)
476 goto no_recovery;
477 strlcpy(bp, qname, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800478 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800479 bp += n;
480 }
481 if (res->options & RES_USE_INET6)
Yabin Cui58d33a52014-12-16 17:03:44 -0800482 map_v4v6_hostent(hent, &bp, ep);
483 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800484 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800485no_recovery:
486 free(aliases);
487 *he = NO_RECOVERY;
488 return NULL;
489success:
490 bp = (char *)ALIGN(bp);
491 n = (int)(ap - aliases);
492 qlen = (n + 1) * sizeof(*hent->h_aliases);
493 if ((size_t)(ep - bp) < qlen)
494 goto nospc;
495 hent->h_aliases = (void *)bp;
496 memcpy(bp, aliases, qlen);
497 free(aliases);
498 aliases = NULL;
499
500 bp += qlen;
501 n = (int)(hap - addr_ptrs);
502 qlen = (n + 1) * sizeof(*hent->h_addr_list);
503 if ((size_t)(ep - bp) < qlen)
504 goto nospc;
505 hent->h_addr_list = (void *)bp;
506 memcpy(bp, addr_ptrs, qlen);
507 *he = NETDB_SUCCESS;
508 return hent;
509nospc:
510 free(aliases);
511 errno = ENOSPC;
512 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800513 return NULL;
514}
515
Yabin Cui58d33a52014-12-16 17:03:44 -0800516/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800517int
518gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
Yabin Cui58d33a52014-12-16 17:03:44 -0800519 struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800520{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800521 res_state res = __res_get_state();
522
Yabin Cui58d33a52014-12-16 17:03:44 -0800523 if (res == NULL) {
524 *result = NULL;
525 *errorp = NETDB_INTERNAL;
526 return -1;
527 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800528
Yabin Cui58d33a52014-12-16 17:03:44 -0800529 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800530
531 if (res->options & RES_USE_INET6) {
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400532 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
533 &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -0800534 if (*result) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800535 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800536 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800537 }
538 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400539 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp,
540 &NETCONTEXT_UNSET);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800541 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800542 if (!*result && errno == ENOSPC) {
543 errno = ERANGE;
544 return ERANGE; /* Return error as in linux manual page. */
545 }
546 return (*result) ? 0 : -1;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800547}
548
Yabin Cui58d33a52014-12-16 17:03:44 -0800549/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
550int
551gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
552 size_t buflen, struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800553{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800554 res_state res = __res_get_state();
555
Yabin Cui58d33a52014-12-16 17:03:44 -0800556 if (res == NULL) {
557 *result = NULL;
558 *errorp = NETDB_INTERNAL;
559 return -1;
560 }
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400561 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp,
562 &NETCONTEXT_UNSET);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800563 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800564 if (!*result && errno == ENOSPC) {
565 errno = ERANGE;
566 return ERANGE;
567 }
568 return (*result) ? 0 : -1;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800569}
570
Elliott Hughes9773fa32014-12-10 14:56:46 -0800571__LIBC_HIDDEN__ FILE* android_open_proxy() {
572 const char* cache_mode = getenv("ANDROID_DNS_MODE");
573 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
574 if (!use_proxy) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200575 return NULL;
576 }
577
Elliott Hughes9773fa32014-12-10 14:56:46 -0800578 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
579 if (s == -1) {
580 return NULL;
581 }
582
583 const int one = 1;
584 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
585
586 struct sockaddr_un proxy_addr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200587 memset(&proxy_addr, 0, sizeof(proxy_addr));
588 proxy_addr.sun_family = AF_UNIX;
589 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Elliott Hughes9773fa32014-12-10 14:56:46 -0800590
591 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
592 close(s);
Mattias Falkc63e5902011-08-23 14:34:14 +0200593 return NULL;
594 }
595
Elliott Hughes9773fa32014-12-10 14:56:46 -0800596 return fdopen(s, "r+");
Mattias Falkc63e5902011-08-23 14:34:14 +0200597}
598
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800599static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800600android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200601{
602 uint32_t size;
603 char buf[4];
604 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
605
Elliott Hughes9773fa32014-12-10 14:56:46 -0800606 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp
607 // and changes here need to be matched there.
Mattias Falkc63e5902011-08-23 14:34:14 +0200608 int result_code = strtol(buf, NULL, 10);
609 if (result_code != DnsProxyQueryResult) {
610 fread(&size, 1, sizeof(size), proxy);
Yabin Cui58d33a52014-12-16 17:03:44 -0800611 *he = HOST_NOT_FOUND;
Mattias Falkc63e5902011-08-23 14:34:14 +0200612 return NULL;
613 }
614
615 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
616 size = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200617
Yabin Cui58d33a52014-12-16 17:03:44 -0800618 memset(hp, 0, sizeof(*hp));
619 char *ptr = hbuf;
620 char *hbuf_end = hbuf + hbuflen;
621
622 if (ptr + size > hbuf_end) {
623 goto nospc;
624 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200625 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800626 hp->h_name = ptr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200627 ptr += size;
Mattias Falkc63e5902011-08-23 14:34:14 +0200628
Yabin Cui58d33a52014-12-16 17:03:44 -0800629 char *aliases_ptrs[MAXALIASES];
630 char **aliases = &aliases_ptrs[0];
631
Mattias Falkc63e5902011-08-23 14:34:14 +0200632 while (1) {
633 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
634 size = ntohl(size);
635
636 if (size == 0) {
637 *aliases = NULL;
638 break;
639 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800640 if (ptr + size > hbuf_end) {
641 goto nospc;
642 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200643 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800644 if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
645 *aliases++ = ptr;
646 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200647 ptr += size;
648 }
649
Elliott Hughes65dd8582015-07-06 14:16:12 -0700650 // Fix alignment after variable-length data.
651 ptr = (char*)ALIGN(ptr);
652
Yabin Cui58d33a52014-12-16 17:03:44 -0800653 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
654 if (ptr + aliases_len > hbuf_end) {
655 goto nospc;
656 }
657 hp->h_aliases = (void*)ptr;
658 memcpy(ptr, aliases_ptrs, aliases_len);
659 ptr += aliases_len;
Mattias Falkc63e5902011-08-23 14:34:14 +0200660
661 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800662 hp->h_addrtype = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200663
Yabin Cui58d33a52014-12-16 17:03:44 -0800664 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
665 hp->h_length = ntohl(size);
666
667 char *addr_ptrs[MAXADDRS];
668 char **addr_p = &addr_ptrs[0];
669
Mattias Falkc63e5902011-08-23 14:34:14 +0200670 while (1) {
671 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
672 size = ntohl(size);
673 if (size == 0) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800674 *addr_p = NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200675 break;
676 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800677 if (ptr + size > hbuf_end) {
678 goto nospc;
679 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200680 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800681 if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
682 *addr_p++ = ptr;
683 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200684 ptr += size;
685 }
686
Elliott Hughes65dd8582015-07-06 14:16:12 -0700687 // Fix alignment after variable-length data.
688 ptr = (char*)ALIGN(ptr);
689
Yabin Cui58d33a52014-12-16 17:03:44 -0800690 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
691 if (ptr + addrs_len > hbuf_end) {
692 goto nospc;
693 }
694 hp->h_addr_list = (void*)ptr;
695 memcpy(ptr, addr_ptrs, addrs_len);
696 *he = NETDB_SUCCESS;
697 return hp;
698
699nospc:
700 *he = NETDB_INTERNAL;
701 errno = ENOSPC;
702 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200703}
704
Mattias Falkc63e5902011-08-23 14:34:14 +0200705static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800706gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf,
707 size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800708{
709 const char *cp;
Yabin Cui58d33a52014-12-16 17:03:44 -0800710 struct getnamaddr info;
711 char hbuf[MAXHOSTNAMELEN];
712 size_t size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800713 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800714 NS_FILES_CB(_hf_gethtbyname, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800715 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800716 NS_NIS_CB(_yp_gethtbyname, NULL)
717 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800718 };
719
Yabin Cui58d33a52014-12-16 17:03:44 -0800720 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800721
722 switch (af) {
723 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -0800724 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800725 break;
726 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -0800727 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800728 break;
729 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800730 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800731 errno = EAFNOSUPPORT;
732 return NULL;
733 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800734 if (buflen < size)
735 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800736
Yabin Cui58d33a52014-12-16 17:03:44 -0800737 hp->h_addrtype = af;
738 hp->h_length = (int)size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800739
740 /*
741 * if there aren't any dots, it could be a user-level alias.
742 * this is also done in res_nquery() since we are not the only
743 * function that looks up host names.
744 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800745 if (!strchr(name, '.') && (cp = res_hostalias(res, name,
746 hbuf, sizeof(hbuf))))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800747 name = cp;
748
749 /*
750 * disallow names consisting only of digits/dots, unless
751 * they end in a dot.
752 */
753 if (isdigit((u_char) name[0]))
754 for (cp = name;; ++cp) {
755 if (!*cp) {
756 if (*--cp == '.')
757 break;
758 /*
759 * All-numeric, no dot at the end.
760 * Fake up a hostent as if we'd actually
761 * done a lookup.
762 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800763 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800764 }
765 if (!isdigit((u_char) *cp) && *cp != '.')
766 break;
767 }
768 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
769 name[0] == ':')
770 for (cp = name;; ++cp) {
771 if (!*cp) {
772 if (*--cp == '.')
773 break;
774 /*
775 * All-IPv6-legal, no dot at the end.
776 * Fake up a hostent as if we'd actually
777 * done a lookup.
778 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800779 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800780 }
781 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
782 break;
783 }
784
Yabin Cui58d33a52014-12-16 17:03:44 -0800785 *he = NETDB_INTERNAL;
786 info.hp = hp;
787 info.buf = buf;
788 info.buflen = buflen;
789 info.he = he;
790 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
791 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
792 return NULL;
793 *he = NETDB_SUCCESS;
794 return hp;
795nospc:
796 *he = NETDB_INTERNAL;
797 errno = ENOSPC;
798 return NULL;
799fake:
800 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
801 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
802
803 hp->h_aliases[0] = NULL;
804 if (size > buflen)
805 goto nospc;
806
807 if (inet_pton(af, name, buf) <= 0) {
808 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800809 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200810 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800811 hp->h_addr_list[0] = buf;
812 hp->h_addr_list[1] = NULL;
813 buf += size;
814 buflen -= size;
815 HENT_SCOPY(hp->h_name, name, buf, buflen);
816 if (res->options & RES_USE_INET6)
817 map_v4v6_hostent(hp, &buf, buf + buflen);
818 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800819 return hp;
820}
821
Mattias Falkc63e5902011-08-23 14:34:14 +0200822// very similar in proxy-ness to android_getaddrinfo_proxy
823static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800824gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400825 size_t hbuflen, int *errorp, const struct android_net_context *netcontext)
Mattias Falkc63e5902011-08-23 14:34:14 +0200826{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800827 FILE* proxy = android_open_proxy();
828 if (proxy == NULL) {
829 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400830 res_setnetid(res, netcontext->dns_netid);
831 res_setmark(res, netcontext->dns_mark);
Yabin Cui58d33a52014-12-16 17:03:44 -0800832 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Mattias Falkc63e5902011-08-23 14:34:14 +0200833 }
834
Ben Schwartzdd878fe2017-05-22 10:19:25 -0400835 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Paul Jensen5240b562014-05-15 14:43:07 -0400836
Elliott Hughes9773fa32014-12-10 14:56:46 -0800837 // This is writing to system/netd/server/DnsProxyListener.cpp and changes
838 // here need to be matched there.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500839 if (fprintf(proxy, "gethostbyname %u %s %d",
840 netid,
Mattias Falkc63e5902011-08-23 14:34:14 +0200841 name == NULL ? "^" : name,
842 af) < 0) {
Elliott Hughes9773fa32014-12-10 14:56:46 -0800843 fclose(proxy);
844 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200845 }
846
847 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200848 fclose(proxy);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800849 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200850 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800851
Yabin Cui58d33a52014-12-16 17:03:44 -0800852 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800853 fclose(proxy);
Mattias Falkc63e5902011-08-23 14:34:14 +0200854 return result;
855}
856
Yabin Cui58d33a52014-12-16 17:03:44 -0800857/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
858int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
859 size_t buflen, struct hostent **result, int *h_errnop)
860{
Ben Schwartz50178052017-04-24 17:57:11 -0400861 *result = android_gethostbyaddrfornetcontext_proxy_internal(
862 addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -0800863 if (!*result && errno == ENOSPC) {
864 errno = ERANGE;
865 return ERANGE;
866 }
867 return (*result) ? 0 : -1;
868}
Mattias Falkc63e5902011-08-23 14:34:14 +0200869
Elliott Hughes9773fa32014-12-10 14:56:46 -0800870static struct hostent *
Ben Schwartz50178052017-04-24 17:57:11 -0400871android_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
872 char *buf, size_t buflen, int *he,
873 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800874{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800875 const u_char *uaddr = (const u_char *)addr;
876 socklen_t size;
Yabin Cui58d33a52014-12-16 17:03:44 -0800877 struct getnamaddr info;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800878 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800879 NS_FILES_CB(_hf_gethtbyaddr, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800880 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800881 NS_NIS_CB(_yp_gethtbyaddr, NULL)
882 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800883 };
884
Yabin Cui58d33a52014-12-16 17:03:44 -0800885 _DIAGASSERT(addr != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800886
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700887 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
888 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
889 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800890 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800891 return NULL;
892 }
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700893 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
894 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
895 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800896 /* Unmap. */
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700897 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
898 addr = uaddr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800899 af = AF_INET;
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700900 len = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800901 }
902 switch (af) {
903 case AF_INET:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700904 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800905 break;
906 case AF_INET6:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700907 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800908 break;
909 default:
910 errno = EAFNOSUPPORT;
Yabin Cui58d33a52014-12-16 17:03:44 -0800911 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800912 return NULL;
913 }
914 if (size != len) {
915 errno = EINVAL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800916 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800917 return NULL;
918 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800919 info.hp = hp;
920 info.buf = buf;
921 info.buflen = buflen;
922 info.he = he;
923 *he = NETDB_INTERNAL;
924 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
Ben Schwartz50178052017-04-24 17:57:11 -0400925 default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800926 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800927 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800928 return hp;
929}
930
Yabin Cui58d33a52014-12-16 17:03:44 -0800931static struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -0400932android_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
Yabin Cui58d33a52014-12-16 17:03:44 -0800933 struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
Ben Schwartz50178052017-04-24 17:57:11 -0400934 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -0800935{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800936 FILE* proxy = android_open_proxy();
937 if (proxy == NULL) {
938 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Ben Schwartz50178052017-04-24 17:57:11 -0400939 return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800940 }
941
942 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6
943 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
944 if (addrStr == NULL) {
945 fclose(proxy);
946 return NULL;
947 }
948
Ben Schwartz50178052017-04-24 17:57:11 -0400949 unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800950
951 if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
952 addrStr, len, af, netid) < 0) {
953 fclose(proxy);
954 return NULL;
955 }
956
957 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
958 fclose(proxy);
959 return NULL;
960 }
961
Yabin Cui58d33a52014-12-16 17:03:44 -0800962 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800963 fclose(proxy);
964 return result;
965}
966
Yabin Cui58d33a52014-12-16 17:03:44 -0800967struct hostent*
968netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200969{
Yabin Cui58d33a52014-12-16 17:03:44 -0800970 char *p, *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800971 char *cp, **q;
972 int af, len;
Yabin Cui58d33a52014-12-16 17:03:44 -0800973 size_t anum;
974 char **aliases;
975 size_t maxaliases;
976 struct in6_addr host_addr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800977
Yabin Cui58d33a52014-12-16 17:03:44 -0800978 if (hf == NULL) {
979 *he = NETDB_INTERNAL;
980 errno = EINVAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800981 return NULL;
982 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800983 p = NULL;
984 setup(aliases, maxaliases);
985
986 /* Allocate a new space to read file lines like upstream does.
987 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
988 * as the buffer may be used to store content for a previous hostent
989 * returned by non-reentrant functions like gethostbyname().
990 */
991 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
992 if ((p = malloc(line_buf_size)) == NULL) {
993 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800994 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800995 for (;;) {
996 if (!fgets(p, line_buf_size, hf)) {
997 free(p);
998 free(aliases);
999 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001000 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -08001001 }
1002 if (*p == '#') {
1003 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001004 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001005 if (!(cp = strpbrk(p, "#\n"))) {
1006 continue;
1007 }
1008 *cp = '\0';
1009 if (!(cp = strpbrk(p, " \t")))
1010 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001011 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001012 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
1013 af = AF_INET6;
1014 len = NS_IN6ADDRSZ;
1015 } else {
1016 if (inet_pton(AF_INET, p, &host_addr) <= 0)
1017 continue;
1018
1019 res_state res = __res_get_state();
1020 if (res == NULL)
1021 goto nospc;
1022 if (res->options & RES_USE_INET6) {
1023 map_v4v6_address(buf, buf);
1024 af = AF_INET6;
1025 len = NS_IN6ADDRSZ;
1026 } else {
1027 af = AF_INET;
1028 len = NS_INADDRSZ;
1029 }
1030 __res_put_state(res);
1031 }
1032
1033 /* if this is not something we're looking for, skip it. */
1034 if (hent->h_addrtype != 0 && hent->h_addrtype != af)
1035 continue;
1036 if (hent->h_length != 0 && hent->h_length != len)
1037 continue;
1038
1039 while (*cp == ' ' || *cp == '\t')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001040 cp++;
Yabin Cui58d33a52014-12-16 17:03:44 -08001041 if ((cp = strpbrk(name = cp, " \t")) != NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001042 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001043 q = aliases;
1044 while (cp && *cp) {
1045 if (*cp == ' ' || *cp == '\t') {
1046 cp++;
1047 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001048 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001049 addalias(q, cp, aliases, maxaliases);
1050 if ((cp = strpbrk(cp, " \t")) != NULL)
1051 *cp++ = '\0';
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001052 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001053 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001054 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001055 hent->h_length = len;
1056 hent->h_addrtype = af;
1057 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1058 anum = (size_t)(q - aliases);
1059 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
1060 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
1061 buflen);
1062 hent->h_addr_list[1] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001063
Yabin Cui58d33a52014-12-16 17:03:44 -08001064 HENT_SCOPY(hent->h_name, name, buf, buflen);
1065 for (size_t i = 0; i < anum; i++)
1066 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1067 hent->h_aliases[anum] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001068
Yabin Cui58d33a52014-12-16 17:03:44 -08001069 *he = NETDB_SUCCESS;
1070 free(p);
1071 free(aliases);
1072 return hent;
1073nospc:
1074 free(p);
1075 free(aliases);
1076 errno = ENOSPC;
1077 *he = NETDB_INTERNAL;
1078 return NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001079}
1080
1081static void
1082map_v4v6_address(const char *src, char *dst)
1083{
1084 u_char *p = (u_char *)dst;
Yabin Cui58d33a52014-12-16 17:03:44 -08001085 char tmp[NS_INADDRSZ];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001086 int i;
1087
Yabin Cui58d33a52014-12-16 17:03:44 -08001088 _DIAGASSERT(src != NULL);
1089 _DIAGASSERT(dst != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001090
1091 /* Stash a temporary copy so our caller can update in place. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001092 (void)memcpy(tmp, src, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001093 /* Mark this ipv6 addr as a mapped ipv4. */
1094 for (i = 0; i < 10; i++)
1095 *p++ = 0x00;
1096 *p++ = 0xff;
1097 *p++ = 0xff;
1098 /* Retrieve the saved copy and we're done. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001099 (void)memcpy(p, tmp, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001100}
1101
1102static void
1103map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1104{
1105 char **ap;
1106
Yabin Cui58d33a52014-12-16 17:03:44 -08001107 _DIAGASSERT(hp != NULL);
1108 _DIAGASSERT(bpp != NULL);
1109 _DIAGASSERT(ep != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001110
Yabin Cui58d33a52014-12-16 17:03:44 -08001111 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001112 return;
1113 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001114 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001115 for (ap = hp->h_addr_list; *ap; ap++) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001116 int i = (int)(sizeof(align) -
1117 (size_t)((u_long)*bpp % sizeof(align)));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001118
Yabin Cui58d33a52014-12-16 17:03:44 -08001119 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001120 /* Out of memory. Truncate address list here. XXX */
1121 *ap = NULL;
1122 return;
1123 }
1124 *bpp += i;
1125 map_v4v6_address(*ap, *bpp);
1126 *ap = *bpp;
Yabin Cui58d33a52014-12-16 17:03:44 -08001127 *bpp += NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001128 }
1129}
1130
1131static void
1132addrsort(char **ap, int num, res_state res)
1133{
1134 int i, j;
1135 char **p;
1136 short aval[MAXADDRS];
1137 int needsort = 0;
1138
Yabin Cui58d33a52014-12-16 17:03:44 -08001139 _DIAGASSERT(ap != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001140
1141 p = ap;
1142 for (i = 0; i < num; i++, p++) {
1143 for (j = 0 ; (unsigned)j < res->nsort; j++)
1144 if (res->sort_list[j].addr.s_addr ==
1145 (((struct in_addr *)(void *)(*p))->s_addr &
1146 res->sort_list[j].mask))
1147 break;
1148 aval[i] = j;
1149 if (needsort == 0 && i > 0 && j < aval[i-1])
1150 needsort = i;
1151 }
1152 if (!needsort)
1153 return;
1154
1155 while (needsort < num) {
1156 for (j = needsort - 1; j >= 0; j--) {
1157 if (aval[j] > aval[j+1]) {
1158 char *hp;
1159
1160 i = aval[j];
1161 aval[j] = aval[j+1];
1162 aval[j+1] = i;
1163
1164 hp = ap[j];
1165 ap[j] = ap[j+1];
1166 ap[j+1] = hp;
1167 } else
1168 break;
1169 }
1170 needsort++;
1171 }
1172}
1173
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001174/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001175static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001176_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1177{
1178 querybuf *buf;
1179 int n, type;
1180 struct hostent *hp;
1181 const char *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001182 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001183 struct getnamaddr *info = rv;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001184
Yabin Cui58d33a52014-12-16 17:03:44 -08001185 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001186
1187 name = va_arg(ap, char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001188 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1189 info->hp->h_addrtype = va_arg(ap, int);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001190
Yabin Cui58d33a52014-12-16 17:03:44 -08001191 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001192 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -08001193 info->hp->h_length = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001194 type = T_A;
1195 break;
1196 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -08001197 info->hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001198 type = T_AAAA;
1199 break;
1200 default:
1201 return NS_UNAVAIL;
1202 }
1203 buf = malloc(sizeof(*buf));
1204 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001205 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001206 return NS_NOTFOUND;
1207 }
1208 res = __res_get_state();
1209 if (res == NULL) {
1210 free(buf);
1211 return NS_NOTFOUND;
1212 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001213 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001214 if (n < 0) {
1215 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001216 debugprintf("res_nsearch failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001217 __res_put_state(res);
1218 return NS_NOTFOUND;
1219 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001220 hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
1221 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001222 free(buf);
1223 __res_put_state(res);
1224 if (hp == NULL)
Yabin Cui70692562014-12-19 10:10:04 -08001225 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001226 case HOST_NOT_FOUND:
1227 return NS_NOTFOUND;
1228 case TRY_AGAIN:
1229 return NS_TRYAGAIN;
1230 default:
1231 return NS_UNAVAIL;
1232 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001233 return NS_SUCCESS;
1234}
1235
1236/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001237static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001238_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1239{
1240 char qbuf[MAXDNAME + 1], *qp, *ep;
1241 int n;
1242 querybuf *buf;
1243 struct hostent *hp;
1244 const unsigned char *uaddr;
Yabin Cui58d33a52014-12-16 17:03:44 -08001245 int advance;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001246 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001247 char *bf;
1248 size_t blen;
1249 struct getnamaddr *info = rv;
Ben Schwartz50178052017-04-24 17:57:11 -04001250 const struct android_net_context *netcontext;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001251
Yabin Cui58d33a52014-12-16 17:03:44 -08001252 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001253
1254 uaddr = va_arg(ap, unsigned char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001255 info->hp->h_length = va_arg(ap, int);
1256 info->hp->h_addrtype = va_arg(ap, int);
Ben Schwartz50178052017-04-24 17:57:11 -04001257 netcontext = va_arg(ap, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001258
Yabin Cui58d33a52014-12-16 17:03:44 -08001259 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001260 case AF_INET:
1261 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1262 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1263 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1264 break;
1265
1266 case AF_INET6:
1267 qp = qbuf;
1268 ep = qbuf + sizeof(qbuf) - 1;
Yabin Cui58d33a52014-12-16 17:03:44 -08001269 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001270 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1271 uaddr[n] & 0xf,
1272 ((unsigned int)uaddr[n] >> 4) & 0xf);
1273 if (advance > 0 && qp + advance < ep)
1274 qp += advance;
1275 else {
Yabin Cui58d33a52014-12-16 17:03:44 -08001276 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001277 return NS_NOTFOUND;
1278 }
1279 }
1280 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001281 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001282 return NS_NOTFOUND;
1283 }
1284 break;
1285 default:
Yabin Cui58d33a52014-12-16 17:03:44 -08001286 return NS_UNAVAIL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001287 }
1288
1289 buf = malloc(sizeof(*buf));
1290 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001291 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001292 return NS_NOTFOUND;
1293 }
1294 res = __res_get_state();
1295 if (res == NULL) {
1296 free(buf);
1297 return NS_NOTFOUND;
1298 }
Ben Schwartz50178052017-04-24 17:57:11 -04001299 res_setnetid(res, netcontext->dns_netid);
1300 res_setmark(res, netcontext->dns_mark);
Yabin Cui58d33a52014-12-16 17:03:44 -08001301 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 -08001302 if (n < 0) {
1303 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001304 debugprintf("res_nquery failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001305 __res_put_state(res);
1306 return NS_NOTFOUND;
1307 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001308 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1309 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001310 free(buf);
1311 if (hp == NULL) {
1312 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001313 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001314 case HOST_NOT_FOUND:
1315 return NS_NOTFOUND;
1316 case TRY_AGAIN:
1317 return NS_TRYAGAIN;
1318 default:
1319 return NS_UNAVAIL;
1320 }
1321 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001322
1323 bf = (void *)(hp->h_addr_list + 2);
1324 blen = (size_t)(bf - info->buf);
1325 if (blen + info->hp->h_length > info->buflen)
1326 goto nospc;
1327 hp->h_addr_list[0] = bf;
1328 hp->h_addr_list[1] = NULL;
1329 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1330 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1331 if (blen + NS_IN6ADDRSZ > info->buflen)
1332 goto nospc;
1333 map_v4v6_address(bf, bf);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001334 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001335 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001336 }
1337
1338 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001339 *info->he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001340 return NS_SUCCESS;
Yabin Cui58d33a52014-12-16 17:03:44 -08001341nospc:
Yabin Cui70692562014-12-19 10:10:04 -08001342 errno = ENOSPC;
Yabin Cui58d33a52014-12-16 17:03:44 -08001343 *info->he = NETDB_INTERNAL;
1344 return NS_UNAVAIL;
1345}
1346
1347#ifdef YP
1348/*ARGSUSED*/
1349static struct hostent *
1350_yp_hostent(char *line, int af, struct getnamaddr *info)
1351{
1352 struct in6_addr host_addrs[MAXADDRS];
1353 char **aliases;
1354 size_t maxaliases;
1355 char *p = line;
1356 char *cp, **q, *ptr;
1357 size_t len, anum, i;
1358 int addrok;
1359 int more;
1360 size_t naddrs;
1361 struct hostent *hp = info->hp;
1362
1363 _DIAGASSERT(line != NULL);
1364
1365 hp->h_name = NULL;
1366 hp->h_addrtype = af;
1367 switch (af) {
1368 case AF_INET:
1369 hp->h_length = NS_INADDRSZ;
1370 break;
1371 case AF_INET6:
1372 hp->h_length = NS_IN6ADDRSZ;
1373 break;
1374 default:
1375 return NULL;
1376 }
1377 setup(aliases, maxaliases);
1378 naddrs = 0;
1379 q = aliases;
1380
1381nextline:
1382 /* check for host_addrs overflow */
1383 if (naddrs >= __arraycount(host_addrs))
1384 goto done;
1385
1386 more = 0;
1387 cp = strpbrk(p, " \t");
1388 if (cp == NULL)
1389 goto done;
1390 *cp++ = '\0';
1391
1392 /* p has should have an address */
1393 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1394 if (addrok != 1) {
1395 /* skip to the next line */
1396 while (cp && *cp) {
1397 if (*cp == '\n') {
1398 cp++;
1399 goto nextline;
1400 }
1401 cp++;
1402 }
1403 goto done;
1404 }
1405 naddrs++;
1406
1407 while (*cp == ' ' || *cp == '\t')
1408 cp++;
1409 p = cp;
1410 cp = strpbrk(p, " \t\n");
1411 if (cp != NULL) {
1412 if (*cp == '\n')
1413 more = 1;
1414 *cp++ = '\0';
1415 }
1416 if (!hp->h_name)
1417 hp->h_name = p;
1418 else if (strcmp(hp->h_name, p) == 0)
1419 ;
1420 else
1421 addalias(q, p, aliases, maxaliases);
1422 p = cp;
1423 if (more)
1424 goto nextline;
1425
1426 while (cp && *cp) {
1427 if (*cp == ' ' || *cp == '\t') {
1428 cp++;
1429 continue;
1430 }
1431 if (*cp == '\n') {
1432 cp++;
1433 goto nextline;
1434 }
1435 addalias(q, cp, aliases, maxaliases);
1436 cp = strpbrk(cp, " \t");
1437 if (cp != NULL)
1438 *cp++ = '\0';
1439 }
1440
1441done:
1442 if (hp->h_name == NULL) {
1443 free(aliases);
1444 return NULL;
1445 }
1446
1447 ptr = info->buf;
1448 len = info->buflen;
1449
1450 anum = (size_t)(q - aliases);
1451 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1452 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1453
1454 for (i = 0; i < naddrs; i++)
1455 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1456 ptr, len);
1457 hp->h_addr_list[naddrs] = NULL;
1458
1459 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1460
1461 for (i = 0; i < anum; i++)
1462 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1463 hp->h_aliases[anum] = NULL;
1464 free(aliases);
1465
1466 return hp;
1467nospc:
1468 free(aliases);
1469 *info->he = NETDB_INTERNAL;
1470 errno = ENOSPC;
1471 return NULL;
1472}
1473
1474/*ARGSUSED*/
1475int
1476_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1477{
1478 struct hostent *hp = NULL;
1479 char *ypcurrent;
1480 int ypcurrentlen, r;
1481 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1482 const unsigned char *uaddr;
1483 int af;
1484 const char *map;
1485 struct getnamaddr *info = rv;
1486
1487 _DIAGASSERT(rv != NULL);
1488
1489 uaddr = va_arg(ap, unsigned char *);
1490 /* NOSTRICT skip len */(void)va_arg(ap, int);
1491 af = va_arg(ap, int);
1492
1493 if (!__ypdomain) {
1494 if (_yp_check(&__ypdomain) == 0)
1495 return NS_UNAVAIL;
1496 }
1497 /*
1498 * XXX unfortunately, we cannot support IPv6 extended scoped address
1499 * notation here. gethostbyaddr() is not scope-aware. too bad.
1500 */
1501 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1502 return NS_UNAVAIL;
1503 switch (af) {
1504 case AF_INET:
1505 map = "hosts.byaddr";
1506 break;
1507 default:
1508 map = "ipnodes.byaddr";
1509 break;
1510 }
1511 ypcurrent = NULL;
1512 r = yp_match(__ypdomain, map, name,
1513 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1514 if (r == 0)
1515 hp = _yp_hostent(ypcurrent, af, info);
1516 else
1517 hp = NULL;
1518 free(ypcurrent);
1519 if (hp == NULL) {
1520 *info->he = HOST_NOT_FOUND;
1521 return NS_NOTFOUND;
1522 }
1523 return NS_SUCCESS;
1524}
1525
1526/*ARGSUSED*/
1527int
1528_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1529{
1530 struct hostent *hp;
1531 char *ypcurrent;
1532 int ypcurrentlen, r;
1533 const char *name;
1534 int af;
1535 const char *map;
1536 struct getnamaddr *info = rv;
1537
1538 _DIAGASSERT(rv != NULL);
1539
1540 name = va_arg(ap, char *);
1541 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1542 af = va_arg(ap, int);
1543
1544 if (!__ypdomain) {
1545 if (_yp_check(&__ypdomain) == 0)
1546 return NS_UNAVAIL;
1547 }
1548 switch (af) {
1549 case AF_INET:
1550 map = "hosts.byname";
1551 break;
1552 default:
1553 map = "ipnodes.byname";
1554 break;
1555 }
1556 ypcurrent = NULL;
1557 r = yp_match(__ypdomain, map, name,
1558 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1559 if (r == 0)
1560 hp = _yp_hostent(ypcurrent, af, info);
1561 else
1562 hp = NULL;
1563 free(ypcurrent);
1564 if (hp == NULL) {
1565 *info->he = HOST_NOT_FOUND;
1566 return NS_NOTFOUND;
1567 }
1568 return NS_SUCCESS;
1569}
1570#endif
1571
1572/*
1573 * Non-reentrant versions.
1574 */
1575
1576struct hostent *
1577gethostbyname(const char *name)
1578{
1579 struct hostent *result = NULL;
1580 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1581
1582 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1583 return result;
1584}
1585
1586struct hostent *
1587gethostbyname2(const char *name, int af)
1588{
1589 struct hostent *result = NULL;
1590 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1591
1592 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1593 return result;
1594}
1595
Ben Schwartz50178052017-04-24 17:57:11 -04001596// android_gethostby*fornet can be called in two different contexts.
1597// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1598// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1599// The netcontext is constructed before checking which context we are in.
1600// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1601// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1602static struct android_net_context make_context(unsigned netid, unsigned mark) {
1603 struct android_net_context netcontext = NETCONTEXT_UNSET;
1604 netcontext.app_netid = netid;
1605 netcontext.app_mark = mark;
1606 netcontext.dns_netid = netid;
1607 netcontext.dns_mark = mark;
1608 return netcontext;
1609}
1610
Yabin Cui58d33a52014-12-16 17:03:44 -08001611struct hostent *
1612android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
1613{
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001614 const struct android_net_context netcontext = make_context(netid, mark);
1615 return android_gethostbynamefornetcontext(name, af, &netcontext);
1616}
1617
1618struct hostent *
1619android_gethostbynamefornetcontext(const char *name, int af,
1620 const struct android_net_context *netcontext)
1621{
Yabin Cui58d33a52014-12-16 17:03:44 -08001622 struct hostent *hp;
1623 res_state res = __res_get_state();
1624 if (res == NULL)
1625 return NULL;
1626 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1627 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
Ben Schwartzdd878fe2017-05-22 10:19:25 -04001628 &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001629 __res_put_state(res);
1630 return hp;
1631}
1632
1633struct hostent *
1634gethostbyaddr(const void *addr, socklen_t len, int af)
1635{
Ben Schwartz50178052017-04-24 17:57:11 -04001636 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Yabin Cui58d33a52014-12-16 17:03:44 -08001637}
1638
1639struct hostent *
1640android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
1641{
Ben Schwartz50178052017-04-24 17:57:11 -04001642 const struct android_net_context netcontext = make_context(netid, mark);
1643 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
1644}
1645
1646struct hostent *
1647android_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
1648 const struct android_net_context *netcontext)
1649{
1650 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001651}
1652
1653__LIBC_HIDDEN__ struct hostent*
Ben Schwartz50178052017-04-24 17:57:11 -04001654android_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
1655 const struct android_net_context *netcontext)
Yabin Cui58d33a52014-12-16 17:03:44 -08001656{
1657 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
Ben Schwartz50178052017-04-24 17:57:11 -04001658 return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
1659 sizeof(rs->hostbuf), &h_errno, netcontext);
Yabin Cui58d33a52014-12-16 17:03:44 -08001660}
1661
1662struct hostent *
1663gethostent(void)
1664{
1665 res_static rs = __res_get_static();
1666 if (!rs->hostf) {
1667 sethostent_r(&rs->hostf);
1668 if (!rs->hostf) {
1669 h_errno = NETDB_INTERNAL;
1670 return NULL;
1671 }
1672 }
1673 memset(&rs->host, 0, sizeof(rs->host));
1674 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 -08001675}