blob: 338f2af474c6b110ce889b45cd3c11ff234fe4a3 [file] [log] [blame]
Bernie Innocenti55864192018-08-30 04:05:20 +09001/* $NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1988, 1993
5 * -
6 * Copyright (c) 1985, 1988, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 * -
33 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
34 *
35 * Permission to use, copy, modify, and distribute this software for any
36 * purpose with or without fee is hereby granted, provided that the above
37 * copyright notice and this permission notice appear in all copies, and that
38 * the name of Digital Equipment Corporation not be used in advertising or
39 * publicity pertaining to distribution of the document or software without
40 * specific, written prior permission.
41 *
42 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 * SOFTWARE.
50 * -
51 * --Copyright--
52 */
53
Bernie Innocenti55864192018-08-30 04:05:20 +090054#include <arpa/inet.h>
55#include <arpa/nameser.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090056#include <assert.h>
57#include <ctype.h>
58#include <errno.h>
59#include <netdb.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090060#include <netinet/in.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090061#include <stdarg.h>
62#include <stdbool.h>
63#include <stdio.h>
64#include <strings.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090065#include <sys/param.h>
66#include <sys/socket.h>
Bernie Innocentif89b3512018-08-30 07:34:37 +090067#include <sys/types.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090068#include <sys/un.h>
Bernie Innocenti55864192018-08-30 04:05:20 +090069#include <syslog.h>
70#include <unistd.h>
Bernie Innocentif89b3512018-08-30 07:34:37 +090071
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090072#include "resolv_cache.h"
73#include "resolv_netid.h"
74#include "resolv_private.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090075
Bernie Innocentif89b3512018-08-30 07:34:37 +090076// NetBSD uses _DIAGASSERT to null-check arguments and the like,
77// but it's clear from the number of mistakes in their assertions
78// that they don't actually test or ship with this.
79#define _DIAGASSERT(e) /* nothing */
80
Bernie Innocenti55864192018-08-30 04:05:20 +090081#define ALIGNBYTES (sizeof(uintptr_t) - 1)
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090082#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) & ~ALIGNBYTES)
Bernie Innocenti55864192018-08-30 04:05:20 +090083
84#ifndef LOG_AUTH
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090085#define LOG_AUTH 0
Bernie Innocenti55864192018-08-30 04:05:20 +090086#endif
87
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090088#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
Bernie Innocenti55864192018-08-30 04:05:20 +090089
Bernie Innocenti55864192018-08-30 04:05:20 +090090#include <stdlib.h>
91#include <string.h>
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090092#include "nsswitch.h"
Bernie Innocenti55864192018-08-30 04:05:20 +090093
94#include "hostent.h"
95
Bernie Innocentif12d5bb2018-08-31 14:09:46 +090096#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || (ok)(nm) != 0)
Bernie Innocenti55864192018-08-30 04:05:20 +090097#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
98#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
99
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900100#define addalias(d, s, arr, siz) \
101 do { \
102 if (d >= &arr[siz]) { \
103 char** xptr = (char**) realloc(arr, (siz + 10) * sizeof(*arr)); \
104 if (xptr == NULL) goto nospc; \
105 d = xptr + (d - arr); \
106 arr = xptr; \
107 siz += 10; \
108 } \
109 *d++ = s; \
110 } while (0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900111
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900112static const char AskedForGot[] = "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
Bernie Innocenti55864192018-08-30 04:05:20 +0900113
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900114static const struct android_net_context NETCONTEXT_UNSET = {.app_mark = MARK_UNSET,
115 .app_netid = NETID_UNSET,
116 .dns_mark = MARK_UNSET,
117 .dns_netid = NETID_UNSET,
118 .uid = NET_CONTEXT_INVALID_UID};
Bernie Innocenti55864192018-08-30 04:05:20 +0900119
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900120#define MAXPACKET (8 * 1024)
Bernie Innocenti55864192018-08-30 04:05:20 +0900121
122typedef union {
123 HEADER hdr;
124 u_char buf[MAXPACKET];
125} querybuf;
126
127typedef union {
128 int32_t al;
129 char ac;
130} align;
131
132#ifdef DEBUG
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900133static void debugprintf(const char*, res_state, ...) __attribute__((__format__(__printf__, 1, 3)));
Bernie Innocenti55864192018-08-30 04:05:20 +0900134#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900135static struct hostent* getanswer(const querybuf*, int, const char*, int, res_state, struct hostent*,
136 char*, size_t, int*);
137static void map_v4v6_address(const char*, char*);
138static void map_v4v6_hostent(struct hostent*, char**, char*);
139static void addrsort(char**, int, res_state);
Bernie Innocenti55864192018-08-30 04:05:20 +0900140
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900141struct hostent* ht_gethostbyname(char*);
142struct hostent* ht_gethostbyaddr(const char*, int, int);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900143static int _dns_gethtbyaddr(void*, void*, va_list);
Bernie Innocenti9bf0e1d2018-09-12 17:59:17 +0900144static int _dns_gethtbyname(const char* name, int addr_type, getnamaddr* info);
Bernie Innocenti55864192018-08-30 04:05:20 +0900145
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900146static struct hostent* gethostbyname_internal(const char*, int, res_state, struct hostent*, char*,
147 size_t, int*, const struct android_net_context*);
148static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
149 const void*, socklen_t, int, struct hostent*, char*, size_t, int*,
150 const struct android_net_context*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900151
152static const ns_src default_dns_files[] = {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900153 {NSSRC_FILES, NS_SUCCESS},
154 {NSSRC_DNS, NS_SUCCESS},
155 {0, 0}
156};
Bernie Innocenti55864192018-08-30 04:05:20 +0900157
158static int h_errno_to_result(int* herrno_p) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900159 // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
160 if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
161 errno = ERANGE;
162 return errno;
163 }
164 // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
165 return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900166}
167
168#ifdef DEBUG
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900169static void debugprintf(const char* msg, res_state res, ...) {
170 _DIAGASSERT(msg != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900171
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900172 if (res->options & RES_DEBUG) {
173 int save = errno;
174 va_list ap;
Bernie Innocenti55864192018-08-30 04:05:20 +0900175
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900176 va_start(ap, res);
177 vprintf(msg, ap);
178 va_end(ap);
Bernie Innocenti55864192018-08-30 04:05:20 +0900179
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900180 errno = save;
181 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900182}
183#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900184#define debugprintf(msg, res, num) /*nada*/
Bernie Innocenti55864192018-08-30 04:05:20 +0900185#endif
186
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900187#define BOUNDED_INCR(x) \
188 do { \
189 BOUNDS_CHECK(cp, x); \
190 cp += (x); \
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900191 } while (0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900192
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900193#define BOUNDS_CHECK(ptr, count) \
194 do { \
195 if (eom - (ptr) < (count)) goto no_recovery; \
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900196 } while (0)
Bernie Innocenti55864192018-08-30 04:05:20 +0900197
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900198static struct hostent* getanswer(const querybuf* answer, int anslen, const char* qname, int qtype,
199 res_state res, struct hostent* hent, char* buf, size_t buflen,
200 int* he) {
201 const HEADER* hp;
202 const u_char* cp;
203 int n;
204 size_t qlen;
205 const u_char *eom, *erdata;
206 char *bp, **ap, **hap, *ep;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900207 int ancount, qdcount;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900208 int haveanswer, had_error;
209 int toobig = 0;
210 char tbuf[MAXDNAME];
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900211 char* addr_ptrs[MAXADDRS];
212 const char* tname;
213 int (*name_ok)(const char*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900214
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900215 _DIAGASSERT(answer != NULL);
216 _DIAGASSERT(qname != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900217
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900218 tname = qname;
219 hent->h_name = NULL;
220 eom = answer->buf + anslen;
221 switch (qtype) {
222 case T_A:
223 case T_AAAA:
224 name_ok = res_hnok;
225 break;
226 case T_PTR:
227 name_ok = res_dnok;
228 break;
229 default:
230 *he = NO_RECOVERY;
231 return NULL; /* XXX should be abort(); */
232 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900233
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900234 size_t maxaliases = 10;
235 char** aliases = (char**) malloc(maxaliases * sizeof(char*));
236 if (!aliases) goto nospc;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900237 /*
238 * find first satisfactory answer
239 */
240 hp = &answer->hdr;
241 ancount = ntohs(hp->ancount);
242 qdcount = ntohs(hp->qdcount);
243 bp = buf;
244 ep = buf + buflen;
245 cp = answer->buf;
246 BOUNDED_INCR(HFIXEDSZ);
247 if (qdcount != 1) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900248
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900249 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
250 if ((n < 0) || !maybe_ok(res, bp, name_ok)) goto no_recovery;
Bernie Innocenti55864192018-08-30 04:05:20 +0900251
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900252 BOUNDED_INCR(n + QFIXEDSZ);
253 if (qtype == T_A || qtype == T_AAAA) {
254 /* res_send() has already verified that the query name is the
255 * same as the one we sent; this just gets the expanded name
256 * (i.e., with the succeeding search-domain tacked on).
257 */
258 n = (int) strlen(bp) + 1; /* for the \0 */
259 if (n >= MAXHOSTNAMELEN) goto no_recovery;
260 hent->h_name = bp;
261 bp += n;
262 /* The qname can be abbreviated, but h_name is now absolute. */
263 qname = hent->h_name;
264 }
265 hent->h_aliases = ap = aliases;
266 hent->h_addr_list = hap = addr_ptrs;
267 *ap = NULL;
268 *hap = NULL;
269 haveanswer = 0;
270 had_error = 0;
271 while (ancount-- > 0 && cp < eom && !had_error) {
272 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
273 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
274 had_error++;
275 continue;
276 }
277 cp += n; /* name */
278 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900279 int type = _getshort(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900280 cp += INT16SZ; /* type */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900281 int cl = _getshort(cp);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900282 cp += INT16SZ + INT32SZ; /* class, TTL */
283 n = _getshort(cp);
284 cp += INT16SZ; /* len */
285 BOUNDS_CHECK(cp, n);
286 erdata = cp + n;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900287 if (cl != C_IN) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900288 /* XXX - debug? syslog? */
289 cp += n;
290 continue; /* XXX - had_error++ ? */
291 }
292 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
293 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
294 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
295 had_error++;
296 continue;
297 }
298 cp += n;
299 if (cp != erdata) goto no_recovery;
300 /* Store alias. */
301 addalias(ap, bp, aliases, maxaliases);
302 n = (int) strlen(bp) + 1; /* for the \0 */
303 if (n >= MAXHOSTNAMELEN) {
304 had_error++;
305 continue;
306 }
307 bp += n;
308 /* Get canonical name. */
309 n = (int) strlen(tbuf) + 1; /* for the \0 */
310 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
311 had_error++;
312 continue;
313 }
314 strlcpy(bp, tbuf, (size_t)(ep - bp));
315 hent->h_name = bp;
316 bp += n;
317 continue;
318 }
319 if (qtype == T_PTR && type == T_CNAME) {
320 n = dn_expand(answer->buf, eom, cp, tbuf, (int) sizeof tbuf);
321 if (n < 0 || !maybe_dnok(res, tbuf)) {
322 had_error++;
323 continue;
324 }
325 cp += n;
326 if (cp != erdata) goto no_recovery;
327 /* Get canonical name. */
328 n = (int) strlen(tbuf) + 1; /* for the \0 */
329 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
330 had_error++;
331 continue;
332 }
333 strlcpy(bp, tbuf, (size_t)(ep - bp));
334 tname = bp;
335 bp += n;
336 continue;
337 }
338 if (type != qtype) {
339 if (type != T_KEY && type != T_SIG)
340 syslog(LOG_NOTICE | LOG_AUTH,
341 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", qname,
342 p_class(C_IN), p_type(qtype), p_type(type));
343 cp += n;
344 continue; /* XXX - had_error++ ? */
345 }
346 switch (type) {
347 case T_PTR:
348 if (strcasecmp(tname, bp) != 0) {
349 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
350 cp += n;
351 continue; /* XXX - had_error++ ? */
352 }
353 n = dn_expand(answer->buf, eom, cp, bp, (int) (ep - bp));
354 if ((n < 0) || !maybe_hnok(res, bp)) {
355 had_error++;
356 break;
357 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900358#if MULTI_PTRS_ARE_ALIASES
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900359 cp += n;
360 if (cp != erdata) goto no_recovery;
361 if (!haveanswer)
362 hent->h_name = bp;
363 else
364 addalias(ap, bp, aliases, maxaliases);
365 if (n != -1) {
366 n = (int) strlen(bp) + 1; /* for the \0 */
367 if (n >= MAXHOSTNAMELEN) {
368 had_error++;
369 break;
370 }
371 bp += n;
372 }
373 break;
Bernie Innocenti55864192018-08-30 04:05:20 +0900374#else
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900375 hent->h_name = bp;
376 if (res->options & RES_USE_INET6) {
377 n = strlen(bp) + 1; /* for the \0 */
378 if (n >= MAXHOSTNAMELEN) {
379 had_error++;
380 break;
381 }
382 bp += n;
383 map_v4v6_hostent(hent, &bp, ep);
384 }
385 goto success;
Bernie Innocenti55864192018-08-30 04:05:20 +0900386#endif
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900387 case T_A:
388 case T_AAAA:
389 if (strcasecmp(hent->h_name, bp) != 0) {
390 syslog(LOG_NOTICE | LOG_AUTH, AskedForGot, hent->h_name, bp);
391 cp += n;
392 continue; /* XXX - had_error++ ? */
393 }
394 if (n != hent->h_length) {
395 cp += n;
396 continue;
397 }
398 if (type == T_AAAA) {
399 struct in6_addr in6;
400 memcpy(&in6, cp, NS_IN6ADDRSZ);
401 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
402 cp += n;
403 continue;
404 }
405 }
406 if (!haveanswer) {
407 int nn;
Bernie Innocenti55864192018-08-30 04:05:20 +0900408
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900409 hent->h_name = bp;
410 nn = (int) strlen(bp) + 1; /* for the \0 */
411 bp += nn;
412 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900413
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900414 bp += sizeof(align) - (size_t)((u_long) bp % sizeof(align));
Bernie Innocenti55864192018-08-30 04:05:20 +0900415
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900416 if (bp + n >= ep) {
417 debugprintf("size (%d) too big\n", res, n);
418 had_error++;
419 continue;
420 }
421 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
422 if (!toobig++) {
423 debugprintf("Too many addresses (%d)\n", res, MAXADDRS);
424 }
425 cp += n;
426 continue;
427 }
428 (void) memcpy(*hap++ = bp, cp, (size_t) n);
429 bp += n;
430 cp += n;
431 if (cp != erdata) goto no_recovery;
432 break;
433 default:
434 abort();
435 }
436 if (!had_error) haveanswer++;
437 }
438 if (haveanswer) {
439 *ap = NULL;
440 *hap = NULL;
441 /*
442 * Note: we sort even if host can take only one address
443 * in its return structures - should give it the "best"
444 * address in that case, not some random one
445 */
446 if (res->nsort && haveanswer > 1 && qtype == T_A) addrsort(addr_ptrs, haveanswer, res);
447 if (!hent->h_name) {
448 n = (int) strlen(qname) + 1; /* for the \0 */
449 if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery;
450 strlcpy(bp, qname, (size_t)(ep - bp));
451 hent->h_name = bp;
452 bp += n;
453 }
454 if (res->options & RES_USE_INET6) map_v4v6_hostent(hent, &bp, ep);
455 goto success;
456 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900457no_recovery:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900458 free(aliases);
459 *he = NO_RECOVERY;
460 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900461success:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900462 bp = (char*) ALIGN(bp);
463 n = (int) (ap - aliases);
464 qlen = (n + 1) * sizeof(*hent->h_aliases);
465 if ((size_t)(ep - bp) < qlen) goto nospc;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900466 hent->h_aliases = (char**) bp;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900467 memcpy(bp, aliases, qlen);
468 free(aliases);
469 aliases = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900470
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900471 bp += qlen;
472 n = (int) (hap - addr_ptrs);
473 qlen = (n + 1) * sizeof(*hent->h_addr_list);
474 if ((size_t)(ep - bp) < qlen) goto nospc;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900475 hent->h_addr_list = (char**) bp;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900476 memcpy(bp, addr_ptrs, qlen);
477 *he = NETDB_SUCCESS;
478 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900479nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900480 free(aliases);
481 errno = ENOSPC;
482 *he = NETDB_INTERNAL;
483 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900484}
485
486/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900487int gethostbyname_r(const char* name, struct hostent* hp, char* buf, size_t buflen,
488 struct hostent** result, int* errorp) {
489 res_state res = __res_get_state();
490 if (res == NULL) {
491 *result = NULL;
492 *errorp = NETDB_INTERNAL;
493 return -1;
494 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900495
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900496 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900497
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900498 if (res->options & RES_USE_INET6) {
499 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
500 &NETCONTEXT_UNSET);
501 if (*result) {
502 __res_put_state(res);
503 return 0;
504 }
505 }
506 *result =
507 gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
508 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900509}
510
511/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900512int gethostbyname2_r(const char* name, int af, struct hostent* hp, char* buf, size_t buflen,
513 struct hostent** result, int* errorp) {
514 res_state res = __res_get_state();
515 if (res == NULL) {
516 *result = NULL;
517 *errorp = NETDB_INTERNAL;
518 return -1;
519 }
520 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, &NETCONTEXT_UNSET);
521 return h_errno_to_result(errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900522}
523
524__LIBC_HIDDEN__ FILE* android_open_proxy() {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900525 const char* cache_mode = getenv("ANDROID_DNS_MODE");
526 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
527 if (!use_proxy) {
528 return NULL;
529 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900530
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900531 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
532 if (s == -1) {
533 return NULL;
534 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900535
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900536 const int one = 1;
537 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
Bernie Innocenti55864192018-08-30 04:05:20 +0900538
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900539 struct sockaddr_un proxy_addr;
540 memset(&proxy_addr, 0, sizeof(proxy_addr));
541 proxy_addr.sun_family = AF_UNIX;
542 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Bernie Innocenti55864192018-08-30 04:05:20 +0900543
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900544 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) !=
545 0) {
546 close(s);
547 return NULL;
548 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900549
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900550 return fdopen(s, "r+");
Bernie Innocenti55864192018-08-30 04:05:20 +0900551}
552
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900553static struct hostent* gethostbyname_internal_real(const char* name, int af, res_state res,
554 struct hostent* hp, char* buf, size_t buflen,
555 int* he) {
556 const char* cp;
557 struct getnamaddr info;
558 char hbuf[MAXHOSTNAMELEN];
559 size_t size;
Bernie Innocenti55864192018-08-30 04:05:20 +0900560
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900561 _DIAGASSERT(name != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900562
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900563 switch (af) {
564 case AF_INET:
565 size = NS_INADDRSZ;
566 break;
567 case AF_INET6:
568 size = NS_IN6ADDRSZ;
569 break;
570 default:
571 *he = NETDB_INTERNAL;
572 errno = EAFNOSUPPORT;
573 return NULL;
574 }
575 if (buflen < size) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900576
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900577 hp->h_addrtype = af;
578 hp->h_length = (int) size;
Bernie Innocenti55864192018-08-30 04:05:20 +0900579
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900580 /*
581 * if there aren't any dots, it could be a user-level alias.
582 * this is also done in res_nquery() since we are not the only
583 * function that looks up host names.
584 */
585 if (!strchr(name, '.') && (cp = res_hostalias(res, name, hbuf, sizeof(hbuf)))) name = cp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900586
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900587 /*
588 * disallow names consisting only of digits/dots, unless
589 * they end in a dot.
590 */
591 if (isdigit((u_char) name[0]))
592 for (cp = name;; ++cp) {
593 if (!*cp) {
594 if (*--cp == '.') break;
595 /*
596 * All-numeric, no dot at the end.
597 * Fake up a hostent as if we'd actually
598 * done a lookup.
599 */
600 goto fake;
601 }
602 if (!isdigit((u_char) *cp) && *cp != '.') break;
603 }
604 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) || name[0] == ':')
605 for (cp = name;; ++cp) {
606 if (!*cp) {
607 if (*--cp == '.') break;
608 /*
609 * All-IPv6-legal, no dot at the end.
610 * Fake up a hostent as if we'd actually
611 * done a lookup.
612 */
613 goto fake;
614 }
615 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.') break;
616 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900617
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900618 *he = NETDB_INTERNAL;
619 info.hp = hp;
620 info.buf = buf;
621 info.buflen = buflen;
622 info.he = he;
Bernie Innocenti9bf0e1d2018-09-12 17:59:17 +0900623 if (!_hf_gethtbyname2(name, af, &info)) {
624 if (_dns_gethtbyname(name, af, &info) != NS_SUCCESS) {
625 return NULL;
626 }
627 }
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900628 *he = NETDB_SUCCESS;
629 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900630nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900631 *he = NETDB_INTERNAL;
632 errno = ENOSPC;
633 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900634fake:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900635 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
636 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
Bernie Innocenti55864192018-08-30 04:05:20 +0900637
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900638 hp->h_aliases[0] = NULL;
639 if (size > buflen) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900640
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900641 if (inet_pton(af, name, buf) <= 0) {
642 *he = HOST_NOT_FOUND;
643 return NULL;
644 }
645 hp->h_addr_list[0] = buf;
646 hp->h_addr_list[1] = NULL;
647 buf += size;
648 buflen -= size;
649 HENT_SCOPY(hp->h_name, name, buf, buflen);
650 if (res->options & RES_USE_INET6) map_v4v6_hostent(hp, &buf, buf + buflen);
651 *he = NETDB_SUCCESS;
652 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900653}
654
655// very similar in proxy-ness to android_getaddrinfo_proxy
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900656static struct hostent* gethostbyname_internal(const char* name, int af, res_state res,
657 struct hostent* hp, char* hbuf, size_t hbuflen,
658 int* errorp,
659 const struct android_net_context* netcontext) {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900660 res_setnetcontext(res, netcontext);
661 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Bernie Innocenti55864192018-08-30 04:05:20 +0900662}
663
664/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900665int gethostbyaddr_r(const void* addr, socklen_t len, int af, struct hostent* hp, char* buf,
666 size_t buflen, struct hostent** result, int* h_errnop) {
667 *result = android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, hp, buf, buflen,
668 h_errnop, &NETCONTEXT_UNSET);
669 return h_errno_to_result(h_errnop);
Bernie Innocenti55864192018-08-30 04:05:20 +0900670}
671
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900672static struct hostent* android_gethostbyaddrfornetcontext_real(
673 const void* addr, socklen_t len, int af, struct hostent* hp, char* buf, size_t buflen,
674 int* he, const struct android_net_context* netcontext) {
675 const u_char* uaddr = (const u_char*) addr;
676 socklen_t size;
677 struct getnamaddr info;
Bernie Innocentif89b3512018-08-30 07:34:37 +0900678 static const ns_dtab dtab[] = {
679 {NSSRC_FILES, _hf_gethtbyaddr, NULL},
680 {NSSRC_DNS, _dns_gethtbyaddr, NULL},
681 {0, 0, 0}
682 };
Bernie Innocenti55864192018-08-30 04:05:20 +0900683
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900684 _DIAGASSERT(addr != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900685
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900686 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
687 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr*) addr) ||
688 IN6_IS_ADDR_SITELOCAL((const struct in6_addr*) addr))) {
689 *he = HOST_NOT_FOUND;
690 return NULL;
691 }
692 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
693 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr*) addr) ||
694 IN6_IS_ADDR_V4COMPAT((const struct in6_addr*) addr))) {
695 /* Unmap. */
696 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
697 addr = uaddr;
698 af = AF_INET;
699 len = NS_INADDRSZ;
700 }
701 switch (af) {
702 case AF_INET:
703 size = NS_INADDRSZ;
704 break;
705 case AF_INET6:
706 size = NS_IN6ADDRSZ;
707 break;
708 default:
709 errno = EAFNOSUPPORT;
710 *he = NETDB_INTERNAL;
711 return NULL;
712 }
713 if (size != len) {
714 errno = EINVAL;
715 *he = NETDB_INTERNAL;
716 return NULL;
717 }
718 info.hp = hp;
719 info.buf = buf;
720 info.buflen = buflen;
721 info.he = he;
722 *he = NETDB_INTERNAL;
723 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr", default_dns_files, uaddr, len, af,
724 netcontext) != NS_SUCCESS)
725 return NULL;
726 *he = NETDB_SUCCESS;
727 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900728}
729
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900730static struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(
731 const void* addr, socklen_t len, int af, struct hostent* hp, char* hbuf, size_t hbuflen,
732 int* he, const struct android_net_context* netcontext) {
Bernie Innocentif89b3512018-08-30 07:34:37 +0900733 return android_gethostbyaddrfornetcontext_real(addr, len, af, hp, hbuf, hbuflen, he,
734 netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +0900735}
736
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900737struct hostent* netbsd_gethostent_r(FILE* hf, struct hostent* hent, char* buf, size_t buflen,
738 int* he) {
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900739 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
740 char *name;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900741 char *cp, **q;
742 int af, len;
743 size_t anum;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900744 struct in6_addr host_addr;
Bernie Innocenti55864192018-08-30 04:05:20 +0900745
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900746 if (hf == NULL) {
747 *he = NETDB_INTERNAL;
748 errno = EINVAL;
749 return NULL;
750 }
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900751 char* p = NULL;
752 size_t maxaliases = 10;
753 char** aliases = (char**) malloc(maxaliases * sizeof(char*));
754 if (!aliases) goto nospc;
Bernie Innocenti55864192018-08-30 04:05:20 +0900755
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900756 /* Allocate a new space to read file lines like upstream does.
757 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
758 * as the buffer may be used to store content for a previous hostent
759 * returned by non-reentrant functions like gethostbyname().
760 */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900761 if ((p = (char*) malloc(line_buf_size)) == NULL) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900762 goto nospc;
763 }
764 for (;;) {
765 if (!fgets(p, line_buf_size, hf)) {
766 free(p);
767 free(aliases);
768 *he = HOST_NOT_FOUND;
769 return NULL;
770 }
771 if (*p == '#') {
772 continue;
773 }
774 if (!(cp = strpbrk(p, "#\n"))) {
775 continue;
776 }
777 *cp = '\0';
778 if (!(cp = strpbrk(p, " \t"))) continue;
779 *cp++ = '\0';
780 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
781 af = AF_INET6;
782 len = NS_IN6ADDRSZ;
783 } else {
784 if (inet_pton(AF_INET, p, &host_addr) <= 0) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900785
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900786 res_state res = __res_get_state();
787 if (res == NULL) goto nospc;
788 if (res->options & RES_USE_INET6) {
789 map_v4v6_address(buf, buf);
790 af = AF_INET6;
791 len = NS_IN6ADDRSZ;
792 } else {
793 af = AF_INET;
794 len = NS_INADDRSZ;
795 }
796 __res_put_state(res);
797 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900798
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900799 /* if this is not something we're looking for, skip it. */
800 if (hent->h_addrtype != 0 && hent->h_addrtype != af) continue;
801 if (hent->h_length != 0 && hent->h_length != len) continue;
Bernie Innocenti55864192018-08-30 04:05:20 +0900802
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900803 while (*cp == ' ' || *cp == '\t') cp++;
804 if ((cp = strpbrk(name = cp, " \t")) != NULL) *cp++ = '\0';
805 q = aliases;
806 while (cp && *cp) {
807 if (*cp == ' ' || *cp == '\t') {
808 cp++;
809 continue;
810 }
811 addalias(q, cp, aliases, maxaliases);
812 if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0';
813 }
814 break;
815 }
816 hent->h_length = len;
817 hent->h_addrtype = af;
818 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
819 anum = (size_t)(q - aliases);
820 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
821 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf, buflen);
822 hent->h_addr_list[1] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900823
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900824 HENT_SCOPY(hent->h_name, name, buf, buflen);
825 for (size_t i = 0; i < anum; i++) HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
826 hent->h_aliases[anum] = NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900827
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900828 *he = NETDB_SUCCESS;
829 free(p);
830 free(aliases);
831 return hent;
Bernie Innocenti55864192018-08-30 04:05:20 +0900832nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900833 free(p);
834 free(aliases);
835 errno = ENOSPC;
836 *he = NETDB_INTERNAL;
837 return NULL;
Bernie Innocenti55864192018-08-30 04:05:20 +0900838}
839
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900840static void map_v4v6_address(const char* src, char* dst) {
841 u_char* p = (u_char*) dst;
842 char tmp[NS_INADDRSZ];
843 int i;
Bernie Innocenti55864192018-08-30 04:05:20 +0900844
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900845 _DIAGASSERT(src != NULL);
846 _DIAGASSERT(dst != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900847
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900848 /* Stash a temporary copy so our caller can update in place. */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900849 memcpy(tmp, src, NS_INADDRSZ);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900850 /* Mark this ipv6 addr as a mapped ipv4. */
851 for (i = 0; i < 10; i++) *p++ = 0x00;
852 *p++ = 0xff;
853 *p++ = 0xff;
854 /* Retrieve the saved copy and we're done. */
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900855 memcpy(p, tmp, NS_INADDRSZ);
Bernie Innocenti55864192018-08-30 04:05:20 +0900856}
857
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900858static void map_v4v6_hostent(struct hostent* hp, char** bpp, char* ep) {
859 char** ap;
Bernie Innocenti55864192018-08-30 04:05:20 +0900860
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900861 _DIAGASSERT(hp != NULL);
862 _DIAGASSERT(bpp != NULL);
863 _DIAGASSERT(ep != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900864
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900865 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ) return;
866 hp->h_addrtype = AF_INET6;
867 hp->h_length = NS_IN6ADDRSZ;
868 for (ap = hp->h_addr_list; *ap; ap++) {
869 int i = (int) (sizeof(align) - (size_t)((u_long) *bpp % sizeof(align)));
Bernie Innocenti55864192018-08-30 04:05:20 +0900870
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900871 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
872 /* Out of memory. Truncate address list here. XXX */
873 *ap = NULL;
874 return;
875 }
876 *bpp += i;
877 map_v4v6_address(*ap, *bpp);
878 *ap = *bpp;
879 *bpp += NS_IN6ADDRSZ;
880 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900881}
882
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900883static void addrsort(char** ap, int num, res_state res) {
884 int i, j;
885 char** p;
886 short aval[MAXADDRS];
887 int needsort = 0;
Bernie Innocenti55864192018-08-30 04:05:20 +0900888
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900889 _DIAGASSERT(ap != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900890
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900891 p = ap;
892 for (i = 0; i < num; i++, p++) {
893 for (j = 0; (unsigned) j < res->nsort; j++)
894 if (res->sort_list[j].addr.s_addr ==
895 (((struct in_addr*) (void*) (*p))->s_addr & res->sort_list[j].mask))
896 break;
897 aval[i] = j;
898 if (needsort == 0 && i > 0 && j < aval[i - 1]) needsort = i;
899 }
900 if (!needsort) return;
Bernie Innocenti55864192018-08-30 04:05:20 +0900901
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900902 while (needsort < num) {
903 for (j = needsort - 1; j >= 0; j--) {
904 if (aval[j] > aval[j + 1]) {
905 char* hp;
Bernie Innocenti55864192018-08-30 04:05:20 +0900906
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900907 i = aval[j];
908 aval[j] = aval[j + 1];
909 aval[j + 1] = i;
Bernie Innocenti55864192018-08-30 04:05:20 +0900910
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900911 hp = ap[j];
912 ap[j] = ap[j + 1];
913 ap[j + 1] = hp;
914 } else
915 break;
916 }
917 needsort++;
918 }
Bernie Innocenti55864192018-08-30 04:05:20 +0900919}
920
Bernie Innocenti9bf0e1d2018-09-12 17:59:17 +0900921static int _dns_gethtbyname(const char* name, int addr_type, getnamaddr* info) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900922 int n, type;
923 struct hostent* hp;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900924 res_state res;
Bernie Innocenti55864192018-08-30 04:05:20 +0900925
Bernie Innocenti9bf0e1d2018-09-12 17:59:17 +0900926 info->hp->h_addrtype = addr_type;
Bernie Innocenti55864192018-08-30 04:05:20 +0900927
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900928 switch (info->hp->h_addrtype) {
929 case AF_INET:
930 info->hp->h_length = NS_INADDRSZ;
931 type = T_A;
932 break;
933 case AF_INET6:
934 info->hp->h_length = NS_IN6ADDRSZ;
935 type = T_AAAA;
936 break;
937 default:
938 return NS_UNAVAIL;
939 }
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900940 querybuf* buf = (querybuf*) malloc(sizeof(querybuf));
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900941 if (buf == NULL) {
942 *info->he = NETDB_INTERNAL;
943 return NS_NOTFOUND;
944 }
945 res = __res_get_state();
946 if (res == NULL) {
947 free(buf);
948 return NS_NOTFOUND;
949 }
950 n = res_nsearch(res, name, C_IN, type, buf->buf, (int) sizeof(buf->buf));
951 if (n < 0) {
952 free(buf);
953 debugprintf("res_nsearch failed (%d)\n", res, n);
954 __res_put_state(res);
955 return NS_NOTFOUND;
956 }
957 hp = getanswer(buf, n, name, type, res, info->hp, info->buf, info->buflen, info->he);
958 free(buf);
959 __res_put_state(res);
960 if (hp == NULL) switch (*info->he) {
961 case HOST_NOT_FOUND:
962 return NS_NOTFOUND;
963 case TRY_AGAIN:
964 return NS_TRYAGAIN;
965 default:
966 return NS_UNAVAIL;
967 }
968 return NS_SUCCESS;
Bernie Innocenti55864192018-08-30 04:05:20 +0900969}
970
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900971static int _dns_gethtbyaddr(void* rv, void* /*cb_data*/, va_list ap) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900972 char qbuf[MAXDNAME + 1], *qp, *ep;
973 int n;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900974 struct hostent* hp;
975 const unsigned char* uaddr;
976 int advance;
977 res_state res;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +0900978 struct getnamaddr* info = (struct getnamaddr*) rv;
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900979 const struct android_net_context* netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +0900980
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900981 _DIAGASSERT(rv != NULL);
Bernie Innocenti55864192018-08-30 04:05:20 +0900982
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900983 uaddr = va_arg(ap, unsigned char*);
984 info->hp->h_length = va_arg(ap, int);
985 info->hp->h_addrtype = va_arg(ap, int);
986 netcontext = va_arg(ap, const struct android_net_context*);
Bernie Innocenti55864192018-08-30 04:05:20 +0900987
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900988 switch (info->hp->h_addrtype) {
989 case AF_INET:
990 (void) snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
991 (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
992 break;
Bernie Innocenti55864192018-08-30 04:05:20 +0900993
Bernie Innocentif12d5bb2018-08-31 14:09:46 +0900994 case AF_INET6:
995 qp = qbuf;
996 ep = qbuf + sizeof(qbuf) - 1;
997 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
998 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.", uaddr[n] & 0xf,
999 ((unsigned int) uaddr[n] >> 4) & 0xf);
1000 if (advance > 0 && qp + advance < ep)
1001 qp += advance;
1002 else {
1003 *info->he = NETDB_INTERNAL;
1004 return NS_NOTFOUND;
1005 }
1006 }
1007 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
1008 *info->he = NETDB_INTERNAL;
1009 return NS_NOTFOUND;
1010 }
1011 break;
1012 default:
1013 return NS_UNAVAIL;
1014 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001015
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001016 querybuf* buf = (querybuf*) malloc(sizeof(querybuf));
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001017 if (buf == NULL) {
1018 *info->he = NETDB_INTERNAL;
1019 return NS_NOTFOUND;
1020 }
1021 res = __res_get_state();
1022 if (res == NULL) {
1023 free(buf);
1024 return NS_NOTFOUND;
1025 }
1026 res_setnetcontext(res, netcontext);
1027 n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int) sizeof(buf->buf));
1028 if (n < 0) {
1029 free(buf);
1030 debugprintf("res_nquery failed (%d)\n", res, n);
1031 __res_put_state(res);
1032 return NS_NOTFOUND;
1033 }
1034 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf, info->buflen, info->he);
1035 free(buf);
1036 if (hp == NULL) {
1037 __res_put_state(res);
1038 switch (*info->he) {
1039 case HOST_NOT_FOUND:
1040 return NS_NOTFOUND;
1041 case TRY_AGAIN:
1042 return NS_TRYAGAIN;
1043 default:
1044 return NS_UNAVAIL;
1045 }
1046 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001047
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001048 char* bf = (char*) (hp->h_addr_list + 2);
1049 size_t blen = (size_t)(bf - info->buf);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001050 if (blen + info->hp->h_length > info->buflen) goto nospc;
1051 hp->h_addr_list[0] = bf;
1052 hp->h_addr_list[1] = NULL;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001053 memcpy(bf, uaddr, (size_t) info->hp->h_length);
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001054 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1055 if (blen + NS_IN6ADDRSZ > info->buflen) goto nospc;
1056 map_v4v6_address(bf, bf);
1057 hp->h_addrtype = AF_INET6;
1058 hp->h_length = NS_IN6ADDRSZ;
1059 }
Bernie Innocenti55864192018-08-30 04:05:20 +09001060
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001061 __res_put_state(res);
1062 *info->he = NETDB_SUCCESS;
1063 return NS_SUCCESS;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001064
Bernie Innocenti55864192018-08-30 04:05:20 +09001065nospc:
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001066 errno = ENOSPC;
1067 *info->he = NETDB_INTERNAL;
1068 return NS_UNAVAIL;
Bernie Innocenti55864192018-08-30 04:05:20 +09001069}
1070
Bernie Innocenti55864192018-08-30 04:05:20 +09001071/*
1072 * Non-reentrant versions.
1073 */
1074
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001075struct hostent* gethostbyname(const char* name) {
1076 struct hostent* result = NULL;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001077 struct res_static* rs = __res_get_static(); // For thread-safety.
Bernie Innocenti55864192018-08-30 04:05:20 +09001078
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001079 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1080 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001081}
1082
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001083struct hostent* gethostbyname2(const char* name, int af) {
1084 struct hostent* result = NULL;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001085 struct res_static* rs = __res_get_static(); // For thread-safety.
Bernie Innocenti55864192018-08-30 04:05:20 +09001086
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001087 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1088 return result;
Bernie Innocenti55864192018-08-30 04:05:20 +09001089}
1090
1091// android_gethostby*fornet can be called in two different contexts.
1092// - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
1093// - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
1094// The netcontext is constructed before checking which context we are in.
1095// Therefore, we have to populate both fields, and rely on the downstream code to check whether
1096// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
1097static struct android_net_context make_context(unsigned netid, unsigned mark) {
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001098 struct android_net_context netcontext = NETCONTEXT_UNSET;
1099 netcontext.app_netid = netid;
1100 netcontext.app_mark = mark;
1101 netcontext.dns_netid = netid;
1102 netcontext.dns_mark = mark;
1103 return netcontext;
Bernie Innocenti55864192018-08-30 04:05:20 +09001104}
1105
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001106struct hostent* android_gethostbynamefornet(const char* name, int af, unsigned netid,
1107 unsigned mark) {
1108 const struct android_net_context netcontext = make_context(netid, mark);
1109 return android_gethostbynamefornetcontext(name, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001110}
1111
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001112struct hostent* android_gethostbynamefornetcontext(const char* name, int af,
1113 const struct android_net_context* netcontext) {
1114 struct hostent* hp;
1115 res_state res = __res_get_state();
1116 if (res == NULL) return NULL;
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001117 struct res_static* rs = __res_get_static(); // For thread-safety.
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001118 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
1119 &h_errno, netcontext);
1120 __res_put_state(res);
1121 return hp;
Bernie Innocenti55864192018-08-30 04:05:20 +09001122}
1123
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001124struct hostent* gethostbyaddr(const void* addr, socklen_t len, int af) {
1125 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
Bernie Innocenti55864192018-08-30 04:05:20 +09001126}
1127
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001128struct hostent* android_gethostbyaddrfornet(const void* addr, socklen_t len, int af, unsigned netid,
1129 unsigned mark) {
1130 const struct android_net_context netcontext = make_context(netid, mark);
1131 return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001132}
1133
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001134struct hostent* android_gethostbyaddrfornetcontext(const void* addr, socklen_t len, int af,
1135 const struct android_net_context* netcontext) {
1136 return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001137}
1138
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001139__LIBC_HIDDEN__ struct hostent* android_gethostbyaddrfornetcontext_proxy(
1140 const void* addr, socklen_t len, int af, const struct android_net_context* netcontext) {
Bernie Innocenti1f4a9fd2018-09-07 21:10:25 +09001141 struct res_static* rs = __res_get_static(); // For thread-safety.
Bernie Innocentif12d5bb2018-08-31 14:09:46 +09001142 return android_gethostbyaddrfornetcontext_proxy_internal(
1143 addr, len, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno, netcontext);
Bernie Innocenti55864192018-08-30 04:05:20 +09001144}