158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/*	$NetBSD: gethnamaddr.c,v 1.91 2014/06/19 15:08:18 christos Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ++Copyright++ 1985, 1988, 1993
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1985, 1988, 1993
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    The Regents of the University of California.  All rights reserved.
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Portions Copyright (c) 1993 by Digital Equipment Corporation.
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this software for any
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * purpose with or without fee is hereby granted, provided that the above
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * copyright notice and this permission notice appear in all copies, and that
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the name of Digital Equipment Corporation not be used in advertising or
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * publicity pertaining to distribution of the document or software without
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * specific, written prior permission.
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SOFTWARE.
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * -
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * --Copyright--
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/param.h>
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/socket.h>
59c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk#include <sys/un.h>
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netinet/in.h>
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <arpa/inet.h>
62569fb9887d00104509df79fa77d92e3cf9afe7dbCalin Juravle#include <arpa/nameser.h>
635240b562e7e9de2f31ba70f71c394c5529aadf0fPaul Jensen#include "NetdClientDispatch.h"
64ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak#include "resolv_netid.h"
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_private.h"
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "resolv_cache.h"
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <assert.h>
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <ctype.h>
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <netdb.h>
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdarg.h>
729773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes#include <stdbool.h>
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
742cc2b2be692f1d559a09d2066e56e450249cc9c0Carl Shapiro#include <strings.h>
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <syslog.h>
76c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk#include <unistd.h>
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
78c20de902875dcaebde0ccd0b7a8351598f254d4cCalin Juravle#define ALIGNBYTES (sizeof(uintptr_t) - 1)
79c20de902875dcaebde0ccd0b7a8351598f254d4cCalin Juravle#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
80c20de902875dcaebde0ccd0b7a8351598f254d4cCalin Juravle
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifndef LOG_AUTH
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project# define LOG_AUTH 0
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MULTI_PTRS_ARE_ALIASES 1	/* XXX - experimental */
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "nsswitch.h"
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#include "hostent.h"
9258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
9358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
9458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui                               (ok)(nm) != 0)
9558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
9658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok)
9758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
9858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#define addalias(d, s, arr, siz) do {			\
9958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (d >= &arr[siz]) {				\
10058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		char **xptr = realloc(arr, (siz + 10) * sizeof(*arr)); \
10158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (xptr == NULL)			\
10258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto nospc;			\
10358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		d = xptr + (d - arr);			\
10458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		arr = xptr;				\
10558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		siz += 10;				\
10658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}						\
10758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*d++ = s;					\
10858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui} while (/*CONSTCOND*/0)
10958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
11058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#define setup(arr, siz) do {				\
11158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	arr = malloc((siz = 10) * sizeof(*arr)); 	\
11258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (arr == NULL)				\
11358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;				\
11458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui} while (/*CONSTCOND*/0)
11558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
116c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk// This should be synchronized to ResponseCode.h
117c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falkstatic const int DnsProxyQueryResult = 222;
118c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
11968c2755d71750401d82d9aa17774ebd385cb5dc0Elliott Hughesstatic const char AskedForGot[] =
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			  "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12250178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzstatic const struct android_net_context NETCONTEXT_UNSET = {
12350178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	.app_mark = MARK_UNSET,
12450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	.app_netid = NETID_UNSET,
12550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	.dns_mark = MARK_UNSET,
12650178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	.dns_netid = NETID_UNSET,
12750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	.uid = NET_CONTEXT_INVALID_UID
12850178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz};
12950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz
13047fb0e826dd8c345d9034fda75c3238488a4690cBen Schwartz#define	MAXPACKET	(8*1024)
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union {
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    HEADER hdr;
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    u_char buf[MAXPACKET];
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} querybuf;
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union {
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    int32_t al;
1391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    char ac;
1401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} align;
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG
14358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistatic void debugprintf(const char *, res_state, ...)
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	__attribute__((__format__(__printf__, 1, 3)));
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct hostent *getanswer(const querybuf *, int, const char *, int,
14758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui    res_state, struct hostent *, char *, size_t, int *);
1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void map_v4v6_address(const char *, char *);
1491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void map_v4v6_hostent(struct hostent *, char **, char *);
1501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void addrsort(char **, int, res_state);
1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid ht_sethostent(int);
1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid ht_endhostent(void);
1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct hostent *ht_gethostbyname(char *);
1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct hostent *ht_gethostbyaddr(const char *, int, int);
1561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvoid dns_service(void);
1571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#undef dn_skipname
1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint dn_skipname(const u_char *, const u_char *);
159e5c35e075fad5b5c143971c4401a360f6eaf5470Jim Huangstatic int _dns_gethtbyaddr(void *, void *, va_list);
160e5c35e075fad5b5c143971c4401a360f6eaf5470Jim Huangstatic int _dns_gethtbyname(void *, void *, va_list);
1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
16258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistatic struct hostent *gethostbyname_internal(const char *, int, res_state,
163dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz    struct hostent *, char *, size_t, int *, const struct android_net_context *);
16450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzstatic struct hostent* android_gethostbyaddrfornetcontext_proxy_internal(const void*, socklen_t,
16550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz    int, struct hostent *, char *, size_t, int *, const struct android_net_context *);
1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const ns_src default_dns_files[] = {
1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	{ NSSRC_FILES, 	NS_SUCCESS },
1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	{ NSSRC_DNS, 	NS_SUCCESS },
1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	{ 0, 0 }
1711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project};
1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
173bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughesstatic int h_errno_to_result(int* herrno_p) {
174bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes  // glibc considers ERANGE a special case (and BSD uses ENOSPC instead).
175bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes  if (*herrno_p == NETDB_INTERNAL && errno == ENOSPC) {
176bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes    errno = ERANGE;
177bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes    return errno;
178bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes  }
179bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes  // glibc considers HOST_NOT_FOUND not an error for the _r functions' return value.
180bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes  return (*herrno_p != HOST_NOT_FOUND) ? *herrno_p : 0;
181bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes}
1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef DEBUG
1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
18558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuidebugprintf(const char *msg, res_state res, ...)
1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
18758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(msg != NULL);
1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (res->options & RES_DEBUG) {
1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int save = errno;
1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		va_list ap;
1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		va_start (ap, res);
1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		vprintf(msg, ap);
1951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		va_end (ap);
1961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = save;
1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
20158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui# define debugprintf(msg, res, num) /*nada*/
2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BOUNDED_INCR(x) \
2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do { \
20687c0dba7b1b1754d69cc92f2b400a311d6393eedElliott Hughes		BOUNDS_CHECK(cp, x); \
2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += (x); \
2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (/*CONSTCOND*/0)
2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define BOUNDS_CHECK(ptr, count) \
2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	do { \
21287c0dba7b1b1754d69cc92f2b400a311d6393eedElliott Hughes		if (eom - (ptr) < (count)) \
21358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto no_recovery; \
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} while (/*CONSTCOND*/0)
2151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct hostent *
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgetanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
21858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui    res_state res, struct hostent *hent, char *buf, size_t buflen, int *he)
2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const HEADER *hp;
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *cp;
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
22358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t qlen;
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *eom, *erdata;
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *bp, **ap, **hap, *ep;
2261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int type, class, ancount, qdcount;
2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int haveanswer, had_error;
2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int toobig = 0;
2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char tbuf[MAXDNAME];
23058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char **aliases;
23158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t maxaliases;
23258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *addr_ptrs[MAXADDRS];
2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *tname;
2341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int (*name_ok)(const char *);
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
23658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(answer != NULL);
23758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(qname != NULL);
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	tname = qname;
24058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_name = NULL;
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	eom = answer->buf + anslen;
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (qtype) {
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case T_A:
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case T_AAAA:
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		name_ok = res_hnok;
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case T_PTR:
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		name_ok = res_dnok;
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
25158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  *he = NO_RECOVERY;
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;	/* XXX should be abort(); */
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
25458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
25558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	setup(aliases, maxaliases);
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * find first satisfactory answer
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	hp = &answer->hdr;
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ancount = ntohs(hp->ancount);
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	qdcount = ntohs(hp->qdcount);
26258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	bp = buf;
26358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	ep = buf + buflen;
2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = answer->buf;
2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	BOUNDED_INCR(HFIXEDSZ);
26658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (qdcount != 1)
26758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto no_recovery;
26858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
26958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
27058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if ((n < 0) || !maybe_ok(res, bp, name_ok))
27158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto no_recovery;
27258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	BOUNDED_INCR(n + QFIXEDSZ);
2741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (qtype == T_A || qtype == T_AAAA) {
2751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* res_send() has already verified that the query name is the
2761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * same as the one we sent; this just gets the expanded name
2771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * (i.e., with the succeeding search-domain tacked on).
2781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
27958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		n = (int)strlen(bp) + 1;		/* for the \0 */
28058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (n >= MAXHOSTNAMELEN)
28158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto no_recovery;
28258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hent->h_name = bp;
2831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		bp += n;
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* The qname can be abbreviated, but h_name is now absolute. */
28558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		qname = hent->h_name;
2861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
28758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_aliases = ap = aliases;
28858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_addr_list = hap = addr_ptrs;
2891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*ap = NULL;
2901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*hap = NULL;
2911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	haveanswer = 0;
2921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	had_error = 0;
2931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (ancount-- > 0 && cp < eom && !had_error) {
29458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
29558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
2961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			had_error++;
2971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
2981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
2991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += n;			/* name */
3001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
3011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		type = _getshort(cp);
3021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 		cp += INT16SZ;			/* type */
3031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		class = _getshort(cp);
3041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 		cp += INT16SZ + INT32SZ;	/* class, TTL */
3051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		n = _getshort(cp);
3061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp += INT16SZ;			/* len */
3071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		BOUNDS_CHECK(cp, n);
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		erdata = cp + n;
3091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (class != C_IN) {
3101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* XXX - debug? syslog? */
3111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
3121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;		/* XXX - had_error++ ? */
3131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
31558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = dn_expand(answer->buf, eom, cp, tbuf,
31658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			    (int)sizeof tbuf);
31758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
3201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
32258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (cp != erdata)
32358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto no_recovery;
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Store alias. */
32558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			addalias(ap, bp, aliases, maxaliases);
32658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = (int)strlen(bp) + 1;	/* for the \0 */
3271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n >= MAXHOSTNAMELEN) {
3281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
3301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += n;
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Get canonical name. */
33358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
3371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strlcpy(bp, tbuf, (size_t)(ep - bp));
33958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			hent->h_name = bp;
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += n;
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (qtype == T_PTR && type == T_CNAME) {
34458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = dn_expand(answer->buf, eom, cp, tbuf,
34558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			    (int)sizeof tbuf);
34658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (n < 0 || !maybe_dnok(res, tbuf)) {
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
3491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
35158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (cp != erdata)
35258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto no_recovery;
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Get canonical name. */
35458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = (int)strlen(tbuf) + 1;	/* for the \0 */
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strlcpy(bp, tbuf, (size_t)(ep - bp));
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			tname = bp;
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += n;
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (type != qtype) {
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (type != T_KEY && type != T_SIG)
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				syslog(LOG_NOTICE|LOG_AUTH,
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				       qname, p_class(C_IN), p_type(qtype),
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				       p_type(type));
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;		/* XXX - had_error++ ? */
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (type) {
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_PTR:
3751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (strcasecmp(tname, bp) != 0) {
3761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				syslog(LOG_NOTICE|LOG_AUTH,
3771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				       AskedForGot, qname, bp);
3781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				cp += n;
3791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;	/* XXX - had_error++ ? */
3801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
38158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = dn_expand(answer->buf, eom, cp, bp, (int)(ep - bp));
38258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if ((n < 0) || !maybe_hnok(res, bp)) {
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if MULTI_PTRS_ARE_ALIASES
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
38858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (cp != erdata)
38958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto no_recovery;
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!haveanswer)
39158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				hent->h_name = bp;
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
39358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				addalias(ap, bp, aliases, maxaliases);
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n != -1) {
39558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				n = (int)strlen(bp) + 1;	/* for the \0 */
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (n >= MAXHOSTNAMELEN) {
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					had_error++;
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				bp += n;
4011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
40458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			hent->h_name = bp;
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (res->options & RES_USE_INET6) {
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				n = strlen(bp) + 1;	/* for the \0 */
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (n >= MAXHOSTNAMELEN) {
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					had_error++;
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				bp += n;
41258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				map_v4v6_hostent(hent, &bp, ep);
4131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
41458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto success;
4151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
4161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_A:
4171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_AAAA:
41858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (strcasecmp(hent->h_name, bp) != 0) {
4191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				syslog(LOG_NOTICE|LOG_AUTH,
42058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				       AskedForGot, hent->h_name, bp);
4211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				cp += n;
4221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;	/* XXX - had_error++ ? */
4231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
42458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (n != hent->h_length) {
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				cp += n;
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (type == T_AAAA) {
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				struct in6_addr in6;
43058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				memcpy(&in6, cp, NS_IN6ADDRSZ);
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					cp += n;
4331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					continue;
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!haveanswer) {
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				int nn;
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
43958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				hent->h_name = bp;
44058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				nn = (int)strlen(bp) + 1;	/* for the \0 */
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				bp += nn;
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += sizeof(align) -
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    (size_t)((u_long)bp % sizeof(align));
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
44758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (bp + n >= ep) {
44858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				debugprintf("size (%d) too big\n", res, n);
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				had_error++;
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
45258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (hap >= &addr_ptrs[MAXADDRS - 1]) {
45358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				if (!toobig++) {
45458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui					debugprintf("Too many addresses (%d)\n",
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						res, MAXADDRS);
45658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				}
4571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				cp += n;
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				continue;
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			(void)memcpy(*hap++ = bp, cp, (size_t)n);
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += n;
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp += n;
46358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (cp != erdata)
46458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto no_recovery;
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			abort();
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (!had_error)
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			haveanswer++;
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (haveanswer) {
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*ap = NULL;
4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*hap = NULL;
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Note: we sort even if host can take only one address
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * in its return structures - should give it the "best"
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * address in that case, not some random one
4791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
4801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (res->nsort && haveanswer > 1 && qtype == T_A)
48158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			addrsort(addr_ptrs, haveanswer, res);
48258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (!hent->h_name) {
48358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			n = (int)strlen(qname) + 1;	/* for the \0 */
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (n > ep - bp || n >= MAXHOSTNAMELEN)
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto no_recovery;
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			strlcpy(bp, qname, (size_t)(ep - bp));
48758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			hent->h_name = bp;
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			bp += n;
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (res->options & RES_USE_INET6)
49158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			map_v4v6_hostent(hent, &bp, ep);
49258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  goto success;
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
49458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuino_recovery:
49558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
49658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NO_RECOVERY;
49758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NULL;
49858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuisuccess:
49958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	bp = (char *)ALIGN(bp);
50058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	n = (int)(ap - aliases);
50158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	qlen = (n + 1) * sizeof(*hent->h_aliases);
50258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if ((size_t)(ep - bp) < qlen)
50358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
50458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_aliases = (void *)bp;
50558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memcpy(bp, aliases, qlen);
50658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
50758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	aliases = NULL;
50858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
50958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	bp += qlen;
51058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	n = (int)(hap - addr_ptrs);
51158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	qlen = (n + 1) * sizeof(*hent->h_addr_list);
51258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if ((size_t)(ep - bp) < qlen)
51358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
51458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_addr_list = (void *)bp;
51558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memcpy(bp, addr_ptrs, qlen);
51658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
51758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hent;
51858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
51958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
52058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	errno = ENOSPC;
52158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return NULL;
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
52558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/* The prototype of gethostbyname_r is from glibc, not that in netbsd. */
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectgethostbyname_r(const char *name, struct hostent *hp, char *buf, size_t buflen,
52858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui    struct hostent **result, int *errorp)
5291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
5301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state res = __res_get_state();
53158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (res == NULL) {
532bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes		*result = NULL;
53358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*errorp = NETDB_INTERNAL;
53458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return -1;
53558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
53758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(name != NULL);
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (res->options & RES_USE_INET6) {
540dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz		*result = gethostbyname_internal(name, AF_INET6, res, hp, buf, buflen, errorp,
541dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz		                                 &NETCONTEXT_UNSET);
54258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (*result) {
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			__res_put_state(res);
54458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			return 0;
5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
547dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	*result = gethostbyname_internal(name, AF_INET, res, hp, buf, buflen, errorp,
548dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	                                 &NETCONTEXT_UNSET);
549bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes	return h_errno_to_result(errorp);
550c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk}
551c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
55258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/* The prototype of gethostbyname2_r is from glibc, not that in netbsd. */
55358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiint
55458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyname2_r(const char *name, int af, struct hostent *hp, char *buf,
55558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui    size_t buflen, struct hostent **result, int *errorp)
556c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk{
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state res = __res_get_state();
55858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (res == NULL) {
55958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*result = NULL;
56058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*errorp = NETDB_INTERNAL;
56158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return -1;
56258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
563dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	*result = gethostbyname_internal(name, af, res, hp, buf, buflen, errorp,
564dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	                                 &NETCONTEXT_UNSET);
565bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes	return h_errno_to_result(errorp);
5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5689773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes__LIBC_HIDDEN__ FILE* android_open_proxy() {
5699773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	const char* cache_mode = getenv("ANDROID_DNS_MODE");
5709773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	bool use_proxy = (cache_mode == NULL || strcmp(cache_mode, "local") != 0);
5719773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (!use_proxy) {
5729773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
5739773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	}
574c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
5759773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
5769773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (s == -1) {
577c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		return NULL;
578c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
579c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
5809773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	const int one = 1;
5819773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
5829773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
5839773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	struct sockaddr_un proxy_addr;
584c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	memset(&proxy_addr, 0, sizeof(proxy_addr));
585c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	proxy_addr.sun_family = AF_UNIX;
586c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", sizeof(proxy_addr.sun_path));
5879773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
5889773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (TEMP_FAILURE_RETRY(connect(s, (const struct sockaddr*) &proxy_addr, sizeof(proxy_addr))) != 0) {
5899773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		close(s);
590c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		return NULL;
591c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
592c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
5939773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	return fdopen(s, "r+");
594c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk}
595c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
596c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falkstatic struct hostent *
59758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiandroid_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen, int *he)
598c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk{
599c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	uint32_t size;
600c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	char buf[4];
601c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) return NULL;
602c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
6039773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	// This is reading serialized data from system/netd/server/DnsProxyListener.cpp
6049773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	// and changes here need to be matched there.
605c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	int result_code = strtol(buf, NULL, 10);
606c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (result_code != DnsProxyQueryResult) {
607c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		fread(&size, 1, sizeof(size), proxy);
60858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = HOST_NOT_FOUND;
609c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		return NULL;
610c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
611c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
612c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
613c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	size = ntohl(size);
614c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
61558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memset(hp, 0, sizeof(*hp));
61658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *ptr = hbuf;
61758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *hbuf_end = hbuf + hbuflen;
61858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
61958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (ptr + size > hbuf_end) {
62058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
62158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
622c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fread(ptr, 1, size, proxy) != size) return NULL;
62358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_name = ptr;
624c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	ptr += size;
625c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
62658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *aliases_ptrs[MAXALIASES];
62758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char **aliases = &aliases_ptrs[0];
62858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
629c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	while (1) {
630c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
631c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		size = ntohl(size);
632c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
633c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (size == 0) {
634c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk			*aliases = NULL;
635c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk			break;
636c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		}
63758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (ptr + size > hbuf_end) {
63858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		  goto nospc;
63958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
640c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (fread(ptr, 1, size, proxy) != size) return NULL;
64158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (aliases < &aliases_ptrs[MAXALIASES - 1]) {
64258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		  *aliases++ = ptr;
64358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
644c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		ptr += size;
645c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
646c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
64765dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes	// Fix alignment after variable-length data.
64865dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes	ptr = (char*)ALIGN(ptr);
64965dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes
65058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
65158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (ptr + aliases_len > hbuf_end) {
65258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
65358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
65458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_aliases = (void*)ptr;
65558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memcpy(ptr, aliases_ptrs, aliases_len);
65658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	ptr += aliases_len;
65758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
658c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
65958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addrtype = ntohl(size);
660c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
661c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
66258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_length = ntohl(size);
66358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
66458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *addr_ptrs[MAXADDRS];
66558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char **addr_p = &addr_ptrs[0];
666c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
667c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	while (1) {
668c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (fread(&size, 1, sizeof(size), proxy) != sizeof(size)) return NULL;
669c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		size = ntohl(size);
670c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (size == 0) {
67158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			*addr_p = NULL;
672c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk			break;
673c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		}
67458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (ptr + size > hbuf_end) {
67558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		  goto nospc;
67658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
677c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		if (fread(ptr, 1, size, proxy) != size) return NULL;
67858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (addr_p < &addr_ptrs[MAXADDRS - 1]) {
67958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		  *addr_p++ = ptr;
68058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
681c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		ptr += size;
682c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
683c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
68465dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes	// Fix alignment after variable-length data.
68565dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes	ptr = (char*)ALIGN(ptr);
68665dd858239c4e32a5a1afbc14ac30dbcdd2a50a3Elliott Hughes
68758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
68858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (ptr + addrs_len > hbuf_end) {
68958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
69058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
69158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list = (void*)ptr;
69258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memcpy(ptr, addr_ptrs, addrs_len);
69358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
69458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hp;
695c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
69658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
69758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
69858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	errno = ENOSPC;
69958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NULL;
70058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
701c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
7021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct hostent *
70358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyname_internal_real(const char *name, int af, res_state res, struct hostent *hp, char *buf,
70458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui                            size_t buflen, int *he)
7051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
7061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *cp;
70758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr info;
70858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char hbuf[MAXHOSTNAMELEN];
70958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t size;
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	static const ns_dtab dtab[] = {
71158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_FILES_CB(_hf_gethtbyname, NULL)
7121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		{ NSSRC_DNS, _dns_gethtbyname, NULL },	/* force -DHESIOD */
71358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_NIS_CB(_yp_gethtbyname, NULL)
71458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_NULL_CB
7151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	};
7161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
71758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(name != NULL);
7181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (af) {
7201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
72158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		size = NS_INADDRSZ;
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
7231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
72458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		size = NS_IN6ADDRSZ;
7251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
7261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
72758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = NETDB_INTERNAL;
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EAFNOSUPPORT;
7291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
7301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
73158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (buflen < size)
73258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
7331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
73458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addrtype = af;
73558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_length = (int)size;
7361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
7381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * if there aren't any dots, it could be a user-level alias.
7391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * this is also done in res_nquery() since we are not the only
7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * function that looks up host names.
7411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
74258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (!strchr(name, '.') && (cp = res_hostalias(res, name,
74358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    hbuf, sizeof(hbuf))))
7441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		name = cp;
7451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
7461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
7471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * disallow names consisting only of digits/dots, unless
7481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * they end in a dot.
7491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
7501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (isdigit((u_char) name[0]))
7511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (cp = name;; ++cp) {
7521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!*cp) {
7531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (*--cp == '.')
7541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
7551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
7561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * All-numeric, no dot at the end.
7571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * Fake up a hostent as if we'd actually
7581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * done a lookup.
7591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
76058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto fake;
7611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
7621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!isdigit((u_char) *cp) && *cp != '.')
7631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
7641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((isxdigit((u_char) name[0]) && strchr(name, ':') != NULL) ||
7661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    name[0] == ':')
7671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		for (cp = name;; ++cp) {
7681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!*cp) {
7691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (*--cp == '.')
7701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
7711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
7721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * All-IPv6-legal, no dot at the end.
7731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * Fake up a hostent as if we'd actually
7741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * done a lookup.
7751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
77658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto fake;
7771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
7781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!isxdigit((u_char) *cp) && *cp != ':' && *cp != '.')
7791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
7801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
7811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
78258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
78358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.hp = hp;
78458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.buf = buf;
78558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.buflen = buflen;
78658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.he = he;
78758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyname",
78858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    default_dns_files, name, strlen(name), af) != NS_SUCCESS)
78958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NULL;
79058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
79158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hp;
79258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
79358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
79458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	errno = ENOSPC;
79558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NULL;
79658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuifake:
79758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hp->h_addr_list, 1, buf, buflen);
79858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hp->h_aliases, 0, buf, buflen);
79958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
80058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_aliases[0] = NULL;
80158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (size > buflen)
80258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
80358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
80458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (inet_pton(af, name, buf) <= 0) {
80558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = HOST_NOT_FOUND;
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
807c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
80858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list[0] = buf;
80958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list[1] = NULL;
81058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	buf += size;
81158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	buflen -= size;
81258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_SCOPY(hp->h_name, name, buf, buflen);
81358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (res->options & RES_USE_INET6)
81458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map_v4v6_hostent(hp, &buf, buf + buflen);
81558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return hp;
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
819c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk// very similar in proxy-ness to android_getaddrinfo_proxy
820c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falkstatic struct hostent *
82158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyname_internal(const char *name, int af, res_state res, struct hostent *hp, char *hbuf,
822dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz                       size_t hbuflen, int *errorp, const struct android_net_context *netcontext)
823c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk{
8249773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	FILE* proxy = android_open_proxy();
8259773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (proxy == NULL) {
8269773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		// Either we're not supposed to be using the proxy or the proxy is unavailable.
82790a83beb4dd3a70aeb512a786e9a79bbd641f4deBen Schwartz		res_setnetcontext(res, netcontext);
82858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return gethostbyname_internal_real(name, af, res, hp, hbuf, hbuflen, errorp);
829c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
830c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
831dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
8325240b562e7e9de2f31ba70f71c394c5529aadf0fPaul Jensen
8339773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	// This is writing to system/netd/server/DnsProxyListener.cpp and changes
8349773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	// here need to be matched there.
835ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak	if (fprintf(proxy, "gethostbyname %u %s %d",
836ea9bf6788144b83cc51c454b2bfe6b980d6e947cSzymon Jakubczak			netid,
837c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk			name == NULL ? "^" : name,
838c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk			af) < 0) {
839c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		fclose(proxy);
8409773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
841c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
842c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
843c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
844c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk		fclose(proxy);
8459773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
846c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	}
8479773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
84858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent* result = android_read_hostent(proxy, hp, hbuf, hbuflen, errorp);
8499773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	fclose(proxy);
850c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk	return result;
851c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk}
852c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk
85358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/* The prototype of gethostbyaddr_r is from glibc, not that in netbsd. */
85458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiint gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp, char *buf,
85558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui                    size_t buflen, struct hostent **result, int *h_errnop)
85658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
85750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	*result = android_gethostbyaddrfornetcontext_proxy_internal(
85850178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz		addr, len, af, hp, buf, buflen, h_errnop, &NETCONTEXT_UNSET);
859bb7d9fb5d438c7477c404f97e07e145d49335947Elliott Hughes	return h_errno_to_result(h_errnop);
86058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
8619773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
8629773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughesstatic struct hostent *
86350178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzandroid_gethostbyaddrfornetcontext_real(const void *addr, socklen_t len, int af, struct hostent *hp,
86450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz                                 char *buf, size_t buflen, int *he,
86550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz				 const struct android_net_context *netcontext)
86658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const u_char *uaddr = (const u_char *)addr;
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	socklen_t size;
86958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr info;
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	static const ns_dtab dtab[] = {
87158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_FILES_CB(_hf_gethtbyaddr, NULL)
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		{ NSSRC_DNS, _dns_gethtbyaddr, NULL },	/* force -DHESIOD */
87358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_NIS_CB(_yp_gethtbyaddr, NULL)
87458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		NS_NULL_CB
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	};
8761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
87758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(addr != NULL);
8781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8793e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
8803e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	    (IN6_IS_ADDR_LINKLOCAL((const struct in6_addr *)addr) ||
8813e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	     IN6_IS_ADDR_SITELOCAL((const struct in6_addr *)addr))) {
88258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = HOST_NOT_FOUND;
8831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8853e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	if (af == AF_INET6 && len == NS_IN6ADDRSZ &&
8863e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	    (IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)addr) ||
8873e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes	     IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)addr))) {
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* Unmap. */
8893e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes		uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
8903e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes		addr = uaddr;
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		af = AF_INET;
8923e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes		len = NS_INADDRSZ;
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
8941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	switch (af) {
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
8963e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes		size = NS_INADDRSZ;
8971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
8993e5f0c9849bf09ad9a5b1999430aec796276d9f6Elliott Hughes		size = NS_IN6ADDRSZ;
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
9021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EAFNOSUPPORT;
90358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = NETDB_INTERNAL;
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (size != len) {
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EINVAL;
90858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = NETDB_INTERNAL;
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
91158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.hp = hp;
91258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.buf = buf;
91358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.buflen = buflen;
91458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info.he = he;
91558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
91658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (nsdispatch(&info, dtab, NSDB_HOSTS, "gethostbyaddr",
91750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	    default_dns_files, uaddr, len, af, netcontext) != NS_SUCCESS)
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
91958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return hp;
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
92358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistatic struct hostent*
92450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzandroid_gethostbyaddrfornetcontext_proxy_internal(const void* addr, socklen_t len, int af,
92558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui                             struct hostent *hp, char *hbuf, size_t hbuflen, int *he,
92650178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz                             const struct android_net_context *netcontext)
92758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
9289773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	FILE* proxy = android_open_proxy();
9299773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (proxy == NULL) {
9309773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		// Either we're not supposed to be using the proxy or the proxy is unavailable.
93150178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz		return android_gethostbyaddrfornetcontext_real(addr,len, af, hp, hbuf, hbuflen, he, netcontext);
9329773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	}
9339773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
9349773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	char buf[INET6_ADDRSTRLEN];  //big enough for IPv4 and IPv6
9359773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	const char * addrStr = inet_ntop(af, addr, buf, sizeof(buf));
9369773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (addrStr == NULL) {
9379773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		fclose(proxy);
9389773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
9399773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	}
9409773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
94150178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	unsigned netid = __netdClientDispatch.netIdForResolv(netcontext->app_netid);
9429773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
9439773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (fprintf(proxy, "gethostbyaddr %s %d %d %u",
9449773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes			addrStr, len, af, netid) < 0) {
9459773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		fclose(proxy);
9469773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
9479773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	}
9489773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
9499773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
9509773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		fclose(proxy);
9519773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes		return NULL;
9529773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	}
9539773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
95458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *result = android_read_hostent(proxy, hp, hbuf, hbuflen, he);
9559773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	fclose(proxy);
9569773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes	return result;
9579773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes}
9589773fa3ffd7c2d1de2431b8ea1eb8043e8959fcbElliott Hughes
95958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent*
96058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinetbsd_gethostent_r(FILE *hf, struct hostent *hent, char *buf, size_t buflen, int *he)
961c63e59039d28c352e3053bb81319e960c392dbd4Mattias Falk{
96258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *p, *name;
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *cp, **q;
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int af, len;
96558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t anum;
96658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char **aliases;
96758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t maxaliases;
96858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct in6_addr host_addr;
9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
97058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (hf == NULL) {
97158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*he = NETDB_INTERNAL;
97258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		errno = EINVAL;
9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NULL;
9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
97558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	p = NULL;
97658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	setup(aliases, maxaliases);
97758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
97858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* Allocate a new space to read file lines like upstream does.
97958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 * To keep reentrancy we cannot use __res_get_static()->hostbuf here,
98058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 * as the buffer may be used to store content for a previous hostent
98158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 * returned by non-reentrant functions like gethostbyname().
98258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 */
98358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	const size_t line_buf_size = sizeof(__res_get_static()->hostbuf);
98458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if ((p = malloc(line_buf_size)) == NULL) {
98558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  goto nospc;
9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
98758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	for (;;) {
98858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (!fgets(p, line_buf_size, hf)) {
98958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			free(p);
99058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			free(aliases);
99158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			*he = HOST_NOT_FOUND;
9921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NULL;
99358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui    		}
99458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (*p == '#') {
9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
99758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (!(cp = strpbrk(p, "#\n"))) {
9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;
9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
100058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*cp = '\0';
100158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (!(cp = strpbrk(p, " \t")))
100258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			continue;
100358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*cp++ = '\0';
100458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (inet_pton(AF_INET6, p, &host_addr) > 0) {
100558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			af = AF_INET6;
100658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			len = NS_IN6ADDRSZ;
100758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		} else {
100858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (inet_pton(AF_INET, p, &host_addr) <= 0)
100958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				continue;
10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
101158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			res_state res = __res_get_state();
101258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (res == NULL)
101358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto nospc;
101458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (res->options & RES_USE_INET6) {
101558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				map_v4v6_address(buf, buf);
101658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				af = AF_INET6;
101758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				len = NS_IN6ADDRSZ;
101858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			} else {
101958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				af = AF_INET;
102058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				len = NS_INADDRSZ;
10211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
102258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			__res_put_state(res);
10231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
102558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		/* if this is not something we're looking for, skip it. */
102658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (hent->h_addrtype != 0 && hent->h_addrtype != af)
102758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			continue;
102858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (hent->h_length != 0 && hent->h_length != len)
102958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			continue;
10301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
103158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		while (*cp == ' ' || *cp == '\t')
103258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			cp++;
103358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if ((cp = strpbrk(name = cp, " \t")) != NULL)
103458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			*cp++ = '\0';
103558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		q = aliases;
103658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		while (cp && *cp) {
103758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (*cp == ' ' || *cp == '\t') {
103858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				cp++;
103958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				continue;
104058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			}
104158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			addalias(q, cp, aliases, maxaliases);
104258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if ((cp = strpbrk(cp, " \t")) != NULL)
104358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				*cp++ = '\0';
104458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
104558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
104758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_length = len;
104858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_addrtype = af;
104958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hent->h_addr_list, 1, buf, buflen);
105058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	anum = (size_t)(q - aliases);
105158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hent->h_aliases, anum, buf, buflen);
105258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_COPY(hent->h_addr_list[0], &host_addr, hent->h_length, buf,
105358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    buflen);
105458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_addr_list[1] = NULL;
105558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
105658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_SCOPY(hent->h_name, name, buf, buflen);
105758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	for (size_t i = 0; i < anum; i++)
105858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		HENT_SCOPY(hent->h_aliases[i], aliases[i], buf, buflen);
105958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hent->h_aliases[anum] = NULL;
106058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
106158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_SUCCESS;
106258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(p);
106358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
106458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hent;
106558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
106658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(p);
106758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
106858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	errno = ENOSPC;
106958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*he = NETDB_INTERNAL;
107058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NULL;
10711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
10721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
10741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmap_v4v6_address(const char *src, char *dst)
10751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_char *p = (u_char *)dst;
107758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char tmp[NS_INADDRSZ];
10781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int i;
10791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
108058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(src != NULL);
108158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(dst != NULL);
10821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Stash a temporary copy so our caller can update in place. */
108458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	(void)memcpy(tmp, src, NS_INADDRSZ);
10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Mark this ipv6 addr as a mapped ipv4. */
10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (i = 0; i < 10; i++)
10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*p++ = 0x00;
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*p++ = 0xff;
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*p++ = 0xff;
10901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* Retrieve the saved copy and we're done. */
109158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	(void)memcpy(p, tmp, NS_INADDRSZ);
10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectmap_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **ap;
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
109958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(hp != NULL);
110058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(bpp != NULL);
110158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(ep != NULL);
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
110358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (hp->h_addrtype != AF_INET || hp->h_length != NS_INADDRSZ)
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return;
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	hp->h_addrtype = AF_INET6;
110658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_length = NS_IN6ADDRSZ;
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (ap = hp->h_addr_list; *ap; ap++) {
110858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		int i = (int)(sizeof(align) -
110958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		    (size_t)((u_long)*bpp % sizeof(align)));
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
111158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (ep - *bpp < (i + NS_IN6ADDRSZ)) {
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* Out of memory.  Truncate address list here.  XXX */
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*ap = NULL;
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return;
11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*bpp += i;
11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		map_v4v6_address(*ap, *bpp);
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*ap = *bpp;
111958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*bpp += NS_IN6ADDRSZ;
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
11221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic void
11241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectaddrsort(char **ap, int num, res_state res)
11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int i, j;
11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char **p;
11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	short aval[MAXADDRS];
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int needsort = 0;
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
113158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(ap != NULL);
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	p = ap;
11341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (i = 0; i < num; i++, p++) {
11351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    for (j = 0 ; (unsigned)j < res->nsort; j++)
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (res->sort_list[j].addr.s_addr ==
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    (((struct in_addr *)(void *)(*p))->s_addr &
11381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    res->sort_list[j].mask))
11391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
11401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    aval[i] = j;
11411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    if (needsort == 0 && i > 0 && j < aval[i-1])
11421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		needsort = i;
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (!needsort)
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    return;
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (needsort < num) {
11481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    for (j = needsort - 1; j >= 0; j--) {
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (aval[j] > aval[j+1]) {
11501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    char *hp;
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    i = aval[j];
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    aval[j] = aval[j+1];
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    aval[j+1] = i;
11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    hp = ap[j];
11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ap[j] = ap[j+1];
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    ap[j+1] = hp;
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    break;
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    needsort++;
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/
1167e5c35e075fad5b5c143971c4401a360f6eaf5470Jim Huangstatic int
11681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_dns_gethtbyname(void *rv, void *cb_data, va_list ap)
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	querybuf *buf;
11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n, type;
11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct hostent *hp;
11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const char *name;
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state res;
117558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr *info = rv;
11761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
117758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(rv != NULL);
11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	name = va_arg(ap, char *);
118058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* NOSTRICT skip string len */(void)va_arg(ap, int);
118158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info->hp->h_addrtype = va_arg(ap, int);
11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
118358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	switch (info->hp->h_addrtype) {
11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
118558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		info->hp->h_length = NS_INADDRSZ;
11861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		type = T_A;
11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
118958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		info->hp->h_length = NS_IN6ADDRSZ;
11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		type = T_AAAA;
11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_UNAVAIL;
11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	buf = malloc(sizeof(*buf));
11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (buf == NULL) {
119758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*info->he = NETDB_INTERNAL;
11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res = __res_get_state();
12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (res == NULL) {
12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		free(buf);
12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
120558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	n = res_nsearch(res, name, C_IN, type, buf->buf, (int)sizeof(buf->buf));
12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n < 0) {
12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		free(buf);
120858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		debugprintf("res_nsearch failed (%d)\n", res, n);
12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		__res_put_state(res);
12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
121258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp = getanswer(buf, n, name, type, res, info->hp, info->buf,
121358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    info->buflen, info->he);
12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	free(buf);
12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	__res_put_state(res);
12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp == NULL)
12177069256495ef8a38a16a39a8570800e9e5290004Yabin Cui		switch (*info->he) {
12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case HOST_NOT_FOUND:
12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_NOTFOUND;
12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TRY_AGAIN:
12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_TRYAGAIN;
12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_UNAVAIL;
12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return NS_SUCCESS;
12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*ARGSUSED*/
1229e5c35e075fad5b5c143971c4401a360f6eaf5470Jim Huangstatic int
12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_dns_gethtbyaddr(void *rv, void	*cb_data, va_list ap)
12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char qbuf[MAXDNAME + 1], *qp, *ep;
12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int n;
12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	querybuf *buf;
12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct hostent *hp;
12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	const unsigned char *uaddr;
123758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int advance;
12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res_state res;
123958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *bf;
124058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t blen;
124158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr *info = rv;
124250178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	const struct android_net_context *netcontext;
12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
124458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(rv != NULL);
12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uaddr = va_arg(ap, unsigned char *);
124758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info->hp->h_length = va_arg(ap, int);
124858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	info->hp->h_addrtype = va_arg(ap, int);
124950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	netcontext = va_arg(ap, const struct android_net_context *);
12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
125158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	switch (info->hp->h_addrtype) {
12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET:
12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		(void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa",
12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    (uaddr[3] & 0xff), (uaddr[2] & 0xff),
12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    (uaddr[1] & 0xff), (uaddr[0] & 0xff));
12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	case AF_INET6:
12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		qp = qbuf;
12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ep = qbuf + sizeof(qbuf) - 1;
126158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			advance = snprintf(qp, (size_t)(ep - qp), "%x.%x.",
12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    uaddr[n] & 0xf,
12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			    ((unsigned int)uaddr[n] >> 4) & 0xf);
12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (advance > 0 && qp + advance < ep)
12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				qp += advance;
12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else {
126858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				*info->he = NETDB_INTERNAL;
12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				return NS_NOTFOUND;
12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
12721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (strlcat(qbuf, "ip6.arpa", sizeof(qbuf)) >= sizeof(qbuf)) {
127358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			*info->he = NETDB_INTERNAL;
12741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_NOTFOUND;
12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		break;
12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	default:
127858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NS_UNAVAIL;
12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	buf = malloc(sizeof(*buf));
12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (buf == NULL) {
128358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*info->he = NETDB_INTERNAL;
12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	res = __res_get_state();
12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (res == NULL) {
12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		free(buf);
12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
129190a83beb4dd3a70aeb512a786e9a79bbd641f4deBen Schwartz	res_setnetcontext(res, netcontext);
129258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, (int)sizeof(buf->buf));
12931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (n < 0) {
12941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		free(buf);
129558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		debugprintf("res_nquery failed (%d)\n", res, n);
12961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		__res_put_state(res);
12971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return NS_NOTFOUND;
12981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
129958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp = getanswer(buf, n, qbuf, T_PTR, res, info->hp, info->buf,
130058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    info->buflen, info->he);
13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	free(buf);
13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (hp == NULL) {
13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		__res_put_state(res);
130458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		switch (*info->he) {
13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case HOST_NOT_FOUND:
13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_NOTFOUND;
13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TRY_AGAIN:
13081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_TRYAGAIN;
13091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:
13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			return NS_UNAVAIL;
13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
131358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
131458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	bf = (void *)(hp->h_addr_list + 2);
131558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	blen = (size_t)(bf - info->buf);
131658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (blen + info->hp->h_length > info->buflen)
131758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nospc;
131858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list[0] = bf;
131958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list[1] = NULL;
132058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	(void)memcpy(bf, uaddr, (size_t)info->hp->h_length);
132158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (info->hp->h_addrtype == AF_INET && (res->options & RES_USE_INET6)) {
132258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (blen + NS_IN6ADDRSZ > info->buflen)
132358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto nospc;
132458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map_v4v6_address(bf, bf);
13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		hp->h_addrtype = AF_INET6;
132658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp->h_length = NS_IN6ADDRSZ;
13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	__res_put_state(res);
133058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*info->he = NETDB_SUCCESS;
133158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NS_SUCCESS;
133258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
13337069256495ef8a38a16a39a8570800e9e5290004Yabin Cui	errno = ENOSPC;
133458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*info->he = NETDB_INTERNAL;
133558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NS_UNAVAIL;
133658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
133758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
133858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#ifdef YP
133958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/*ARGSUSED*/
134058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistatic struct hostent *
134158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui_yp_hostent(char *line, int af, struct getnamaddr *info)
134258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
134358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct in6_addr host_addrs[MAXADDRS];
134458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char **aliases;
134558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t maxaliases;
134658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *p = line;
134758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *cp, **q, *ptr;
134858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t len, anum, i;
134958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int addrok;
135058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int more;
135158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	size_t naddrs;
135258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *hp = info->hp;
135358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
135458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(line != NULL);
135558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
135658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_name = NULL;
135758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addrtype = af;
135858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	switch (af) {
135958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	case AF_INET:
136058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp->h_length = NS_INADDRSZ;
136158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
136258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	case AF_INET6:
136358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp->h_length = NS_IN6ADDRSZ;
136458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
136558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	default:
136658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NULL;
136758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
136858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	setup(aliases, maxaliases);
136958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	naddrs = 0;
137058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	q = aliases;
137158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
137258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinextline:
137358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* check for host_addrs overflow */
137458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (naddrs >= __arraycount(host_addrs))
137558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto done;
137658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
137758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	more = 0;
137858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	cp = strpbrk(p, " \t");
137958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (cp == NULL)
138058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto done;
138158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*cp++ = '\0';
138258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
138358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* p has should have an address */
138458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	addrok = inet_pton(af, p, &host_addrs[naddrs]);
138558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (addrok != 1) {
138658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		/* skip to the next line */
138758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		while (cp && *cp) {
138858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			if (*cp == '\n') {
138958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				cp++;
139058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui				goto nextline;
139158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			}
139258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			cp++;
139358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
139458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto done;
139558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
139658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	naddrs++;
139758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
139858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	while (*cp == ' ' || *cp == '\t')
139958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		cp++;
140058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	p = cp;
140158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	cp = strpbrk(p, " \t\n");
140258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (cp != NULL) {
140358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (*cp == '\n')
140458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			more = 1;
140558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*cp++ = '\0';
140658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
140758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (!hp->h_name)
140858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp->h_name = p;
140958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	else if (strcmp(hp->h_name, p) == 0)
141058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		;
141158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	else
141258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		addalias(q, p, aliases, maxaliases);
141358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	p = cp;
141458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (more)
141558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		goto nextline;
141658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
141758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	while (cp && *cp) {
141858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (*cp == ' ' || *cp == '\t') {
141958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			cp++;
142058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			continue;
142158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
142258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (*cp == '\n') {
142358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			cp++;
142458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			goto nextline;
142558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		}
142658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		addalias(q, cp, aliases, maxaliases);
142758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		cp = strpbrk(cp, " \t");
142858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (cp != NULL)
142958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			*cp++ = '\0';
143058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
143158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
143258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuidone:
143358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (hp->h_name == NULL) {
143458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		free(aliases);
143558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NULL;
143658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
143758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
143858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	ptr = info->buf;
143958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	len = info->buflen;
144058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
144158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	anum = (size_t)(q - aliases);
144258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hp->h_addr_list, naddrs, ptr, len);
144358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_ARRAY(hp->h_aliases, anum, ptr, len);
144458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
144558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	for (i = 0; i < naddrs; i++)
144658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		HENT_COPY(hp->h_addr_list[i], &host_addrs[i], hp->h_length,
144758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		    ptr, len);
144858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_addr_list[naddrs] = NULL;
144958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
145058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	HENT_SCOPY(hp->h_name, hp->h_name, ptr, len);
145158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
145258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	for (i = 0; i < anum; i++)
145358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		HENT_SCOPY(hp->h_aliases[i], aliases[i], ptr, len);
145458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp->h_aliases[anum] = NULL;
145558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
145658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
145758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hp;
145858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuinospc:
145958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(aliases);
146058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	*info->he = NETDB_INTERNAL;
146158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	errno = ENOSPC;
146258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NULL;
146358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
146458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
146558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/*ARGSUSED*/
146658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiint
146758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui_yp_gethtbyaddr(void *rv, void *cb_data, va_list ap)
146858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
146958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *hp = NULL;
147058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *ypcurrent;
147158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int ypcurrentlen, r;
147258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char name[INET6_ADDRSTRLEN];	/* XXX enough? */
147358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	const unsigned char *uaddr;
147458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int af;
147558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	const char *map;
147658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr *info = rv;
147758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
147858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(rv != NULL);
147958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
148058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	uaddr = va_arg(ap, unsigned char *);
148158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* NOSTRICT skip len */(void)va_arg(ap, int);
148258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	af = va_arg(ap, int);
148358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
148458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (!__ypdomain) {
148558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (_yp_check(&__ypdomain) == 0)
148658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			return NS_UNAVAIL;
148758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
148858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/*
148958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 * XXX unfortunately, we cannot support IPv6 extended scoped address
149058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 * notation here.  gethostbyaddr() is not scope-aware.  too bad.
149158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	 */
149258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (inet_ntop(af, uaddr, name, (socklen_t)sizeof(name)) == NULL)
149358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NS_UNAVAIL;
149458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	switch (af) {
149558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	case AF_INET:
149658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map = "hosts.byaddr";
149758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
149858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	default:
149958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map = "ipnodes.byaddr";
150058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
150158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
150258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	ypcurrent = NULL;
150358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	r = yp_match(__ypdomain, map, name,
150458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		(int)strlen(name), &ypcurrent, &ypcurrentlen);
150558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (r == 0)
150658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp = _yp_hostent(ypcurrent, af, info);
150758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	else
150858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp = NULL;
150958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(ypcurrent);
151058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (hp == NULL) {
151158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*info->he = HOST_NOT_FOUND;
151258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NS_NOTFOUND;
151358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
151458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return NS_SUCCESS;
151558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
151658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
151758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/*ARGSUSED*/
151858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiint
151958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui_yp_gethtbyname(void *rv, void *cb_data, va_list ap)
152058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
152158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *hp;
152258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	char *ypcurrent;
152358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int ypcurrentlen, r;
152458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	const char *name;
152558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	int af;
152658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	const char *map;
152758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct getnamaddr *info = rv;
152858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
152958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	_DIAGASSERT(rv != NULL);
153058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
153158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	name = va_arg(ap, char *);
153258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	/* NOSTRICT skip string len */(void)va_arg(ap, int);
153358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	af = va_arg(ap, int);
153458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
153558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (!__ypdomain) {
153658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		if (_yp_check(&__ypdomain) == 0)
153758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui			return NS_UNAVAIL;
153858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
153958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	switch (af) {
154058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	case AF_INET:
154158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map = "hosts.byname";
154258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
154358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	default:
154458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		map = "ipnodes.byname";
154558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		break;
154658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
154758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	ypcurrent = NULL;
154858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	r = yp_match(__ypdomain, map, name,
154958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		(int)strlen(name), &ypcurrent, &ypcurrentlen);
155058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (r == 0)
155158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp = _yp_hostent(ypcurrent, af, info);
155258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	else
155358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		hp = NULL;
155458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	free(ypcurrent);
155558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (hp == NULL) {
155658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		*info->he = HOST_NOT_FOUND;
155758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NS_NOTFOUND;
155858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
15591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return NS_SUCCESS;
15601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
156158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui#endif
156258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
156358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui/*
156458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui * Non-reentrant versions.
156558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui */
156658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
156758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
156858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyname(const char *name)
156958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
157058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *result = NULL;
157158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
157258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
157358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	gethostbyname_r(name, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
157458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return result;
157558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
157658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
157758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
157858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyname2(const char *name, int af)
157958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
158058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *result = NULL;
158158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
158258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
158358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	gethostbyname2_r(name, af, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &result, &h_errno);
158458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return result;
158558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
158658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
158750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz// android_gethostby*fornet can be called in two different contexts.
158850178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz//  - In the proxy client context (proxy != NULL), |netid| is |app_netid|.
158950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz//  - In the proxy listener context (proxy == NULL), |netid| is |dns_netid|.
159050178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz// The netcontext is constructed before checking which context we are in.
159150178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz// Therefore, we have to populate both fields, and rely on the downstream code to check whether
159250178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz// |proxy == NULL|, and use that info to query the field that matches the caller's intent.
159350178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzstatic struct android_net_context make_context(unsigned netid, unsigned mark) {
159450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	struct android_net_context netcontext = NETCONTEXT_UNSET;
159550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	netcontext.app_netid = netid;
159650178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	netcontext.app_mark = mark;
159750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	netcontext.dns_netid = netid;
159850178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	netcontext.dns_mark = mark;
159950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	return netcontext;
160050178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz}
160150178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz
160258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
160358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiandroid_gethostbynamefornet(const char *name, int af, unsigned netid, unsigned mark)
160458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
1605dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	const struct android_net_context netcontext = make_context(netid, mark);
1606dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	return android_gethostbynamefornetcontext(name, af, &netcontext);
1607dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz}
1608dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz
1609dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartzstruct hostent *
1610dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartzandroid_gethostbynamefornetcontext(const char *name, int af,
1611dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	const struct android_net_context *netcontext)
1612dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz{
161358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	struct hostent *hp;
161458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	res_state res = __res_get_state();
161558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (res == NULL)
161658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui		return NULL;
161758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
161858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	hp = gethostbyname_internal(name, af, res, &rs->host, rs->hostbuf, sizeof(rs->hostbuf),
1619dd878fe129bb128fb28577c6ccc3fbf04addf898Ben Schwartz	                            &h_errno, netcontext);
162058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	__res_put_state(res);
162158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return hp;
162258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
162358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
162458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
162558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostbyaddr(const void *addr, socklen_t len, int af)
162658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
162750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	return android_gethostbyaddrfornetcontext_proxy(addr, len, af, &NETCONTEXT_UNSET);
162858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
162958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
163058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
163158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuiandroid_gethostbyaddrfornet(const void *addr, socklen_t len, int af, unsigned netid, unsigned mark)
163258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
163350178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	const struct android_net_context netcontext = make_context(netid, mark);
163450178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	return android_gethostbyaddrfornetcontext(addr, len, af, &netcontext);
163550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz}
163650178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz
163750178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzstruct hostent *
163850178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzandroid_gethostbyaddrfornetcontext(const void *addr, socklen_t len, int af,
163950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	const struct android_net_context *netcontext)
164050178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz{
164150178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	return android_gethostbyaddrfornetcontext_proxy(addr, len, af, netcontext);
164258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
164358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
164458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui__LIBC_HIDDEN__ struct hostent*
164550178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartzandroid_gethostbyaddrfornetcontext_proxy(const void* addr, socklen_t len, int af,
164650178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz                                  const struct android_net_context *netcontext)
164758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
164858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	res_static rs = __res_get_static(); /* Use res_static to provide thread-safety. */
164950178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz	return android_gethostbyaddrfornetcontext_proxy_internal(addr, len, af, &rs->host, rs->hostbuf,
165050178056f7930a33cb1d0a45c76b3dfbe17c5506Ben Schwartz                                                    sizeof(rs->hostbuf), &h_errno, netcontext);
165158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
165258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui
165358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuistruct hostent *
165458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cuigethostent(void)
165558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui{
165658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui  res_static  rs = __res_get_static();
165758d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	if (!rs->hostf) {
165858d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  sethostent_r(&rs->hostf);
165958d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  if (!rs->hostf) {
166058d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    h_errno = NETDB_INTERNAL;
166158d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	    return NULL;
166258d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	  }
166358d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	}
166458d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	memset(&rs->host, 0, sizeof(rs->host));
166558d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui	return netbsd_gethostent_r(rs->hostf, &rs->host, rs->hostbuf, sizeof(rs->hostbuf), &h_errno);
166658d33a51f336d6823ef1ec915949a5884699ff5fYabin Cui}
1667