blob: 75cb2b3c5ec735818853ba668e0c09d5d0f5468f [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
122#define MAXPACKET (64*1024)
123
124typedef union {
125 HEADER hdr;
126 u_char buf[MAXPACKET];
127} querybuf;
128
129typedef union {
130 int32_t al;
131 char ac;
132} align;
133
134#ifdef DEBUG
Yabin Cui58d33a52014-12-16 17:03:44 -0800135static void debugprintf(const char *, res_state, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800136 __attribute__((__format__(__printf__, 1, 3)));
137#endif
138static struct hostent *getanswer(const querybuf *, int, const char *, int,
Yabin Cui58d33a52014-12-16 17:03:44 -0800139 res_state, struct hostent *, char *, size_t, int *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800140static void map_v4v6_address(const char *, char *);
141static void map_v4v6_hostent(struct hostent *, char **, char *);
142static void addrsort(char **, int, res_state);
143
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800144void ht_sethostent(int);
145void ht_endhostent(void);
146struct hostent *ht_gethostbyname(char *);
147struct hostent *ht_gethostbyaddr(const char *, int, int);
148void dns_service(void);
149#undef dn_skipname
150int dn_skipname(const u_char *, const u_char *);
Jim Huange5c35e02010-09-27 23:37:10 +0800151static int _dns_gethtbyaddr(void *, void *, va_list);
152static int _dns_gethtbyname(void *, void *, va_list);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800153
Yabin Cui58d33a52014-12-16 17:03:44 -0800154static struct hostent *gethostbyname_internal(const char *, int, res_state,
155 struct hostent *, char *, size_t, int *, unsigned, unsigned);
156static struct hostent* android_gethostbyaddrfornet_proxy_internal(const void*, socklen_t,
157 int, struct hostent *, char *, size_t, int *, unsigned, unsigned);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800158
159static const ns_src default_dns_files[] = {
160 { NSSRC_FILES, NS_SUCCESS },
161 { NSSRC_DNS, NS_SUCCESS },
162 { 0, 0 }
163};
164
165
166#ifdef DEBUG
167static void
Yabin Cui58d33a52014-12-16 17:03:44 -0800168debugprintf(const char *msg, res_state res, ...)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800169{
Yabin Cui58d33a52014-12-16 17:03:44 -0800170 _DIAGASSERT(msg != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800171
172 if (res->options & RES_DEBUG) {
173 int save = errno;
174 va_list ap;
175
176 va_start (ap, res);
177 vprintf(msg, ap);
178 va_end (ap);
179
180 errno = save;
181 }
182}
183#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800184# define debugprintf(msg, res, num) /*nada*/
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800185#endif
186
187#define BOUNDED_INCR(x) \
188 do { \
Elliott Hughes722129e2016-11-14 13:56:32 -0800189 BOUNDS_CHECK(cp, x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800190 cp += (x); \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800191 } while (/*CONSTCOND*/0)
192
193#define BOUNDS_CHECK(ptr, count) \
194 do { \
Elliott Hughes722129e2016-11-14 13:56:32 -0800195 if (eom - (ptr) < (count)) \
Yabin Cui58d33a52014-12-16 17:03:44 -0800196 goto no_recovery; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800197 } while (/*CONSTCOND*/0)
198
199static struct hostent *
200getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
Yabin Cui58d33a52014-12-16 17:03:44 -0800201 res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800202{
203 const HEADER *hp;
204 const u_char *cp;
205 int n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800206 size_t qlen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800207 const u_char *eom, *erdata;
208 char *bp, **ap, **hap, *ep;
209 int type, class, ancount, qdcount;
210 int haveanswer, had_error;
211 int toobig = 0;
212 char tbuf[MAXDNAME];
Yabin Cui58d33a52014-12-16 17:03:44 -0800213 char **aliases;
214 size_t maxaliases;
215 char *addr_ptrs[MAXADDRS];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800216 const char *tname;
217 int (*name_ok)(const char *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800218
Yabin Cui58d33a52014-12-16 17:03:44 -0800219 _DIAGASSERT(answer != NULL);
220 _DIAGASSERT(qname != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800221
222 tname = qname;
Yabin Cui58d33a52014-12-16 17:03:44 -0800223 hent->h_name = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800224 eom = answer->buf + anslen;
225 switch (qtype) {
226 case T_A:
227 case T_AAAA:
228 name_ok = res_hnok;
229 break;
230 case T_PTR:
231 name_ok = res_dnok;
232 break;
233 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800234 *he = NO_RECOVERY;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800235 return NULL; /* XXX should be abort(); */
236 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800237
238 setup(aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800239 /*
240 * find first satisfactory answer
241 */
242 hp = &answer->hdr;
243 ancount = ntohs(hp->ancount);
244 qdcount = ntohs(hp->qdcount);
Yabin Cui58d33a52014-12-16 17:03:44 -0800245 bp = buf;
246 ep = buf + buflen;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800247 cp = answer->buf;
248 BOUNDED_INCR(HFIXEDSZ);
Yabin Cui58d33a52014-12-16 17:03:44 -0800249 if (qdcount != 1)
250 goto no_recovery;
251
252 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
253 if ((n < 0) || !maybe_ok(res, bp, name_ok))
254 goto no_recovery;
255
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800256 BOUNDED_INCR(n + QFIXEDSZ);
257 if (qtype == T_A || qtype == T_AAAA) {
258 /* res_send() has already verified that the query name is the
259 * same as the one we sent; this just gets the expanded name
260 * (i.e., with the succeeding search-domain tacked on).
261 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800262 n = (int)strlen(bp) + 1; /* for the \0 */
263 if (n >= MAXHOSTNAMELEN)
264 goto no_recovery;
265 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800266 bp += n;
267 /* The qname can be abbreviated, but h_name is now absolute. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800268 qname = hent->h_name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800269 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800270 hent->h_aliases = ap = aliases;
271 hent->h_addr_list = hap = addr_ptrs;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800272 *ap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800273 *hap = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800274 haveanswer = 0;
275 had_error = 0;
276 while (ancount-- > 0 && cp < eom && !had_error) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800277 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
278 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800279 had_error++;
280 continue;
281 }
282 cp += n; /* name */
283 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
284 type = _getshort(cp);
285 cp += INT16SZ; /* type */
286 class = _getshort(cp);
287 cp += INT16SZ + INT32SZ; /* class, TTL */
288 n = _getshort(cp);
289 cp += INT16SZ; /* len */
290 BOUNDS_CHECK(cp, n);
291 erdata = cp + n;
292 if (class != C_IN) {
293 /* XXX - debug? syslog? */
294 cp += n;
295 continue; /* XXX - had_error++ ? */
296 }
297 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800298 n = dn_expand(answer->buf, eom, cp, tbuf,
299 (int)sizeof tbuf);
300 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800301 had_error++;
302 continue;
303 }
304 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800305 if (cp != erdata)
306 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800307 /* Store alias. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800308 addalias(ap, bp, aliases, maxaliases);
309 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800310 if (n >= MAXHOSTNAMELEN) {
311 had_error++;
312 continue;
313 }
314 bp += n;
315 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800316 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800317 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
318 had_error++;
319 continue;
320 }
321 strlcpy(bp, tbuf, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800322 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800323 bp += n;
324 continue;
325 }
326 if (qtype == T_PTR && type == T_CNAME) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800327 n = dn_expand(answer->buf, eom, cp, tbuf,
328 (int)sizeof tbuf);
329 if (n < 0 || !maybe_dnok(res, tbuf)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800330 had_error++;
331 continue;
332 }
333 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800334 if (cp != erdata)
335 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800336 /* Get canonical name. */
Yabin Cui58d33a52014-12-16 17:03:44 -0800337 n = (int)strlen(tbuf) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800338 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
339 had_error++;
340 continue;
341 }
342 strlcpy(bp, tbuf, (size_t)(ep - bp));
343 tname = bp;
344 bp += n;
345 continue;
346 }
347 if (type != qtype) {
348 if (type != T_KEY && type != T_SIG)
349 syslog(LOG_NOTICE|LOG_AUTH,
350 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
351 qname, p_class(C_IN), p_type(qtype),
352 p_type(type));
353 cp += n;
354 continue; /* XXX - had_error++ ? */
355 }
356 switch (type) {
357 case T_PTR:
358 if (strcasecmp(tname, bp) != 0) {
359 syslog(LOG_NOTICE|LOG_AUTH,
360 AskedForGot, qname, bp);
361 cp += n;
362 continue; /* XXX - had_error++ ? */
363 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800364 n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
365 if ((n < 0) || !maybe_hnok(res, bp)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800366 had_error++;
367 break;
368 }
369#if MULTI_PTRS_ARE_ALIASES
370 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800371 if (cp != erdata)
372 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800373 if (!haveanswer)
Yabin Cui58d33a52014-12-16 17:03:44 -0800374 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800375 else
Yabin Cui58d33a52014-12-16 17:03:44 -0800376 addalias(ap, bp, aliases, maxaliases);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800377 if (n != -1) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800378 n = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800379 if (n >= MAXHOSTNAMELEN) {
380 had_error++;
381 break;
382 }
383 bp += n;
384 }
385 break;
386#else
Yabin Cui58d33a52014-12-16 17:03:44 -0800387 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800388 if (res->options & RES_USE_INET6) {
389 n = strlen(bp) + 1; /* for the \0 */
390 if (n >= MAXHOSTNAMELEN) {
391 had_error++;
392 break;
393 }
394 bp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800395 map_v4v6_hostent(hent, &bp, ep);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800396 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800397 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800398#endif
399 case T_A:
400 case T_AAAA:
Yabin Cui58d33a52014-12-16 17:03:44 -0800401 if (strcasecmp(hent->h_name, bp) != 0) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800402 syslog(LOG_NOTICE|LOG_AUTH,
Yabin Cui58d33a52014-12-16 17:03:44 -0800403 AskedForGot, hent->h_name, bp);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800404 cp += n;
405 continue; /* XXX - had_error++ ? */
406 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800407 if (n != hent->h_length) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800408 cp += n;
409 continue;
410 }
411 if (type == T_AAAA) {
412 struct in6_addr in6;
Yabin Cui58d33a52014-12-16 17:03:44 -0800413 memcpy(&in6, cp, NS_IN6ADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800414 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
415 cp += n;
416 continue;
417 }
418 }
419 if (!haveanswer) {
420 int nn;
421
Yabin Cui58d33a52014-12-16 17:03:44 -0800422 hent->h_name = bp;
423 nn = (int)strlen(bp) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800424 bp += nn;
425 }
426
427 bp += sizeof(align) -
428 (size_t)((u_long)bp % sizeof(align));
429
Yabin Cui58d33a52014-12-16 17:03:44 -0800430 if (bp + n >= ep) {
431 debugprintf("size (%d) too big\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800432 had_error++;
433 continue;
434 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800435 if (hap >= &addr_ptrs[MAXADDRS - 1]) {
436 if (!toobig++) {
437 debugprintf("Too many addresses (%d)\n",
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800438 res, MAXADDRS);
Yabin Cui58d33a52014-12-16 17:03:44 -0800439 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800440 cp += n;
441 continue;
442 }
443 (void)memcpy(*hap++ = bp, cp, (size_t)n);
444 bp += n;
445 cp += n;
Yabin Cui58d33a52014-12-16 17:03:44 -0800446 if (cp != erdata)
447 goto no_recovery;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800448 break;
449 default:
450 abort();
451 }
452 if (!had_error)
453 haveanswer++;
454 }
455 if (haveanswer) {
456 *ap = NULL;
457 *hap = NULL;
458 /*
459 * Note: we sort even if host can take only one address
460 * in its return structures - should give it the "best"
461 * address in that case, not some random one
462 */
463 if (res->nsort && haveanswer > 1 && qtype == T_A)
Yabin Cui58d33a52014-12-16 17:03:44 -0800464 addrsort(addr_ptrs, haveanswer, res);
465 if (!hent->h_name) {
466 n = (int)strlen(qname) + 1; /* for the \0 */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800467 if (n > ep - bp || n >= MAXHOSTNAMELEN)
468 goto no_recovery;
469 strlcpy(bp, qname, (size_t)(ep - bp));
Yabin Cui58d33a52014-12-16 17:03:44 -0800470 hent->h_name = bp;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800471 bp += n;
472 }
473 if (res->options & RES_USE_INET6)
Yabin Cui58d33a52014-12-16 17:03:44 -0800474 map_v4v6_hostent(hent, &bp, ep);
475 goto success;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800476 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800477no_recovery:
478 free(aliases);
479 *he = NO_RECOVERY;
480 return NULL;
481success:
482 bp = (char *)ALIGN(bp);
483 n = (int)(ap - aliases);
484 qlen = (n + 1) * sizeof(*hent->h_aliases);
485 if ((size_t)(ep - bp) < qlen)
486 goto nospc;
487 hent->h_aliases = (void *)bp;
488 memcpy(bp, aliases, qlen);
489 free(aliases);
490 aliases = NULL;
491
492 bp += qlen;
493 n = (int)(hap - addr_ptrs);
494 qlen = (n + 1) * sizeof(*hent->h_addr_list);
495 if ((size_t)(ep - bp) < qlen)
496 goto nospc;
497 hent->h_addr_list = (void *)bp;
498 memcpy(bp, addr_ptrs, qlen);
499 *he = NETDB_SUCCESS;
500 return hent;
501nospc:
502 free(aliases);
503 errno = ENOSPC;
504 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800505 return NULL;
506}
507
Yabin Cui58d33a52014-12-16 17:03:44 -0800508/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800509int
510gethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
Yabin Cui58d33a52014-12-16 17:03:44 -0800511 struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800512{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800513 res_state res = __res_get_state();
514
Yabin Cui58d33a52014-12-16 17:03:44 -0800515 if (res == NULL) {
516 *result = NULL;
517 *errorp = NETDB_INTERNAL;
518 return -1;
519 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800520
Yabin Cui58d33a52014-12-16 17:03:44 -0800521 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800522
523 if (res->options & RES_USE_INET6) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800524 *result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp, NETID_UNSET,
525 MARK_UNSET);
526 if (*result) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800527 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800528 return 0;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800529 }
530 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800531 *result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp, NETID_UNSET,
532 MARK_UNSET);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800533 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800534 if (!*result && errno == ENOSPC) {
535 errno = ERANGE;
536 return ERANGE; /* Return error as in linux manual page. */
537 }
538 return (*result) ? 0 : -1;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800539}
540
Yabin Cui58d33a52014-12-16 17:03:44 -0800541/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
542int
543gethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
544 size_t buflen, struct hostent **result, int *errorp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800545{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800546 res_state res = __res_get_state();
547
Yabin Cui58d33a52014-12-16 17:03:44 -0800548 if (res == NULL) {
549 *result = NULL;
550 *errorp = NETDB_INTERNAL;
551 return -1;
552 }
553 *result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp, NETID_UNSET,
554 MARK_UNSET);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800555 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -0800556 if (!*result && errno == ENOSPC) {
557 errno = ERANGE;
558 return ERANGE;
559 }
560 return (*result) ? 0 : -1;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800561}
562
Elliott Hughes9773fa32014-12-10 14:56:46 -0800563__LIBC_HIDDEN__ FILE* android_open_proxy() {
564 const char* cache_mode = getenv("ANDROID_DNS_MODE");
565 bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
566 if (!use_proxy) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200567 return NULL;
568 }
569
Elliott Hughes9773fa32014-12-10 14:56:46 -0800570 int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
571 if (s == -1) {
572 return NULL;
573 }
574
575 const int one = 1;
576 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
577
578 struct sockaddr_un proxy_addr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200579 memset(&proxy_addr, 0, sizeof(proxy_addr));
580 proxy_addr.sun_family = AF_UNIX;
581 strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
Elliott Hughes9773fa32014-12-10 14:56:46 -0800582
583 if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
584 close(s);
Mattias Falkc63e5902011-08-23 14:34:14 +0200585 return NULL;
586 }
587
Elliott Hughes9773fa32014-12-10 14:56:46 -0800588 return fdopen(s, "r+");
Mattias Falkc63e5902011-08-23 14:34:14 +0200589}
590
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800591static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800592android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200593{
594 uint32_t size;
595 char buf[4];
596 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
597
Elliott Hughes9773fa32014-12-10 14:56:46 -0800598 // This is reading serialized data from system/netd/server/DnsProxyListener.cpp
599 // and changes here need to be matched there.
Mattias Falkc63e5902011-08-23 14:34:14 +0200600 int result_code = strtol(buf, NULL, 10);
601 if (result_code != DnsProxyQueryResult) {
602 fread(&size, 1, sizeof(size), proxy);
Yabin Cui58d33a52014-12-16 17:03:44 -0800603 *he = HOST_NOT_FOUND;
Mattias Falkc63e5902011-08-23 14:34:14 +0200604 return NULL;
605 }
606
607 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
608 size = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200609
Yabin Cui58d33a52014-12-16 17:03:44 -0800610 memset(hp, 0, sizeof(*hp));
611 char *ptr = hbuf;
612 char *hbuf_end = hbuf + hbuflen;
613
614 if (ptr + size > hbuf_end) {
615 goto nospc;
616 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200617 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800618 hp->h_name = ptr;
Mattias Falkc63e5902011-08-23 14:34:14 +0200619 ptr += size;
Mattias Falkc63e5902011-08-23 14:34:14 +0200620
Yabin Cui58d33a52014-12-16 17:03:44 -0800621 char *aliases_ptrs[MAXALIASES];
622 char **aliases = &aliases_ptrs[0];
623
Mattias Falkc63e5902011-08-23 14:34:14 +0200624 while (1) {
625 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
626 size = ntohl(size);
627
628 if (size == 0) {
629 *aliases = NULL;
630 break;
631 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800632 if (ptr + size > hbuf_end) {
633 goto nospc;
634 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200635 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800636 if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
637 *aliases++ = ptr;
638 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200639 ptr += size;
640 }
641
Elliott Hughes65dd8582015-07-06 14:16:12 -0700642 // Fix alignment after variable-length data.
643 ptr = (char*)ALIGN(ptr);
644
Yabin Cui58d33a52014-12-16 17:03:44 -0800645 int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
646 if (ptr + aliases_len > hbuf_end) {
647 goto nospc;
648 }
649 hp->h_aliases = (void*)ptr;
650 memcpy(ptr, aliases_ptrs, aliases_len);
651 ptr += aliases_len;
Mattias Falkc63e5902011-08-23 14:34:14 +0200652
653 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800654 hp->h_addrtype = ntohl(size);
Mattias Falkc63e5902011-08-23 14:34:14 +0200655
Yabin Cui58d33a52014-12-16 17:03:44 -0800656 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
657 hp->h_length = ntohl(size);
658
659 char *addr_ptrs[MAXADDRS];
660 char **addr_p = &addr_ptrs[0];
661
Mattias Falkc63e5902011-08-23 14:34:14 +0200662 while (1) {
663 if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
664 size = ntohl(size);
665 if (size == 0) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800666 *addr_p = NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200667 break;
668 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800669 if (ptr + size > hbuf_end) {
670 goto nospc;
671 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200672 if (fread(ptr, 1, size, proxy) != size) return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800673 if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
674 *addr_p++ = ptr;
675 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200676 ptr += size;
677 }
678
Elliott Hughes65dd8582015-07-06 14:16:12 -0700679 // Fix alignment after variable-length data.
680 ptr = (char*)ALIGN(ptr);
681
Yabin Cui58d33a52014-12-16 17:03:44 -0800682 int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
683 if (ptr + addrs_len > hbuf_end) {
684 goto nospc;
685 }
686 hp->h_addr_list = (void*)ptr;
687 memcpy(ptr, addr_ptrs, addrs_len);
688 *he = NETDB_SUCCESS;
689 return hp;
690
691nospc:
692 *he = NETDB_INTERNAL;
693 errno = ENOSPC;
694 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200695}
696
Mattias Falkc63e5902011-08-23 14:34:14 +0200697static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800698gethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf,
699 size_t buflen, int *he)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800700{
701 const char *cp;
Yabin Cui58d33a52014-12-16 17:03:44 -0800702 struct getnamaddr info;
703 char hbuf[MAXHOSTNAMELEN];
704 size_t size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800705 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800706 NS_FILES_CB(_hf_gethtbyname, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800707 { NSSRC_DNS, _dns_gethtbyname, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800708 NS_NIS_CB(_yp_gethtbyname, NULL)
709 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800710 };
711
Yabin Cui58d33a52014-12-16 17:03:44 -0800712 _DIAGASSERT(name != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800713
714 switch (af) {
715 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -0800716 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800717 break;
718 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -0800719 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800720 break;
721 default:
Yabin Cui58d33a52014-12-16 17:03:44 -0800722 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800723 errno = EAFNOSUPPORT;
724 return NULL;
725 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800726 if (buflen < size)
727 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800728
Yabin Cui58d33a52014-12-16 17:03:44 -0800729 hp->h_addrtype = af;
730 hp->h_length = (int)size;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800731
732 /*
733 * if there aren't any dots, it could be a user-level alias.
734 * this is also done in res_nquery() since we are not the only
735 * function that looks up host names.
736 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800737 if (!strchr(name, '.') && (cp = res_hostalias(res, name,
738 hbuf, sizeof(hbuf))))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800739 name = cp;
740
741 /*
742 * disallow names consisting only of digits/dots, unless
743 * they end in a dot.
744 */
745 if (isdigit((u_char) name[0]))
746 for (cp = name;; ++cp) {
747 if (!*cp) {
748 if (*--cp == '.')
749 break;
750 /*
751 * All-numeric, no dot at the end.
752 * Fake up a hostent as if we'd actually
753 * done a lookup.
754 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800755 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800756 }
757 if (!isdigit((u_char) *cp) && *cp != '.')
758 break;
759 }
760 if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
761 name[0] == ':')
762 for (cp = name;; ++cp) {
763 if (!*cp) {
764 if (*--cp == '.')
765 break;
766 /*
767 * All-IPv6-legal, no dot at the end.
768 * Fake up a hostent as if we'd actually
769 * done a lookup.
770 */
Yabin Cui58d33a52014-12-16 17:03:44 -0800771 goto fake;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800772 }
773 if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
774 break;
775 }
776
Yabin Cui58d33a52014-12-16 17:03:44 -0800777 *he = NETDB_INTERNAL;
778 info.hp = hp;
779 info.buf = buf;
780 info.buflen = buflen;
781 info.he = he;
782 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
783 default_dns_files, name, strlen(name), af) != NS_SUCCESS)
784 return NULL;
785 *he = NETDB_SUCCESS;
786 return hp;
787nospc:
788 *he = NETDB_INTERNAL;
789 errno = ENOSPC;
790 return NULL;
791fake:
792 HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
793 HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
794
795 hp->h_aliases[0] = NULL;
796 if (size > buflen)
797 goto nospc;
798
799 if (inet_pton(af, name, buf) <= 0) {
800 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800801 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200802 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800803 hp->h_addr_list[0] = buf;
804 hp->h_addr_list[1] = NULL;
805 buf += size;
806 buflen -= size;
807 HENT_SCOPY(hp->h_name, name, buf, buflen);
808 if (res->options & RES_USE_INET6)
809 map_v4v6_hostent(hp, &buf, buf + buflen);
810 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800811 return hp;
812}
813
Mattias Falkc63e5902011-08-23 14:34:14 +0200814// very similar in proxy-ness to android_getaddrinfo_proxy
815static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800816gethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
817 size_t hbuflen, int *errorp, unsigned netid, unsigned mark)
Mattias Falkc63e5902011-08-23 14:34:14 +0200818{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800819 FILE* proxy = android_open_proxy();
820 if (proxy == NULL) {
821 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500822 res_setnetid(res, netid);
Chad Brubakerc39214e2013-06-20 10:36:56 -0700823 res_setmark(res, mark);
Yabin Cui58d33a52014-12-16 17:03:44 -0800824 return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
Mattias Falkc63e5902011-08-23 14:34:14 +0200825 }
826
Paul Jensen5240b562014-05-15 14:43:07 -0400827 netid = __netdClientDispatch.netIdForResolv(netid);
828
Elliott Hughes9773fa32014-12-10 14:56:46 -0800829 // This is writing to system/netd/server/DnsProxyListener.cpp and changes
830 // here need to be matched there.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500831 if (fprintf(proxy, "gethostbyname %u %s %d",
832 netid,
Mattias Falkc63e5902011-08-23 14:34:14 +0200833 name == NULL ? "^" : name,
834 af) < 0) {
Elliott Hughes9773fa32014-12-10 14:56:46 -0800835 fclose(proxy);
836 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200837 }
838
839 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200840 fclose(proxy);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800841 return NULL;
Mattias Falkc63e5902011-08-23 14:34:14 +0200842 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800843
Yabin Cui58d33a52014-12-16 17:03:44 -0800844 struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800845 fclose(proxy);
Mattias Falkc63e5902011-08-23 14:34:14 +0200846 return result;
847}
848
Yabin Cui58d33a52014-12-16 17:03:44 -0800849/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
850int gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
851 size_t buflen, struct hostent **result, int *h_errnop)
852{
853 *result = android_gethostbyaddrfornet_proxy_internal(addr, len, af, hp, buf, buflen, h_errnop,
854 NETID_UNSET, MARK_UNSET);
855 if (!*result && errno == ENOSPC) {
856 errno = ERANGE;
857 return ERANGE;
858 }
859 return (*result) ? 0 : -1;
860}
Mattias Falkc63e5902011-08-23 14:34:14 +0200861
Elliott Hughes9773fa32014-12-10 14:56:46 -0800862static struct hostent *
Yabin Cui58d33a52014-12-16 17:03:44 -0800863android_gethostbyaddrfornet_real(const void *addr, socklen_t len, int af, struct hostent *hp,
864 char *buf, size_t buflen, int *he, unsigned netid, unsigned mark)
865{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800866 const u_char *uaddr = (const u_char *)addr;
867 socklen_t size;
Yabin Cui58d33a52014-12-16 17:03:44 -0800868 struct getnamaddr info;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800869 static const ns_dtab dtab[] = {
Yabin Cui58d33a52014-12-16 17:03:44 -0800870 NS_FILES_CB(_hf_gethtbyaddr, NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800871 { NSSRC_DNS, _dns_gethtbyaddr, NULL }, /* force -DHESIOD */
Yabin Cui58d33a52014-12-16 17:03:44 -0800872 NS_NIS_CB(_yp_gethtbyaddr, NULL)
873 NS_NULL_CB
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800874 };
875
Yabin Cui58d33a52014-12-16 17:03:44 -0800876 _DIAGASSERT(addr != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800877
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700878 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
879 (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
880 IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
Yabin Cui58d33a52014-12-16 17:03:44 -0800881 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800882 return NULL;
883 }
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700884 if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
885 (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
886 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800887 /* Unmap. */
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700888 uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
889 addr = uaddr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800890 af = AF_INET;
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700891 len = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800892 }
893 switch (af) {
894 case AF_INET:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700895 size = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800896 break;
897 case AF_INET6:
Elliott Hughes3e5f0c92014-05-06 11:23:40 -0700898 size = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800899 break;
900 default:
901 errno = EAFNOSUPPORT;
Yabin Cui58d33a52014-12-16 17:03:44 -0800902 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800903 return NULL;
904 }
905 if (size != len) {
906 errno = EINVAL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800907 *he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800908 return NULL;
909 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800910 info.hp = hp;
911 info.buf = buf;
912 info.buflen = buflen;
913 info.he = he;
914 *he = NETDB_INTERNAL;
915 if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
916 default_dns_files, uaddr, len, af, netid, mark) != NS_SUCCESS)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800917 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800918 *he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800919 return hp;
920}
921
Yabin Cui58d33a52014-12-16 17:03:44 -0800922static struct hostent*
923android_gethostbyaddrfornet_proxy_internal(const void* addr, socklen_t len, int af,
924 struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
925 unsigned netid, unsigned mark)
926{
Elliott Hughes9773fa32014-12-10 14:56:46 -0800927 FILE* proxy = android_open_proxy();
928 if (proxy == NULL) {
929 // Either we're not supposed to be using the proxy or the proxy is unavailable.
Yabin Cui58d33a52014-12-16 17:03:44 -0800930 return android_gethostbyaddrfornet_real(addr,len, af, hp, hbuf, hbuflen, he, netid, mark);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800931 }
932
933 char buf[INET6_ADDRSTRLEN]; //big enough for IPv4 and IPv6
934 const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
935 if (addrStr == NULL) {
936 fclose(proxy);
937 return NULL;
938 }
939
940 netid = __netdClientDispatch.netIdForResolv(netid);
941
942 if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
943 addrStr, len, af, netid) < 0) {
944 fclose(proxy);
945 return NULL;
946 }
947
948 if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
949 fclose(proxy);
950 return NULL;
951 }
952
Yabin Cui58d33a52014-12-16 17:03:44 -0800953 struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800954 fclose(proxy);
955 return result;
956}
957
Yabin Cui58d33a52014-12-16 17:03:44 -0800958struct hostent*
959netbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
Mattias Falkc63e5902011-08-23 14:34:14 +0200960{
Yabin Cui58d33a52014-12-16 17:03:44 -0800961 char *p, *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800962 char *cp, **q;
963 int af, len;
Yabin Cui58d33a52014-12-16 17:03:44 -0800964 size_t anum;
965 char **aliases;
966 size_t maxaliases;
967 struct in6_addr host_addr;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800968
Yabin Cui58d33a52014-12-16 17:03:44 -0800969 if (hf == NULL) {
970 *he = NETDB_INTERNAL;
971 errno = EINVAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800972 return NULL;
973 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800974 p = NULL;
975 setup(aliases, maxaliases);
976
977 /* Allocate a new space to read file lines like upstream does.
978 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
979 * as the buffer may be used to store content for a previous hostent
980 * returned by non-reentrant functions like gethostbyname().
981 */
982 const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
983 if ((p = malloc(line_buf_size)) == NULL) {
984 goto nospc;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800985 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800986 for (;;) {
987 if (!fgets(p, line_buf_size, hf)) {
988 free(p);
989 free(aliases);
990 *he = HOST_NOT_FOUND;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800991 return NULL;
Yabin Cui58d33a52014-12-16 17:03:44 -0800992 }
993 if (*p == '#') {
994 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800995 }
Yabin Cui58d33a52014-12-16 17:03:44 -0800996 if (!(cp = strpbrk(p, "#\n"))) {
997 continue;
998 }
999 *cp = '\0';
1000 if (!(cp = strpbrk(p, " \t")))
1001 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001002 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001003 if (inet_pton(AF_INET6, p, &host_addr) > 0) {
1004 af = AF_INET6;
1005 len = NS_IN6ADDRSZ;
1006 } else {
1007 if (inet_pton(AF_INET, p, &host_addr) <= 0)
1008 continue;
1009
1010 res_state res = __res_get_state();
1011 if (res == NULL)
1012 goto nospc;
1013 if (res->options & RES_USE_INET6) {
1014 map_v4v6_address(buf, buf);
1015 af = AF_INET6;
1016 len = NS_IN6ADDRSZ;
1017 } else {
1018 af = AF_INET;
1019 len = NS_INADDRSZ;
1020 }
1021 __res_put_state(res);
1022 }
1023
1024 /* if this is not something we're looking for, skip it. */
1025 if (hent->h_addrtype != 0 && hent->h_addrtype != af)
1026 continue;
1027 if (hent->h_length != 0 && hent->h_length != len)
1028 continue;
1029
1030 while (*cp == ' ' || *cp == '\t')
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001031 cp++;
Yabin Cui58d33a52014-12-16 17:03:44 -08001032 if ((cp = strpbrk(name = cp, " \t")) != NULL)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001033 *cp++ = '\0';
Yabin Cui58d33a52014-12-16 17:03:44 -08001034 q = aliases;
1035 while (cp && *cp) {
1036 if (*cp == ' ' || *cp == '\t') {
1037 cp++;
1038 continue;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001039 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001040 addalias(q, cp, aliases, maxaliases);
1041 if ((cp = strpbrk(cp, " \t")) != NULL)
1042 *cp++ = '\0';
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001043 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001044 break;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001045 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001046 hent->h_length = len;
1047 hent->h_addrtype = af;
1048 HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
1049 anum = (size_t)(q - aliases);
1050 HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
1051 HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
1052 buflen);
1053 hent->h_addr_list[1] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001054
Yabin Cui58d33a52014-12-16 17:03:44 -08001055 HENT_SCOPY(hent->h_name, name, buf, buflen);
1056 for (size_t i = 0; i < anum; i++)
1057 HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
1058 hent->h_aliases[anum] = NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001059
Yabin Cui58d33a52014-12-16 17:03:44 -08001060 *he = NETDB_SUCCESS;
1061 free(p);
1062 free(aliases);
1063 return hent;
1064nospc:
1065 free(p);
1066 free(aliases);
1067 errno = ENOSPC;
1068 *he = NETDB_INTERNAL;
1069 return NULL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001070}
1071
1072static void
1073map_v4v6_address(const char *src, char *dst)
1074{
1075 u_char *p = (u_char *)dst;
Yabin Cui58d33a52014-12-16 17:03:44 -08001076 char tmp[NS_INADDRSZ];
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001077 int i;
1078
Yabin Cui58d33a52014-12-16 17:03:44 -08001079 _DIAGASSERT(src != NULL);
1080 _DIAGASSERT(dst != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001081
1082 /* Stash a temporary copy so our caller can update in place. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001083 (void)memcpy(tmp, src, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001084 /* Mark this ipv6 addr as a mapped ipv4. */
1085 for (i = 0; i < 10; i++)
1086 *p++ = 0x00;
1087 *p++ = 0xff;
1088 *p++ = 0xff;
1089 /* Retrieve the saved copy and we're done. */
Yabin Cui58d33a52014-12-16 17:03:44 -08001090 (void)memcpy(p, tmp, NS_INADDRSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001091}
1092
1093static void
1094map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1095{
1096 char **ap;
1097
Yabin Cui58d33a52014-12-16 17:03:44 -08001098 _DIAGASSERT(hp != NULL);
1099 _DIAGASSERT(bpp != NULL);
1100 _DIAGASSERT(ep != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001101
Yabin Cui58d33a52014-12-16 17:03:44 -08001102 if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001103 return;
1104 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001105 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001106 for (ap = hp->h_addr_list; *ap; ap++) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001107 int i = (int)(sizeof(align) -
1108 (size_t)((u_long)*bpp % sizeof(align)));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001109
Yabin Cui58d33a52014-12-16 17:03:44 -08001110 if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001111 /* Out of memory. Truncate address list here. XXX */
1112 *ap = NULL;
1113 return;
1114 }
1115 *bpp += i;
1116 map_v4v6_address(*ap, *bpp);
1117 *ap = *bpp;
Yabin Cui58d33a52014-12-16 17:03:44 -08001118 *bpp += NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001119 }
1120}
1121
1122static void
1123addrsort(char **ap, int num, res_state res)
1124{
1125 int i, j;
1126 char **p;
1127 short aval[MAXADDRS];
1128 int needsort = 0;
1129
Yabin Cui58d33a52014-12-16 17:03:44 -08001130 _DIAGASSERT(ap != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001131
1132 p = ap;
1133 for (i = 0; i < num; i++, p++) {
1134 for (j = 0 ; (unsigned)j < res->nsort; j++)
1135 if (res->sort_list[j].addr.s_addr ==
1136 (((struct in_addr *)(void *)(*p))->s_addr &
1137 res->sort_list[j].mask))
1138 break;
1139 aval[i] = j;
1140 if (needsort == 0 && i > 0 && j < aval[i-1])
1141 needsort = i;
1142 }
1143 if (!needsort)
1144 return;
1145
1146 while (needsort < num) {
1147 for (j = needsort - 1; j >= 0; j--) {
1148 if (aval[j] > aval[j+1]) {
1149 char *hp;
1150
1151 i = aval[j];
1152 aval[j] = aval[j+1];
1153 aval[j+1] = i;
1154
1155 hp = ap[j];
1156 ap[j] = ap[j+1];
1157 ap[j+1] = hp;
1158 } else
1159 break;
1160 }
1161 needsort++;
1162 }
1163}
1164
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001165/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001166static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001167_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
1168{
1169 querybuf *buf;
1170 int n, type;
1171 struct hostent *hp;
1172 const char *name;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001173 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001174 struct getnamaddr *info = rv;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001175
Yabin Cui58d33a52014-12-16 17:03:44 -08001176 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001177
1178 name = va_arg(ap, char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001179 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1180 info->hp->h_addrtype = va_arg(ap, int);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001181
Yabin Cui58d33a52014-12-16 17:03:44 -08001182 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001183 case AF_INET:
Yabin Cui58d33a52014-12-16 17:03:44 -08001184 info->hp->h_length = NS_INADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001185 type = T_A;
1186 break;
1187 case AF_INET6:
Yabin Cui58d33a52014-12-16 17:03:44 -08001188 info->hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001189 type = T_AAAA;
1190 break;
1191 default:
1192 return NS_UNAVAIL;
1193 }
1194 buf = malloc(sizeof(*buf));
1195 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001196 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001197 return NS_NOTFOUND;
1198 }
1199 res = __res_get_state();
1200 if (res == NULL) {
1201 free(buf);
1202 return NS_NOTFOUND;
1203 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001204 n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001205 if (n < 0) {
1206 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001207 debugprintf("res_nsearch failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001208 __res_put_state(res);
1209 return NS_NOTFOUND;
1210 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001211 hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
1212 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001213 free(buf);
1214 __res_put_state(res);
1215 if (hp == NULL)
Yabin Cui70692562014-12-19 10:10:04 -08001216 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001217 case HOST_NOT_FOUND:
1218 return NS_NOTFOUND;
1219 case TRY_AGAIN:
1220 return NS_TRYAGAIN;
1221 default:
1222 return NS_UNAVAIL;
1223 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001224 return NS_SUCCESS;
1225}
1226
1227/*ARGSUSED*/
Jim Huange5c35e02010-09-27 23:37:10 +08001228static int
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001229_dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1230{
1231 char qbuf[MAXDNAME + 1], *qp, *ep;
1232 int n;
1233 querybuf *buf;
1234 struct hostent *hp;
1235 const unsigned char *uaddr;
Yabin Cui58d33a52014-12-16 17:03:44 -08001236 int advance;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001237 res_state res;
Yabin Cui58d33a52014-12-16 17:03:44 -08001238 char *bf;
1239 size_t blen;
1240 struct getnamaddr *info = rv;
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001241 unsigned netid, mark;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001242
Yabin Cui58d33a52014-12-16 17:03:44 -08001243 _DIAGASSERT(rv != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001244
1245 uaddr = va_arg(ap, unsigned char *);
Yabin Cui58d33a52014-12-16 17:03:44 -08001246 info->hp->h_length = va_arg(ap, int);
1247 info->hp->h_addrtype = va_arg(ap, int);
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001248 netid = va_arg(ap, unsigned);
1249 mark = va_arg(ap, unsigned);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001250
Yabin Cui58d33a52014-12-16 17:03:44 -08001251 switch (info->hp->h_addrtype) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001252 case AF_INET:
1253 (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
1254 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
1255 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
1256 break;
1257
1258 case AF_INET6:
1259 qp = qbuf;
1260 ep = qbuf + sizeof(qbuf) - 1;
Yabin Cui58d33a52014-12-16 17:03:44 -08001261 for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001262 advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
1263 uaddr[n] & 0xf,
1264 ((unsigned int)uaddr[n] >> 4) & 0xf);
1265 if (advance > 0 && qp + advance < ep)
1266 qp += advance;
1267 else {
Yabin Cui58d33a52014-12-16 17:03:44 -08001268 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001269 return NS_NOTFOUND;
1270 }
1271 }
1272 if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001273 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001274 return NS_NOTFOUND;
1275 }
1276 break;
1277 default:
Yabin Cui58d33a52014-12-16 17:03:44 -08001278 return NS_UNAVAIL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001279 }
1280
1281 buf = malloc(sizeof(*buf));
1282 if (buf == NULL) {
Yabin Cui58d33a52014-12-16 17:03:44 -08001283 *info->he = NETDB_INTERNAL;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001284 return NS_NOTFOUND;
1285 }
1286 res = __res_get_state();
1287 if (res == NULL) {
1288 free(buf);
1289 return NS_NOTFOUND;
1290 }
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001291 res_setnetid(res, netid);
Chad Brubakerc39214e2013-06-20 10:36:56 -07001292 res_setmark(res, mark);
Yabin Cui58d33a52014-12-16 17:03:44 -08001293 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 -08001294 if (n < 0) {
1295 free(buf);
Yabin Cui58d33a52014-12-16 17:03:44 -08001296 debugprintf("res_nquery failed (%d)\n", res, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001297 __res_put_state(res);
1298 return NS_NOTFOUND;
1299 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001300 hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
1301 info->buflen, info->he);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001302 free(buf);
1303 if (hp == NULL) {
1304 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001305 switch (*info->he) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001306 case HOST_NOT_FOUND:
1307 return NS_NOTFOUND;
1308 case TRY_AGAIN:
1309 return NS_TRYAGAIN;
1310 default:
1311 return NS_UNAVAIL;
1312 }
1313 }
Yabin Cui58d33a52014-12-16 17:03:44 -08001314
1315 bf = (void *)(hp->h_addr_list + 2);
1316 blen = (size_t)(bf - info->buf);
1317 if (blen + info->hp->h_length > info->buflen)
1318 goto nospc;
1319 hp->h_addr_list[0] = bf;
1320 hp->h_addr_list[1] = NULL;
1321 (void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
1322 if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
1323 if (blen + NS_IN6ADDRSZ > info->buflen)
1324 goto nospc;
1325 map_v4v6_address(bf, bf);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001326 hp->h_addrtype = AF_INET6;
Yabin Cui58d33a52014-12-16 17:03:44 -08001327 hp->h_length = NS_IN6ADDRSZ;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001328 }
1329
1330 __res_put_state(res);
Yabin Cui58d33a52014-12-16 17:03:44 -08001331 *info->he = NETDB_SUCCESS;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001332 return NS_SUCCESS;
Yabin Cui58d33a52014-12-16 17:03:44 -08001333nospc:
Yabin Cui70692562014-12-19 10:10:04 -08001334 errno = ENOSPC;
Yabin Cui58d33a52014-12-16 17:03:44 -08001335 *info->he = NETDB_INTERNAL;
1336 return NS_UNAVAIL;
1337}
1338
1339#ifdef YP
1340/*ARGSUSED*/
1341static struct hostent *
1342_yp_hostent(char *line, int af, struct getnamaddr *info)
1343{
1344 struct in6_addr host_addrs[MAXADDRS];
1345 char **aliases;
1346 size_t maxaliases;
1347 char *p = line;
1348 char *cp, **q, *ptr;
1349 size_t len, anum, i;
1350 int addrok;
1351 int more;
1352 size_t naddrs;
1353 struct hostent *hp = info->hp;
1354
1355 _DIAGASSERT(line != NULL);
1356
1357 hp->h_name = NULL;
1358 hp->h_addrtype = af;
1359 switch (af) {
1360 case AF_INET:
1361 hp->h_length = NS_INADDRSZ;
1362 break;
1363 case AF_INET6:
1364 hp->h_length = NS_IN6ADDRSZ;
1365 break;
1366 default:
1367 return NULL;
1368 }
1369 setup(aliases, maxaliases);
1370 naddrs = 0;
1371 q = aliases;
1372
1373nextline:
1374 /* check for host_addrs overflow */
1375 if (naddrs >= __arraycount(host_addrs))
1376 goto done;
1377
1378 more = 0;
1379 cp = strpbrk(p, " \t");
1380 if (cp == NULL)
1381 goto done;
1382 *cp++ = '\0';
1383
1384 /* p has should have an address */
1385 addrok = inet_pton(af, p, &host_addrs[naddrs]);
1386 if (addrok != 1) {
1387 /* skip to the next line */
1388 while (cp && *cp) {
1389 if (*cp == '\n') {
1390 cp++;
1391 goto nextline;
1392 }
1393 cp++;
1394 }
1395 goto done;
1396 }
1397 naddrs++;
1398
1399 while (*cp == ' ' || *cp == '\t')
1400 cp++;
1401 p = cp;
1402 cp = strpbrk(p, " \t\n");
1403 if (cp != NULL) {
1404 if (*cp == '\n')
1405 more = 1;
1406 *cp++ = '\0';
1407 }
1408 if (!hp->h_name)
1409 hp->h_name = p;
1410 else if (strcmp(hp->h_name, p) == 0)
1411 ;
1412 else
1413 addalias(q, p, aliases, maxaliases);
1414 p = cp;
1415 if (more)
1416 goto nextline;
1417
1418 while (cp && *cp) {
1419 if (*cp == ' ' || *cp == '\t') {
1420 cp++;
1421 continue;
1422 }
1423 if (*cp == '\n') {
1424 cp++;
1425 goto nextline;
1426 }
1427 addalias(q, cp, aliases, maxaliases);
1428 cp = strpbrk(cp, " \t");
1429 if (cp != NULL)
1430 *cp++ = '\0';
1431 }
1432
1433done:
1434 if (hp->h_name == NULL) {
1435 free(aliases);
1436 return NULL;
1437 }
1438
1439 ptr = info->buf;
1440 len = info->buflen;
1441
1442 anum = (size_t)(q - aliases);
1443 HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
1444 HENT_ARRAY(hp->h_aliases, anum, ptr, len);
1445
1446 for (i = 0; i < naddrs; i++)
1447 HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
1448 ptr, len);
1449 hp->h_addr_list[naddrs] = NULL;
1450
1451 HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
1452
1453 for (i = 0; i < anum; i++)
1454 HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
1455 hp->h_aliases[anum] = NULL;
1456 free(aliases);
1457
1458 return hp;
1459nospc:
1460 free(aliases);
1461 *info->he = NETDB_INTERNAL;
1462 errno = ENOSPC;
1463 return NULL;
1464}
1465
1466/*ARGSUSED*/
1467int
1468_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
1469{
1470 struct hostent *hp = NULL;
1471 char *ypcurrent;
1472 int ypcurrentlen, r;
1473 char name[INET6_ADDRSTRLEN]; /* XXX enough? */
1474 const unsigned char *uaddr;
1475 int af;
1476 const char *map;
1477 struct getnamaddr *info = rv;
1478
1479 _DIAGASSERT(rv != NULL);
1480
1481 uaddr = va_arg(ap, unsigned char *);
1482 /* NOSTRICT skip len */(void)va_arg(ap, int);
1483 af = va_arg(ap, int);
1484
1485 if (!__ypdomain) {
1486 if (_yp_check(&__ypdomain) == 0)
1487 return NS_UNAVAIL;
1488 }
1489 /*
1490 * XXX unfortunately, we cannot support IPv6 extended scoped address
1491 * notation here. gethostbyaddr() is not scope-aware. too bad.
1492 */
1493 if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
1494 return NS_UNAVAIL;
1495 switch (af) {
1496 case AF_INET:
1497 map = "hosts.byaddr";
1498 break;
1499 default:
1500 map = "ipnodes.byaddr";
1501 break;
1502 }
1503 ypcurrent = NULL;
1504 r = yp_match(__ypdomain, map, name,
1505 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1506 if (r == 0)
1507 hp = _yp_hostent(ypcurrent, af, info);
1508 else
1509 hp = NULL;
1510 free(ypcurrent);
1511 if (hp == NULL) {
1512 *info->he = HOST_NOT_FOUND;
1513 return NS_NOTFOUND;
1514 }
1515 return NS_SUCCESS;
1516}
1517
1518/*ARGSUSED*/
1519int
1520_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
1521{
1522 struct hostent *hp;
1523 char *ypcurrent;
1524 int ypcurrentlen, r;
1525 const char *name;
1526 int af;
1527 const char *map;
1528 struct getnamaddr *info = rv;
1529
1530 _DIAGASSERT(rv != NULL);
1531
1532 name = va_arg(ap, char *);
1533 /* NOSTRICT skip string len */(void)va_arg(ap, int);
1534 af = va_arg(ap, int);
1535
1536 if (!__ypdomain) {
1537 if (_yp_check(&__ypdomain) == 0)
1538 return NS_UNAVAIL;
1539 }
1540 switch (af) {
1541 case AF_INET:
1542 map = "hosts.byname";
1543 break;
1544 default:
1545 map = "ipnodes.byname";
1546 break;
1547 }
1548 ypcurrent = NULL;
1549 r = yp_match(__ypdomain, map, name,
1550 (int)strlen(name), &ypcurrent, &ypcurrentlen);
1551 if (r == 0)
1552 hp = _yp_hostent(ypcurrent, af, info);
1553 else
1554 hp = NULL;
1555 free(ypcurrent);
1556 if (hp == NULL) {
1557 *info->he = HOST_NOT_FOUND;
1558 return NS_NOTFOUND;
1559 }
1560 return NS_SUCCESS;
1561}
1562#endif
1563
1564/*
1565 * Non-reentrant versions.
1566 */
1567
1568struct hostent *
1569gethostbyname(const char *name)
1570{
1571 struct hostent *result = NULL;
1572 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1573
1574 gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1575 return result;
1576}
1577
1578struct hostent *
1579gethostbyname2(const char *name, int af)
1580{
1581 struct hostent *result = NULL;
1582 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1583
1584 gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
1585 return result;
1586}
1587
1588struct hostent *
1589android_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
1590{
1591 struct hostent *hp;
1592 res_state res = __res_get_state();
1593 if (res == NULL)
1594 return NULL;
1595 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1596 hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
1597 &h_errno, netid, mark);
1598 __res_put_state(res);
1599 return hp;
1600}
1601
1602struct hostent *
1603gethostbyaddr(const void *addr, socklen_t len, int af)
1604{
1605 return android_gethostbyaddrfornet_proxy(addr, len, af, NETID_UNSET, MARK_UNSET);
1606}
1607
1608struct hostent *
1609android_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
1610{
1611 return android_gethostbyaddrfornet_proxy(addr, len, af, netid, mark);
1612}
1613
1614__LIBC_HIDDEN__ struct hostent*
1615android_gethostbyaddrfornet_proxy(const void* addr, socklen_t len, int af,
1616 unsigned netid, unsigned mark)
1617{
1618 res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
1619 return android_gethostbyaddrfornet_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
1620 sizeof(rs->hostbuf), &h_errno, netid, mark);
1621}
1622
1623struct hostent *
1624gethostent(void)
1625{
1626 res_static rs = __res_get_static();
1627 if (!rs->hostf) {
1628 sethostent_r(&rs->hostf);
1629 if (!rs->hostf) {
1630 h_errno = NETDB_INTERNAL;
1631 return NULL;
1632 }
1633 }
1634 memset(&rs->host, 0, sizeof(rs->host));
1635 return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001636}