1/*	$NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $	*/
2/*	$KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $	*/
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked.
36 * - Return values.  There are nonstandard return values defined and used
37 *   in the source code.  This is because RFC2553 is silent about which error
38 *   code must be returned for which situation.
39 * - IPv4 classful (shortened) form.  RFC2553 is silent about it.  XNET 5.2
40 *   says to use inet_aton() to convert IPv4 numeric to binary (alows
41 *   classful form as a result).
42 *   current code - disallow classful form for IPv4 (due to use of inet_pton).
43 * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
44 *   invalid.
45 *   current code - SEGV on freeaddrinfo(NULL)
46 * Note:
47 * - We use getipnodebyname() just for thread-safeness.  There's no intent
48 *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 *   getipnodebyname().
50 * - The code filters out AFs that are not supported by the kernel,
51 *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
52 *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 *   in ai_flags?
54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
55 *   (1) what should we do against numeric hostname (2) what should we do
56 *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
57 *   non-loopback address configured?  global address configured?
58 * - To avoid search order issue, we have a big amount of code duplicate
59 *   from gethnamaddr.c and some other places.  The issues that there's no
60 *   lower layer function to lookup "IPv4 or IPv6" record.  Calling
61 *   gethostbyname2 from getaddrinfo will end up in wrong search order, as
62 *   follows:
63 *	- The code makes use of following calls when asked to resolver with
64 *	  ai_family  = PF_UNSPEC:
65 *		getipnodebyname(host, AF_INET6);
66 *		getipnodebyname(host, AF_INET);
67 *	  This will result in the following queries if the node is configure to
68 *	  prefer /etc/hosts than DNS:
69 *		lookup /etc/hosts for IPv6 address
70 *		lookup DNS for IPv6 address
71 *		lookup /etc/hosts for IPv4 address
72 *		lookup DNS for IPv4 address
73 *	  which may not meet people's requirement.
74 *	  The right thing to happen is to have underlying layer which does
75 *	  PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
76 *	  This would result in a bit of code duplicate with _dns_ghbyname() and
77 *	  friends.
78 */
79
80#include <fcntl.h>
81#include <sys/cdefs.h>
82#include <sys/types.h>
83#include <sys/stat.h>
84#include <sys/param.h>
85#include <sys/socket.h>
86#include <sys/un.h>
87#include <net/if.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include "arpa_nameser.h"
91#include <assert.h>
92#include <ctype.h>
93#include <errno.h>
94#include <netdb.h>
95#include "resolv_private.h"
96#include <stddef.h>
97#include <stdio.h>
98#include <stdlib.h>
99#include <string.h>
100#include <strings.h>
101#include <unistd.h>
102
103#include <syslog.h>
104#include <stdarg.h>
105#include "nsswitch.h"
106
107#ifdef ANDROID_CHANGES
108#include <sys/system_properties.h>
109#endif /* ANDROID_CHANGES */
110
111typedef union sockaddr_union {
112    struct sockaddr     generic;
113    struct sockaddr_in  in;
114    struct sockaddr_in6 in6;
115} sockaddr_union;
116
117#define SUCCESS 0
118#define ANY 0
119#define YES 1
120#define NO  0
121
122static const char in_addrany[] = { 0, 0, 0, 0 };
123static const char in_loopback[] = { 127, 0, 0, 1 };
124#ifdef INET6
125static const char in6_addrany[] = {
126	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
127};
128static const char in6_loopback[] = {
129	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
130};
131#endif
132
133// This should be synchronized to ResponseCode.h
134static const int DnsProxyQueryResult = 222;
135
136static const struct afd {
137	int a_af;
138	int a_addrlen;
139	int a_socklen;
140	int a_off;
141	const char *a_addrany;
142	const char *a_loopback;
143	int a_scoped;
144} afdl [] = {
145#ifdef INET6
146	{PF_INET6, sizeof(struct in6_addr),
147	 sizeof(struct sockaddr_in6),
148	 offsetof(struct sockaddr_in6, sin6_addr),
149	 in6_addrany, in6_loopback, 1},
150#endif
151	{PF_INET, sizeof(struct in_addr),
152	 sizeof(struct sockaddr_in),
153	 offsetof(struct sockaddr_in, sin_addr),
154	 in_addrany, in_loopback, 0},
155	{0, 0, 0, 0, NULL, NULL, 0},
156};
157
158struct explore {
159	int e_af;
160	int e_socktype;
161	int e_protocol;
162	const char *e_protostr;
163	int e_wild;
164#define WILD_AF(ex)		((ex)->e_wild & 0x01)
165#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
166#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
167};
168
169static const struct explore explore[] = {
170#if 0
171	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
172#endif
173#ifdef INET6
174	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
175	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
176	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
177#endif
178	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
179	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
180	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
181	{ PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
182	{ PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
183	{ PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
184	{ -1, 0, 0, NULL, 0 },
185};
186
187#ifdef INET6
188#define PTON_MAX	16
189#else
190#define PTON_MAX	4
191#endif
192
193static const ns_src default_dns_files[] = {
194	{ NSSRC_FILES, 	NS_SUCCESS },
195	{ NSSRC_DNS, 	NS_SUCCESS },
196	{ 0, 0 }
197};
198
199#define MAXPACKET	(64*1024)
200
201typedef union {
202	HEADER hdr;
203	u_char buf[MAXPACKET];
204} querybuf;
205
206struct res_target {
207	struct res_target *next;
208	const char *name;	/* domain name */
209	int qclass, qtype;	/* class and type of query */
210	u_char *answer;		/* buffer to put answer */
211	int anslen;		/* size of answer buffer */
212	int n;			/* result length */
213};
214
215static int str2number(const char *);
216static int explore_fqdn(const struct addrinfo *, const char *,
217	const char *, struct addrinfo **);
218static int explore_null(const struct addrinfo *,
219	const char *, struct addrinfo **);
220static int explore_numeric(const struct addrinfo *, const char *,
221	const char *, struct addrinfo **, const char *);
222static int explore_numeric_scope(const struct addrinfo *, const char *,
223	const char *, struct addrinfo **);
224static int get_canonname(const struct addrinfo *,
225	struct addrinfo *, const char *);
226static struct addrinfo *get_ai(const struct addrinfo *,
227	const struct afd *, const char *);
228static int get_portmatch(const struct addrinfo *, const char *);
229static int get_port(const struct addrinfo *, const char *, int);
230static const struct afd *find_afd(int);
231#ifdef INET6
232static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
233#endif
234
235static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
236	const struct addrinfo *);
237static int _dns_getaddrinfo(void *, void *, va_list);
238static void _sethtent(FILE **);
239static void _endhtent(FILE **);
240static struct addrinfo *_gethtent(FILE **, const char *,
241    const struct addrinfo *);
242static int _files_getaddrinfo(void *, void *, va_list);
243
244static int res_queryN(const char *, struct res_target *, res_state);
245static int res_searchN(const char *, struct res_target *, res_state);
246static int res_querydomainN(const char *, const char *,
247	struct res_target *, res_state);
248
249static const char * const ai_errlist[] = {
250	"Success",
251	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
252	"Temporary failure in name resolution",		/* EAI_AGAIN      */
253	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
254	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
255	"ai_family not supported",			/* EAI_FAMILY     */
256	"Memory allocation failure", 			/* EAI_MEMORY     */
257	"No address associated with hostname", 		/* EAI_NODATA     */
258	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
259	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
260	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
261	"System error returned in errno", 		/* EAI_SYSTEM     */
262	"Invalid value for hints",			/* EAI_BADHINTS	  */
263	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
264	"Argument buffer overflow",			/* EAI_OVERFLOW   */
265	"Unknown error", 				/* EAI_MAX        */
266};
267
268/* XXX macros that make external reference is BAD. */
269
270#define GET_AI(ai, afd, addr) 					\
271do { 								\
272	/* external reference: pai, error, and label free */ 	\
273	(ai) = get_ai(pai, (afd), (addr)); 			\
274	if ((ai) == NULL) { 					\
275		error = EAI_MEMORY; 				\
276		goto free; 					\
277	} 							\
278} while (/*CONSTCOND*/0)
279
280#define GET_PORT(ai, serv) 					\
281do { 								\
282	/* external reference: error and label free */ 		\
283	error = get_port((ai), (serv), 0); 			\
284	if (error != 0) 					\
285		goto free; 					\
286} while (/*CONSTCOND*/0)
287
288#define GET_CANONNAME(ai, str) 					\
289do { 								\
290	/* external reference: pai, error and label free */ 	\
291	error = get_canonname(pai, (ai), (str)); 		\
292	if (error != 0) 					\
293		goto free; 					\
294} while (/*CONSTCOND*/0)
295
296#define ERR(err) 						\
297do { 								\
298	/* external reference: error, and label bad */ 		\
299	error = (err); 						\
300	goto bad; 						\
301	/*NOTREACHED*/ 						\
302} while (/*CONSTCOND*/0)
303
304#define MATCH_FAMILY(x, y, w) 						\
305	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || 	\
306	    (y) == PF_UNSPEC)))
307#define MATCH(x, y, w) 							\
308	((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
309
310const char *
311gai_strerror(int ecode)
312{
313	if (ecode < 0 || ecode > EAI_MAX)
314		ecode = EAI_MAX;
315	return ai_errlist[ecode];
316}
317
318void
319freeaddrinfo(struct addrinfo *ai)
320{
321	struct addrinfo *next;
322
323	assert(ai != NULL);
324
325	do {
326		next = ai->ai_next;
327		if (ai->ai_canonname)
328			free(ai->ai_canonname);
329		/* no need to free(ai->ai_addr) */
330		free(ai);
331		ai = next;
332	} while (ai);
333}
334
335static int
336str2number(const char *p)
337{
338	char *ep;
339	unsigned long v;
340
341	assert(p != NULL);
342
343	if (*p == '\0')
344		return -1;
345	ep = NULL;
346	errno = 0;
347	v = strtoul(p, &ep, 10);
348	if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
349		return v;
350	else
351		return -1;
352}
353
354/*
355 * Connect a UDP socket to a given unicast address. This will cause no network
356 * traffic, but will fail fast if the system has no or limited reachability to
357 * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
358 */
359static int
360_test_connect(int pf, struct sockaddr *addr, size_t addrlen) {
361	int s = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
362	if (s < 0)
363		return 0;
364	int ret;
365	do {
366		ret = connect(s, addr, addrlen);
367	} while (ret < 0 && errno == EINTR);
368	int success = (ret == 0);
369	do {
370		ret = close(s);
371	} while (ret < 0 && errno == EINTR);
372	return success;
373}
374
375/*
376 * The following functions determine whether IPv4 or IPv6 connectivity is
377 * available in order to implement AI_ADDRCONFIG.
378 *
379 * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is
380 * available, but whether addresses of the specified family are "configured
381 * on the local system". However, bionic doesn't currently support getifaddrs,
382 * so checking for connectivity is the next best thing.
383 */
384static int
385_have_ipv6() {
386	static const struct sockaddr_in6 sin6_test = {
387		.sin6_family = AF_INET6,
388		.sin6_addr.s6_addr = {  // 2000::
389			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
390		};
391        sockaddr_union addr = { .in6 = sin6_test };
392	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6));
393}
394
395static int
396_have_ipv4() {
397	static const struct sockaddr_in sin_test = {
398		.sin_family = AF_INET,
399		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
400	};
401        sockaddr_union addr = { .in = sin_test };
402        return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
403}
404
405// Returns 0 on success, else returns non-zero on error (in which case
406// getaddrinfo should continue as normal)
407static int
408android_getaddrinfo_proxy(
409    const char *hostname, const char *servname,
410    const struct addrinfo *hints, struct addrinfo **res)
411{
412	int sock;
413	const int one = 1;
414	struct sockaddr_un proxy_addr;
415	const char* cache_mode = getenv("ANDROID_DNS_MODE");
416	FILE* proxy = NULL;
417	int success = 0;
418
419	// Clear this at start, as we use its non-NULLness later (in the
420	// error path) to decide if we have to free up any memory we
421	// allocated in the process (before failing).
422	*res = NULL;
423
424	if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
425		// Don't use the proxy in local mode.  This is used by the
426		// proxy itself.
427		return -1;
428	}
429
430	// Temporary cautious hack to disable the DNS proxy for processes
431	// requesting special treatment.  Ideally the DNS proxy should
432	// accomodate these apps, though.
433	char propname[PROP_NAME_MAX];
434	char propvalue[PROP_VALUE_MAX];
435	snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
436	if (__system_property_get(propname, propvalue) > 0) {
437		return -1;
438	}
439
440	// Bogus things we can't serialize.  Don't use the proxy.
441	if ((hostname != NULL &&
442	     strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) ||
443	    (servname != NULL &&
444	     strcspn(servname, " \n\r\t^'\"") != strlen(servname))) {
445		return -1;
446	}
447
448	sock = socket(AF_UNIX, SOCK_STREAM, 0);
449	if (sock < 0) {
450		return -1;
451	}
452
453	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
454	memset(&proxy_addr, 0, sizeof(proxy_addr));
455	proxy_addr.sun_family = AF_UNIX;
456	strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd",
457		sizeof(proxy_addr.sun_path));
458	if (TEMP_FAILURE_RETRY(connect(sock,
459				       (const struct sockaddr*) &proxy_addr,
460				       sizeof(proxy_addr))) != 0) {
461		close(sock);
462		return -1;
463	}
464
465	// Send the request.
466	proxy = fdopen(sock, "r+");
467	if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d",
468		    hostname == NULL ? "^" : hostname,
469		    servname == NULL ? "^" : servname,
470		    hints == NULL ? -1 : hints->ai_flags,
471		    hints == NULL ? -1 : hints->ai_family,
472		    hints == NULL ? -1 : hints->ai_socktype,
473		    hints == NULL ? -1 : hints->ai_protocol) < 0) {
474		goto exit;
475	}
476	// literal NULL byte at end, required by FrameworkListener
477	if (fputc(0, proxy) == EOF ||
478	    fflush(proxy) != 0) {
479		goto exit;
480	}
481
482	char buf[4];
483	// read result code for gethostbyaddr
484	if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) {
485		goto exit;
486	}
487
488	int result_code = (int)strtol(buf, NULL, 10);
489	// verify the code itself
490	if (result_code != DnsProxyQueryResult ) {
491		goto exit;
492	}
493
494	struct addrinfo* ai = NULL;
495	struct addrinfo** nextres = res;
496	while (1) {
497		uint32_t addrinfo_len;
498		if (fread(&addrinfo_len, sizeof(addrinfo_len),
499			  1, proxy) != 1) {
500			break;
501		}
502		addrinfo_len = ntohl(addrinfo_len);
503		if (addrinfo_len == 0) {
504			success = 1;
505			break;
506		}
507
508		if (addrinfo_len < sizeof(struct addrinfo)) {
509			break;
510		}
511		struct addrinfo* ai = calloc(1, addrinfo_len +
512					     sizeof(struct sockaddr_storage));
513		if (ai == NULL) {
514			break;
515		}
516
517		if (fread(ai, addrinfo_len, 1, proxy) != 1) {
518			// Error; fall through.
519			break;
520		}
521
522		// Zero out the pointer fields we copied which aren't
523		// valid in this address space.
524		ai->ai_addr = NULL;
525		ai->ai_canonname = NULL;
526		ai->ai_next = NULL;
527
528		// struct sockaddr
529		uint32_t addr_len;
530		if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) {
531			break;
532		}
533		addr_len = ntohl(addr_len);
534		if (addr_len != 0) {
535			if (addr_len > sizeof(struct sockaddr_storage)) {
536				// Bogus; too big.
537				break;
538			}
539			struct sockaddr* addr = (struct sockaddr*)(ai + 1);
540			if (fread(addr, addr_len, 1, proxy) != 1) {
541				break;
542			}
543			ai->ai_addr = addr;
544		}
545
546		// cannonname
547		uint32_t name_len;
548		if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
549			break;
550		}
551		name_len = ntohl(name_len);
552		if (name_len != 0) {
553			ai->ai_canonname = (char*) malloc(name_len);
554			if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) {
555				break;
556			}
557			if (ai->ai_canonname[name_len - 1] != '\0') {
558				// The proxy should be returning this
559				// NULL-terminated.
560				break;
561			}
562		}
563
564		*nextres = ai;
565		nextres = &ai->ai_next;
566		ai = NULL;
567	}
568
569	if (ai != NULL) {
570		// Clean up partially-built addrinfo that we never ended up
571		// attaching to the response.
572		freeaddrinfo(ai);
573	}
574exit:
575	if (proxy != NULL) {
576		fclose(proxy);
577	}
578
579	if (success) {
580		return 0;
581	}
582
583	// Proxy failed; fall through to local
584	// resolver case.  But first clean up any
585	// memory we might've allocated.
586	if (*res) {
587		freeaddrinfo(*res);
588		*res = NULL;
589	}
590	return -1;
591}
592
593int
594getaddrinfo(const char *hostname, const char *servname,
595    const struct addrinfo *hints, struct addrinfo **res)
596{
597	struct addrinfo sentinel;
598	struct addrinfo *cur;
599	int error = 0;
600	struct addrinfo ai;
601	struct addrinfo ai0;
602	struct addrinfo *pai;
603	const struct explore *ex;
604
605	/* hostname is allowed to be NULL */
606	/* servname is allowed to be NULL */
607	/* hints is allowed to be NULL */
608	assert(res != NULL);
609
610	memset(&sentinel, 0, sizeof(sentinel));
611	cur = &sentinel;
612	pai = &ai;
613	pai->ai_flags = 0;
614	pai->ai_family = PF_UNSPEC;
615	pai->ai_socktype = ANY;
616	pai->ai_protocol = ANY;
617	pai->ai_addrlen = 0;
618	pai->ai_canonname = NULL;
619	pai->ai_addr = NULL;
620	pai->ai_next = NULL;
621
622	if (hostname == NULL && servname == NULL)
623		return EAI_NONAME;
624	if (hints) {
625		/* error check for hints */
626		if (hints->ai_addrlen || hints->ai_canonname ||
627		    hints->ai_addr || hints->ai_next)
628			ERR(EAI_BADHINTS); /* xxx */
629		if (hints->ai_flags & ~AI_MASK)
630			ERR(EAI_BADFLAGS);
631		switch (hints->ai_family) {
632		case PF_UNSPEC:
633		case PF_INET:
634#ifdef INET6
635		case PF_INET6:
636#endif
637			break;
638		default:
639			ERR(EAI_FAMILY);
640		}
641		memcpy(pai, hints, sizeof(*pai));
642
643		/*
644		 * if both socktype/protocol are specified, check if they
645		 * are meaningful combination.
646		 */
647		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
648			for (ex = explore; ex->e_af >= 0; ex++) {
649				if (pai->ai_family != ex->e_af)
650					continue;
651				if (ex->e_socktype == ANY)
652					continue;
653				if (ex->e_protocol == ANY)
654					continue;
655				if (pai->ai_socktype == ex->e_socktype
656				 && pai->ai_protocol != ex->e_protocol) {
657					ERR(EAI_BADHINTS);
658				}
659			}
660		}
661	}
662
663	/*
664	 * check for special cases.  (1) numeric servname is disallowed if
665	 * socktype/protocol are left unspecified. (2) servname is disallowed
666	 * for raw and other inet{,6} sockets.
667	 */
668	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
669#ifdef PF_INET6
670	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
671#endif
672	    ) {
673		ai0 = *pai;	/* backup *pai */
674
675		if (pai->ai_family == PF_UNSPEC) {
676#ifdef PF_INET6
677			pai->ai_family = PF_INET6;
678#else
679			pai->ai_family = PF_INET;
680#endif
681		}
682		error = get_portmatch(pai, servname);
683		if (error)
684			ERR(error);
685
686		*pai = ai0;
687	}
688
689	ai0 = *pai;
690
691	/* NULL hostname, or numeric hostname */
692	for (ex = explore; ex->e_af >= 0; ex++) {
693		*pai = ai0;
694
695		/* PF_UNSPEC entries are prepared for DNS queries only */
696		if (ex->e_af == PF_UNSPEC)
697			continue;
698
699		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
700			continue;
701		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
702			continue;
703		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
704			continue;
705
706		if (pai->ai_family == PF_UNSPEC)
707			pai->ai_family = ex->e_af;
708		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
709			pai->ai_socktype = ex->e_socktype;
710		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
711			pai->ai_protocol = ex->e_protocol;
712
713		if (hostname == NULL)
714			error = explore_null(pai, servname, &cur->ai_next);
715		else
716			error = explore_numeric_scope(pai, hostname, servname,
717			    &cur->ai_next);
718
719		if (error)
720			goto free;
721
722		while (cur->ai_next)
723			cur = cur->ai_next;
724	}
725
726	/*
727	 * XXX
728	 * If numeric representation of AF1 can be interpreted as FQDN
729	 * representation of AF2, we need to think again about the code below.
730	 */
731	if (sentinel.ai_next)
732		goto good;
733
734	if (hostname == NULL)
735		ERR(EAI_NODATA);
736	if (pai->ai_flags & AI_NUMERICHOST)
737		ERR(EAI_NONAME);
738
739        /*
740         * BEGIN ANDROID CHANGES; proxying to the cache
741         */
742        if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) {
743            return 0;
744        }
745
746	/*
747	 * hostname as alphabetical name.
748	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
749	 * outer loop by AFs.
750	 */
751	for (ex = explore; ex->e_af >= 0; ex++) {
752		*pai = ai0;
753
754		/* require exact match for family field */
755		if (pai->ai_family != ex->e_af)
756			continue;
757
758		if (!MATCH(pai->ai_socktype, ex->e_socktype,
759				WILD_SOCKTYPE(ex))) {
760			continue;
761		}
762		if (!MATCH(pai->ai_protocol, ex->e_protocol,
763				WILD_PROTOCOL(ex))) {
764			continue;
765		}
766
767		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
768			pai->ai_socktype = ex->e_socktype;
769		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
770			pai->ai_protocol = ex->e_protocol;
771
772		error = explore_fqdn(pai, hostname, servname,
773			&cur->ai_next);
774
775		while (cur && cur->ai_next)
776			cur = cur->ai_next;
777	}
778
779	/* XXX */
780	if (sentinel.ai_next)
781		error = 0;
782
783	if (error)
784		goto free;
785	if (error == 0) {
786		if (sentinel.ai_next) {
787 good:
788			*res = sentinel.ai_next;
789			return SUCCESS;
790		} else
791			error = EAI_FAIL;
792	}
793 free:
794 bad:
795	if (sentinel.ai_next)
796		freeaddrinfo(sentinel.ai_next);
797	*res = NULL;
798	return error;
799}
800
801/*
802 * FQDN hostname, DNS lookup
803 */
804static int
805explore_fqdn(const struct addrinfo *pai, const char *hostname,
806    const char *servname, struct addrinfo **res)
807{
808	struct addrinfo *result;
809	struct addrinfo *cur;
810	int error = 0;
811	static const ns_dtab dtab[] = {
812		NS_FILES_CB(_files_getaddrinfo, NULL)
813		{ NSSRC_DNS, _dns_getaddrinfo, NULL },	/* force -DHESIOD */
814		NS_NIS_CB(_yp_getaddrinfo, NULL)
815		{ 0, 0, 0 }
816	};
817
818	assert(pai != NULL);
819	/* hostname may be NULL */
820	/* servname may be NULL */
821	assert(res != NULL);
822
823	result = NULL;
824
825	/*
826	 * if the servname does not match socktype/protocol, ignore it.
827	 */
828	if (get_portmatch(pai, servname) != 0)
829		return 0;
830
831	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
832			default_dns_files, hostname, pai)) {
833	case NS_TRYAGAIN:
834		error = EAI_AGAIN;
835		goto free;
836	case NS_UNAVAIL:
837		error = EAI_FAIL;
838		goto free;
839	case NS_NOTFOUND:
840		error = EAI_NODATA;
841		goto free;
842	case NS_SUCCESS:
843		error = 0;
844		for (cur = result; cur; cur = cur->ai_next) {
845			GET_PORT(cur, servname);
846			/* canonname should be filled already */
847		}
848		break;
849	}
850
851	*res = result;
852
853	return 0;
854
855free:
856	if (result)
857		freeaddrinfo(result);
858	return error;
859}
860
861/*
862 * hostname == NULL.
863 * passive socket -> anyaddr (0.0.0.0 or ::)
864 * non-passive socket -> localhost (127.0.0.1 or ::1)
865 */
866static int
867explore_null(const struct addrinfo *pai, const char *servname,
868    struct addrinfo **res)
869{
870	int s;
871	const struct afd *afd;
872	struct addrinfo *cur;
873	struct addrinfo sentinel;
874	int error;
875
876	assert(pai != NULL);
877	/* servname may be NULL */
878	assert(res != NULL);
879
880	*res = NULL;
881	sentinel.ai_next = NULL;
882	cur = &sentinel;
883
884	/*
885	 * filter out AFs that are not supported by the kernel
886	 * XXX errno?
887	 */
888	s = socket(pai->ai_family, SOCK_DGRAM, 0);
889	if (s < 0) {
890		if (errno != EMFILE)
891			return 0;
892	} else
893		close(s);
894
895	/*
896	 * if the servname does not match socktype/protocol, ignore it.
897	 */
898	if (get_portmatch(pai, servname) != 0)
899		return 0;
900
901	afd = find_afd(pai->ai_family);
902	if (afd == NULL)
903		return 0;
904
905	if (pai->ai_flags & AI_PASSIVE) {
906		GET_AI(cur->ai_next, afd, afd->a_addrany);
907		/* xxx meaningless?
908		 * GET_CANONNAME(cur->ai_next, "anyaddr");
909		 */
910		GET_PORT(cur->ai_next, servname);
911	} else {
912		GET_AI(cur->ai_next, afd, afd->a_loopback);
913		/* xxx meaningless?
914		 * GET_CANONNAME(cur->ai_next, "localhost");
915		 */
916		GET_PORT(cur->ai_next, servname);
917	}
918	cur = cur->ai_next;
919
920	*res = sentinel.ai_next;
921	return 0;
922
923free:
924	if (sentinel.ai_next)
925		freeaddrinfo(sentinel.ai_next);
926	return error;
927}
928
929/*
930 * numeric hostname
931 */
932static int
933explore_numeric(const struct addrinfo *pai, const char *hostname,
934    const char *servname, struct addrinfo **res, const char *canonname)
935{
936	const struct afd *afd;
937	struct addrinfo *cur;
938	struct addrinfo sentinel;
939	int error;
940	char pton[PTON_MAX];
941
942	assert(pai != NULL);
943	/* hostname may be NULL */
944	/* servname may be NULL */
945	assert(res != NULL);
946
947	*res = NULL;
948	sentinel.ai_next = NULL;
949	cur = &sentinel;
950
951	/*
952	 * if the servname does not match socktype/protocol, ignore it.
953	 */
954	if (get_portmatch(pai, servname) != 0)
955		return 0;
956
957	afd = find_afd(pai->ai_family);
958	if (afd == NULL)
959		return 0;
960
961	switch (afd->a_af) {
962#if 0 /*X/Open spec*/
963	case AF_INET:
964		if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
965			if (pai->ai_family == afd->a_af ||
966			    pai->ai_family == PF_UNSPEC /*?*/) {
967				GET_AI(cur->ai_next, afd, pton);
968				GET_PORT(cur->ai_next, servname);
969				if ((pai->ai_flags & AI_CANONNAME)) {
970					/*
971					 * Set the numeric address itself as
972					 * the canonical name, based on a
973					 * clarification in rfc2553bis-03.
974					 */
975					GET_CANONNAME(cur->ai_next, canonname);
976				}
977				while (cur && cur->ai_next)
978					cur = cur->ai_next;
979			} else
980				ERR(EAI_FAMILY);	/*xxx*/
981		}
982		break;
983#endif
984	default:
985		if (inet_pton(afd->a_af, hostname, pton) == 1) {
986			if (pai->ai_family == afd->a_af ||
987			    pai->ai_family == PF_UNSPEC /*?*/) {
988				GET_AI(cur->ai_next, afd, pton);
989				GET_PORT(cur->ai_next, servname);
990				if ((pai->ai_flags & AI_CANONNAME)) {
991					/*
992					 * Set the numeric address itself as
993					 * the canonical name, based on a
994					 * clarification in rfc2553bis-03.
995					 */
996					GET_CANONNAME(cur->ai_next, canonname);
997				}
998				while (cur->ai_next)
999					cur = cur->ai_next;
1000			} else
1001				ERR(EAI_FAMILY);	/*xxx*/
1002		}
1003		break;
1004	}
1005
1006	*res = sentinel.ai_next;
1007	return 0;
1008
1009free:
1010bad:
1011	if (sentinel.ai_next)
1012		freeaddrinfo(sentinel.ai_next);
1013	return error;
1014}
1015
1016/*
1017 * numeric hostname with scope
1018 */
1019static int
1020explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
1021    const char *servname, struct addrinfo **res)
1022{
1023#if !defined(SCOPE_DELIMITER) || !defined(INET6)
1024	return explore_numeric(pai, hostname, servname, res, hostname);
1025#else
1026	const struct afd *afd;
1027	struct addrinfo *cur;
1028	int error;
1029	char *cp, *hostname2 = NULL, *scope, *addr;
1030	struct sockaddr_in6 *sin6;
1031
1032	assert(pai != NULL);
1033	/* hostname may be NULL */
1034	/* servname may be NULL */
1035	assert(res != NULL);
1036
1037	/*
1038	 * if the servname does not match socktype/protocol, ignore it.
1039	 */
1040	if (get_portmatch(pai, servname) != 0)
1041		return 0;
1042
1043	afd = find_afd(pai->ai_family);
1044	if (afd == NULL)
1045		return 0;
1046
1047	if (!afd->a_scoped)
1048		return explore_numeric(pai, hostname, servname, res, hostname);
1049
1050	cp = strchr(hostname, SCOPE_DELIMITER);
1051	if (cp == NULL)
1052		return explore_numeric(pai, hostname, servname, res, hostname);
1053
1054	/*
1055	 * Handle special case of <scoped_address><delimiter><scope id>
1056	 */
1057	hostname2 = strdup(hostname);
1058	if (hostname2 == NULL)
1059		return EAI_MEMORY;
1060	/* terminate at the delimiter */
1061	hostname2[cp - hostname] = '\0';
1062	addr = hostname2;
1063	scope = cp + 1;
1064
1065	error = explore_numeric(pai, addr, servname, res, hostname);
1066	if (error == 0) {
1067		u_int32_t scopeid;
1068
1069		for (cur = *res; cur; cur = cur->ai_next) {
1070			if (cur->ai_family != AF_INET6)
1071				continue;
1072			sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
1073			if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
1074				free(hostname2);
1075				return(EAI_NODATA); /* XXX: is return OK? */
1076			}
1077			sin6->sin6_scope_id = scopeid;
1078		}
1079	}
1080
1081	free(hostname2);
1082
1083	return error;
1084#endif
1085}
1086
1087static int
1088get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
1089{
1090
1091	assert(pai != NULL);
1092	assert(ai != NULL);
1093	assert(str != NULL);
1094
1095	if ((pai->ai_flags & AI_CANONNAME) != 0) {
1096		ai->ai_canonname = strdup(str);
1097		if (ai->ai_canonname == NULL)
1098			return EAI_MEMORY;
1099	}
1100	return 0;
1101}
1102
1103static struct addrinfo *
1104get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
1105{
1106	char *p;
1107	struct addrinfo *ai;
1108
1109	assert(pai != NULL);
1110	assert(afd != NULL);
1111	assert(addr != NULL);
1112
1113	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
1114		+ (afd->a_socklen));
1115	if (ai == NULL)
1116		return NULL;
1117
1118	memcpy(ai, pai, sizeof(struct addrinfo));
1119	ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
1120	memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
1121
1122#ifdef HAVE_SA_LEN
1123	ai->ai_addr->sa_len = afd->a_socklen;
1124#endif
1125
1126	ai->ai_addrlen = afd->a_socklen;
1127#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__)
1128	ai->__ai_pad0 = 0;
1129#endif
1130	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1131	p = (char *)(void *)(ai->ai_addr);
1132	memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
1133	return ai;
1134}
1135
1136static int
1137get_portmatch(const struct addrinfo *ai, const char *servname)
1138{
1139
1140	assert(ai != NULL);
1141	/* servname may be NULL */
1142
1143	return get_port(ai, servname, 1);
1144}
1145
1146static int
1147get_port(const struct addrinfo *ai, const char *servname, int matchonly)
1148{
1149	const char *proto;
1150	struct servent *sp;
1151	int port;
1152	int allownumeric;
1153
1154	assert(ai != NULL);
1155	/* servname may be NULL */
1156
1157	if (servname == NULL)
1158		return 0;
1159	switch (ai->ai_family) {
1160	case AF_INET:
1161#ifdef AF_INET6
1162	case AF_INET6:
1163#endif
1164		break;
1165	default:
1166		return 0;
1167	}
1168
1169	switch (ai->ai_socktype) {
1170	case SOCK_RAW:
1171		return EAI_SERVICE;
1172	case SOCK_DGRAM:
1173	case SOCK_STREAM:
1174		allownumeric = 1;
1175		break;
1176	case ANY:
1177#if 1  /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */
1178		allownumeric = 1;
1179#else
1180		allownumeric = 0;
1181#endif
1182		break;
1183	default:
1184		return EAI_SOCKTYPE;
1185	}
1186
1187	port = str2number(servname);
1188	if (port >= 0) {
1189		if (!allownumeric)
1190			return EAI_SERVICE;
1191		if (port < 0 || port > 65535)
1192			return EAI_SERVICE;
1193		port = htons(port);
1194	} else {
1195		if (ai->ai_flags & AI_NUMERICSERV)
1196			return EAI_NONAME;
1197
1198		switch (ai->ai_socktype) {
1199		case SOCK_DGRAM:
1200			proto = "udp";
1201			break;
1202		case SOCK_STREAM:
1203			proto = "tcp";
1204			break;
1205		default:
1206			proto = NULL;
1207			break;
1208		}
1209
1210		if ((sp = getservbyname(servname, proto)) == NULL)
1211			return EAI_SERVICE;
1212		port = sp->s_port;
1213	}
1214
1215	if (!matchonly) {
1216		switch (ai->ai_family) {
1217		case AF_INET:
1218			((struct sockaddr_in *)(void *)
1219			    ai->ai_addr)->sin_port = port;
1220			break;
1221#ifdef INET6
1222		case AF_INET6:
1223			((struct sockaddr_in6 *)(void *)
1224			    ai->ai_addr)->sin6_port = port;
1225			break;
1226#endif
1227		}
1228	}
1229
1230	return 0;
1231}
1232
1233static const struct afd *
1234find_afd(int af)
1235{
1236	const struct afd *afd;
1237
1238	if (af == PF_UNSPEC)
1239		return NULL;
1240	for (afd = afdl; afd->a_af; afd++) {
1241		if (afd->a_af == af)
1242			return afd;
1243	}
1244	return NULL;
1245}
1246
1247#ifdef INET6
1248/* convert a string to a scope identifier. XXX: IPv6 specific */
1249static int
1250ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
1251{
1252	u_long lscopeid;
1253	struct in6_addr *a6;
1254	char *ep;
1255
1256	assert(scope != NULL);
1257	assert(sin6 != NULL);
1258	assert(scopeid != NULL);
1259
1260	a6 = &sin6->sin6_addr;
1261
1262	/* empty scopeid portion is invalid */
1263	if (*scope == '\0')
1264		return -1;
1265
1266	if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1267		/*
1268		 * We currently assume a one-to-one mapping between links
1269		 * and interfaces, so we simply use interface indices for
1270		 * like-local scopes.
1271		 */
1272		*scopeid = if_nametoindex(scope);
1273		if (*scopeid == 0)
1274			goto trynumeric;
1275		return 0;
1276	}
1277
1278	/* still unclear about literal, allow numeric only - placeholder */
1279	if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1280		goto trynumeric;
1281	if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1282		goto trynumeric;
1283	else
1284		goto trynumeric;	/* global */
1285
1286	/* try to convert to a numeric id as a last resort */
1287  trynumeric:
1288	errno = 0;
1289	lscopeid = strtoul(scope, &ep, 10);
1290	*scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1291	if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1292		return 0;
1293	else
1294		return -1;
1295}
1296#endif
1297
1298/* code duplicate with gethnamaddr.c */
1299
1300static const char AskedForGot[] =
1301	"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1302
1303static struct addrinfo *
1304getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1305    const struct addrinfo *pai)
1306{
1307	struct addrinfo sentinel, *cur;
1308	struct addrinfo ai;
1309	const struct afd *afd;
1310	char *canonname;
1311	const HEADER *hp;
1312	const u_char *cp;
1313	int n;
1314	const u_char *eom;
1315	char *bp, *ep;
1316	int type, class, ancount, qdcount;
1317	int haveanswer, had_error;
1318	char tbuf[MAXDNAME];
1319	int (*name_ok) (const char *);
1320	char hostbuf[8*1024];
1321
1322	assert(answer != NULL);
1323	assert(qname != NULL);
1324	assert(pai != NULL);
1325
1326	memset(&sentinel, 0, sizeof(sentinel));
1327	cur = &sentinel;
1328
1329	canonname = NULL;
1330	eom = answer->buf + anslen;
1331	switch (qtype) {
1332	case T_A:
1333	case T_AAAA:
1334	case T_ANY:	/*use T_ANY only for T_A/T_AAAA lookup*/
1335		name_ok = res_hnok;
1336		break;
1337	default:
1338		return NULL;	/* XXX should be abort(); */
1339	}
1340	/*
1341	 * find first satisfactory answer
1342	 */
1343	hp = &answer->hdr;
1344	ancount = ntohs(hp->ancount);
1345	qdcount = ntohs(hp->qdcount);
1346	bp = hostbuf;
1347	ep = hostbuf + sizeof hostbuf;
1348	cp = answer->buf + HFIXEDSZ;
1349	if (qdcount != 1) {
1350		h_errno = NO_RECOVERY;
1351		return (NULL);
1352	}
1353	n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1354	if ((n < 0) || !(*name_ok)(bp)) {
1355		h_errno = NO_RECOVERY;
1356		return (NULL);
1357	}
1358	cp += n + QFIXEDSZ;
1359	if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1360		/* res_send() has already verified that the query name is the
1361		 * same as the one we sent; this just gets the expanded name
1362		 * (i.e., with the succeeding search-domain tacked on).
1363		 */
1364		n = strlen(bp) + 1;		/* for the \0 */
1365		if (n >= MAXHOSTNAMELEN) {
1366			h_errno = NO_RECOVERY;
1367			return (NULL);
1368		}
1369		canonname = bp;
1370		bp += n;
1371		/* The qname can be abbreviated, but h_name is now absolute. */
1372		qname = canonname;
1373	}
1374	haveanswer = 0;
1375	had_error = 0;
1376	while (ancount-- > 0 && cp < eom && !had_error) {
1377		n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1378		if ((n < 0) || !(*name_ok)(bp)) {
1379			had_error++;
1380			continue;
1381		}
1382		cp += n;			/* name */
1383		type = _getshort(cp);
1384 		cp += INT16SZ;			/* type */
1385		class = _getshort(cp);
1386 		cp += INT16SZ + INT32SZ;	/* class, TTL */
1387		n = _getshort(cp);
1388		cp += INT16SZ;			/* len */
1389		if (class != C_IN) {
1390			/* XXX - debug? syslog? */
1391			cp += n;
1392			continue;		/* XXX - had_error++ ? */
1393		}
1394		if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1395		    type == T_CNAME) {
1396			n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1397			if ((n < 0) || !(*name_ok)(tbuf)) {
1398				had_error++;
1399				continue;
1400			}
1401			cp += n;
1402			/* Get canonical name. */
1403			n = strlen(tbuf) + 1;	/* for the \0 */
1404			if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1405				had_error++;
1406				continue;
1407			}
1408			strlcpy(bp, tbuf, (size_t)(ep - bp));
1409			canonname = bp;
1410			bp += n;
1411			continue;
1412		}
1413		if (qtype == T_ANY) {
1414			if (!(type == T_A || type == T_AAAA)) {
1415				cp += n;
1416				continue;
1417			}
1418		} else if (type != qtype) {
1419			if (type != T_KEY && type != T_SIG)
1420				syslog(LOG_NOTICE|LOG_AUTH,
1421	       "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1422				       qname, p_class(C_IN), p_type(qtype),
1423				       p_type(type));
1424			cp += n;
1425			continue;		/* XXX - had_error++ ? */
1426		}
1427		switch (type) {
1428		case T_A:
1429		case T_AAAA:
1430			if (strcasecmp(canonname, bp) != 0) {
1431				syslog(LOG_NOTICE|LOG_AUTH,
1432				       AskedForGot, canonname, bp);
1433				cp += n;
1434				continue;	/* XXX - had_error++ ? */
1435			}
1436			if (type == T_A && n != INADDRSZ) {
1437				cp += n;
1438				continue;
1439			}
1440			if (type == T_AAAA && n != IN6ADDRSZ) {
1441				cp += n;
1442				continue;
1443			}
1444			if (type == T_AAAA) {
1445				struct in6_addr in6;
1446				memcpy(&in6, cp, IN6ADDRSZ);
1447				if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1448					cp += n;
1449					continue;
1450				}
1451			}
1452			if (!haveanswer) {
1453				int nn;
1454
1455				canonname = bp;
1456				nn = strlen(bp) + 1;	/* for the \0 */
1457				bp += nn;
1458			}
1459
1460			/* don't overwrite pai */
1461			ai = *pai;
1462			ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1463			afd = find_afd(ai.ai_family);
1464			if (afd == NULL) {
1465				cp += n;
1466				continue;
1467			}
1468			cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1469			if (cur->ai_next == NULL)
1470				had_error++;
1471			while (cur && cur->ai_next)
1472				cur = cur->ai_next;
1473			cp += n;
1474			break;
1475		default:
1476			abort();
1477		}
1478		if (!had_error)
1479			haveanswer++;
1480	}
1481	if (haveanswer) {
1482		if (!canonname)
1483			(void)get_canonname(pai, sentinel.ai_next, qname);
1484		else
1485			(void)get_canonname(pai, sentinel.ai_next, canonname);
1486		h_errno = NETDB_SUCCESS;
1487		return sentinel.ai_next;
1488	}
1489
1490	h_errno = NO_RECOVERY;
1491	return NULL;
1492}
1493
1494struct addrinfo_sort_elem {
1495	struct addrinfo *ai;
1496	int has_src_addr;
1497	sockaddr_union src_addr;
1498	int original_order;
1499};
1500
1501/*ARGSUSED*/
1502static int
1503_get_scope(const struct sockaddr *addr)
1504{
1505	if (addr->sa_family == AF_INET6) {
1506		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
1507		if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) {
1508			return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr);
1509		} else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) ||
1510			   IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
1511			/*
1512			 * RFC 4291 section 2.5.3 says loopback is to be treated as having
1513			 * link-local scope.
1514			 */
1515			return IPV6_ADDR_SCOPE_LINKLOCAL;
1516		} else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
1517			return IPV6_ADDR_SCOPE_SITELOCAL;
1518		} else {
1519			return IPV6_ADDR_SCOPE_GLOBAL;
1520		}
1521	} else if (addr->sa_family == AF_INET) {
1522		const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
1523		unsigned long int na = ntohl(addr4->sin_addr.s_addr);
1524
1525		if (IN_LOOPBACK(na) ||                          /* 127.0.0.0/8 */
1526		    (na & 0xffff0000) == 0xa9fe0000) {          /* 169.254.0.0/16 */
1527			return IPV6_ADDR_SCOPE_LINKLOCAL;
1528		} else {
1529			/*
1530			 * According to draft-ietf-6man-rfc3484-revise-01 section 2.3,
1531			 * it is best not to treat the private IPv4 ranges
1532			 * (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being
1533			 * in a special scope, so we don't.
1534			 */
1535			return IPV6_ADDR_SCOPE_GLOBAL;
1536		}
1537	} else {
1538		/*
1539		 * This should never happen.
1540		 * Return a scope with low priority as a last resort.
1541		 */
1542		return IPV6_ADDR_SCOPE_NODELOCAL;
1543	}
1544}
1545
1546/* These macros are modelled after the ones in <netinet/in6.h>. */
1547
1548/* RFC 4380, section 2.6 */
1549#define IN6_IS_ADDR_TEREDO(a)	 \
1550	((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000)))
1551
1552/* RFC 3056, section 2. */
1553#define IN6_IS_ADDR_6TO4(a)	 \
1554	(((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
1555
1556/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
1557#define IN6_IS_ADDR_6BONE(a)      \
1558	(((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
1559
1560/*
1561 * Get the label for a given IPv4/IPv6 address.
1562 * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
1563 */
1564
1565/*ARGSUSED*/
1566static int
1567_get_label(const struct sockaddr *addr)
1568{
1569	if (addr->sa_family == AF_INET) {
1570		return 3;
1571	} else if (addr->sa_family == AF_INET6) {
1572		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
1573		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
1574			return 0;
1575		} else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
1576			return 1;
1577		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
1578			return 3;
1579		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
1580			return 4;
1581		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
1582			return 5;
1583		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
1584			return 10;
1585		} else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
1586			return 11;
1587		} else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
1588			return 12;
1589		} else {
1590			return 2;
1591		}
1592	} else {
1593		/*
1594		 * This should never happen.
1595		 * Return a semi-random label as a last resort.
1596		 */
1597		return 1;
1598	}
1599}
1600
1601/*
1602 * Get the precedence for a given IPv4/IPv6 address.
1603 * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
1604 */
1605
1606/*ARGSUSED*/
1607static int
1608_get_precedence(const struct sockaddr *addr)
1609{
1610	if (addr->sa_family == AF_INET) {
1611		return 30;
1612	} else if (addr->sa_family == AF_INET6) {
1613		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
1614		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
1615			return 60;
1616		} else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
1617			return 50;
1618		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
1619			return 30;
1620		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
1621			return 20;
1622		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
1623			return 10;
1624		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
1625		           IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
1626		           IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
1627			return 1;
1628		} else {
1629			return 40;
1630		}
1631	} else {
1632		return 1;
1633	}
1634}
1635
1636/*
1637 * Find number of matching initial bits between the two addresses a1 and a2.
1638 */
1639
1640/*ARGSUSED*/
1641static int
1642_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2)
1643{
1644	const char *p1 = (const char *)a1;
1645	const char *p2 = (const char *)a2;
1646	unsigned i;
1647
1648	for (i = 0; i < sizeof(*a1); ++i) {
1649		int x, j;
1650
1651		if (p1[i] == p2[i]) {
1652			continue;
1653		}
1654		x = p1[i] ^ p2[i];
1655		for (j = 0; j < CHAR_BIT; ++j) {
1656			if (x & (1 << (CHAR_BIT - 1))) {
1657				return i * CHAR_BIT + j;
1658			}
1659			x <<= 1;
1660		}
1661	}
1662	return sizeof(*a1) * CHAR_BIT;
1663}
1664
1665/*
1666 * Compare two source/destination address pairs.
1667 * RFC 3484, section 6.
1668 */
1669
1670/*ARGSUSED*/
1671static int
1672_rfc3484_compare(const void *ptr1, const void* ptr2)
1673{
1674	const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1;
1675	const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2;
1676	int scope_src1, scope_dst1, scope_match1;
1677	int scope_src2, scope_dst2, scope_match2;
1678	int label_src1, label_dst1, label_match1;
1679	int label_src2, label_dst2, label_match2;
1680	int precedence1, precedence2;
1681	int prefixlen1, prefixlen2;
1682
1683	/* Rule 1: Avoid unusable destinations. */
1684	if (a1->has_src_addr != a2->has_src_addr) {
1685		return a2->has_src_addr - a1->has_src_addr;
1686	}
1687
1688	/* Rule 2: Prefer matching scope. */
1689	scope_src1 = _get_scope(&a1->src_addr.generic);
1690	scope_dst1 = _get_scope(a1->ai->ai_addr);
1691	scope_match1 = (scope_src1 == scope_dst1);
1692
1693	scope_src2 = _get_scope(&a2->src_addr.generic);
1694	scope_dst2 = _get_scope(a2->ai->ai_addr);
1695	scope_match2 = (scope_src2 == scope_dst2);
1696
1697	if (scope_match1 != scope_match2) {
1698		return scope_match2 - scope_match1;
1699	}
1700
1701	/*
1702	 * Rule 3: Avoid deprecated addresses.
1703	 * TODO(sesse): We don't currently have a good way of finding this.
1704	 */
1705
1706	/*
1707	 * Rule 4: Prefer home addresses.
1708	 * TODO(sesse): We don't currently have a good way of finding this.
1709	 */
1710
1711	/* Rule 5: Prefer matching label. */
1712	label_src1 = _get_label(&a1->src_addr.generic);
1713	label_dst1 = _get_label(a1->ai->ai_addr);
1714	label_match1 = (label_src1 == label_dst1);
1715
1716	label_src2 = _get_label(&a2->src_addr.generic);
1717	label_dst2 = _get_label(a2->ai->ai_addr);
1718	label_match2 = (label_src2 == label_dst2);
1719
1720	if (label_match1 != label_match2) {
1721		return label_match2 - label_match1;
1722	}
1723
1724	/* Rule 6: Prefer higher precedence. */
1725	precedence1 = _get_precedence(a1->ai->ai_addr);
1726	precedence2 = _get_precedence(a2->ai->ai_addr);
1727	if (precedence1 != precedence2) {
1728		return precedence2 - precedence1;
1729	}
1730
1731	/*
1732	 * Rule 7: Prefer native transport.
1733	 * TODO(sesse): We don't currently have a good way of finding this.
1734	 */
1735
1736	/* Rule 8: Prefer smaller scope. */
1737	if (scope_dst1 != scope_dst2) {
1738		return scope_dst1 - scope_dst2;
1739	}
1740
1741	/*
1742	 * Rule 9: Use longest matching prefix.
1743         * We implement this for IPv6 only, as the rules in RFC 3484 don't seem
1744         * to work very well directly applied to IPv4. (glibc uses information from
1745         * the routing table for a custom IPv4 implementation here.)
1746	 */
1747	if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 &&
1748	    a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) {
1749		const struct sockaddr_in6 *a1_src = &a1->src_addr.in6;
1750		const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr;
1751		const struct sockaddr_in6 *a2_src = &a2->src_addr.in6;
1752		const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr;
1753		prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr);
1754		prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr);
1755		if (prefixlen1 != prefixlen2) {
1756			return prefixlen2 - prefixlen1;
1757		}
1758	}
1759
1760	/*
1761	 * Rule 10: Leave the order unchanged.
1762	 * We need this since qsort() is not necessarily stable.
1763	 */
1764	return a1->original_order - a2->original_order;
1765}
1766
1767/*
1768 * Find the source address that will be used if trying to connect to the given
1769 * address. src_addr must be large enough to hold a struct sockaddr_in6.
1770 *
1771 * Returns 1 if a source address was found, 0 if the address is unreachable,
1772 * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
1773 * undefined.
1774 */
1775
1776/*ARGSUSED*/
1777static int
1778_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr)
1779{
1780	int sock;
1781	int ret;
1782	socklen_t len;
1783
1784	switch (addr->sa_family) {
1785	case AF_INET:
1786		len = sizeof(struct sockaddr_in);
1787		break;
1788	case AF_INET6:
1789		len = sizeof(struct sockaddr_in6);
1790		break;
1791	default:
1792		/* No known usable source address for non-INET families. */
1793		return 0;
1794	}
1795
1796	sock = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
1797	if (sock == -1) {
1798		if (errno == EAFNOSUPPORT) {
1799			return 0;
1800		} else {
1801			return -1;
1802		}
1803	}
1804
1805	do {
1806		ret = connect(sock, addr, len);
1807	} while (ret == -1 && errno == EINTR);
1808
1809	if (ret == -1) {
1810		close(sock);
1811		return 0;
1812	}
1813
1814	if (getsockname(sock, src_addr, &len) == -1) {
1815		close(sock);
1816		return -1;
1817	}
1818	close(sock);
1819	return 1;
1820}
1821
1822/*
1823 * Sort the linked list starting at sentinel->ai_next in RFC3484 order.
1824 * Will leave the list unchanged if an error occurs.
1825 */
1826
1827/*ARGSUSED*/
1828static void
1829_rfc3484_sort(struct addrinfo *list_sentinel)
1830{
1831	struct addrinfo *cur;
1832	int nelem = 0, i;
1833	struct addrinfo_sort_elem *elems;
1834
1835	cur = list_sentinel->ai_next;
1836	while (cur) {
1837		++nelem;
1838		cur = cur->ai_next;
1839	}
1840
1841	elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem));
1842	if (elems == NULL) {
1843		goto error;
1844	}
1845
1846	/*
1847	 * Convert the linked list to an array that also contains the candidate
1848	 * source address for each destination address.
1849	 */
1850	for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) {
1851		int has_src_addr;
1852		assert(cur != NULL);
1853		elems[i].ai = cur;
1854		elems[i].original_order = i;
1855
1856		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic);
1857		if (has_src_addr == -1) {
1858			goto error;
1859		}
1860		elems[i].has_src_addr = has_src_addr;
1861	}
1862
1863	/* Sort the addresses, and rearrange the linked list so it matches the sorted order. */
1864	qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc3484_compare);
1865
1866	list_sentinel->ai_next = elems[0].ai;
1867	for (i = 0; i < nelem - 1; ++i) {
1868		elems[i].ai->ai_next = elems[i + 1].ai;
1869	}
1870	elems[nelem - 1].ai->ai_next = NULL;
1871
1872error:
1873	free(elems);
1874}
1875
1876static int _using_alt_dns()
1877{
1878	char propname[PROP_NAME_MAX];
1879	char propvalue[PROP_VALUE_MAX];
1880
1881	propvalue[0] = 0;
1882	snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
1883	if (__system_property_get(propname, propvalue) > 0 ) {
1884		return 1;
1885	}
1886	return 0;
1887}
1888
1889/*ARGSUSED*/
1890static int
1891_dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
1892{
1893	struct addrinfo *ai;
1894	querybuf *buf, *buf2;
1895	const char *name;
1896	const struct addrinfo *pai;
1897	struct addrinfo sentinel, *cur;
1898	struct res_target q, q2;
1899	res_state res;
1900
1901	name = va_arg(ap, char *);
1902	pai = va_arg(ap, const struct addrinfo *);
1903	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
1904
1905	memset(&q, 0, sizeof(q));
1906	memset(&q2, 0, sizeof(q2));
1907	memset(&sentinel, 0, sizeof(sentinel));
1908	cur = &sentinel;
1909
1910	buf = malloc(sizeof(*buf));
1911	if (buf == NULL) {
1912		h_errno = NETDB_INTERNAL;
1913		return NS_NOTFOUND;
1914	}
1915	buf2 = malloc(sizeof(*buf2));
1916	if (buf2 == NULL) {
1917		free(buf);
1918		h_errno = NETDB_INTERNAL;
1919		return NS_NOTFOUND;
1920	}
1921
1922	switch (pai->ai_family) {
1923	case AF_UNSPEC:
1924		/* prefer IPv6 */
1925		q.name = name;
1926		q.qclass = C_IN;
1927		q.answer = buf->buf;
1928		q.anslen = sizeof(buf->buf);
1929		int query_ipv6 = 1, query_ipv4 = 1;
1930		if (pai->ai_flags & AI_ADDRCONFIG) {
1931			// Only implement AI_ADDRCONFIG if the application is not
1932			// using its own DNS servers, since our implementation
1933			// only works on the default connection.
1934			if (!_using_alt_dns()) {
1935				query_ipv6 = _have_ipv6();
1936				query_ipv4 = _have_ipv4();
1937			}
1938		}
1939		if (query_ipv6) {
1940			q.qtype = T_AAAA;
1941			if (query_ipv4) {
1942				q.next = &q2;
1943				q2.name = name;
1944				q2.qclass = C_IN;
1945				q2.qtype = T_A;
1946				q2.answer = buf2->buf;
1947				q2.anslen = sizeof(buf2->buf);
1948			}
1949		} else if (query_ipv4) {
1950			q.qtype = T_A;
1951		} else {
1952			free(buf);
1953			free(buf2);
1954			return NS_NOTFOUND;
1955		}
1956		break;
1957	case AF_INET:
1958		q.name = name;
1959		q.qclass = C_IN;
1960		q.qtype = T_A;
1961		q.answer = buf->buf;
1962		q.anslen = sizeof(buf->buf);
1963		break;
1964	case AF_INET6:
1965		q.name = name;
1966		q.qclass = C_IN;
1967		q.qtype = T_AAAA;
1968		q.answer = buf->buf;
1969		q.anslen = sizeof(buf->buf);
1970		break;
1971	default:
1972		free(buf);
1973		free(buf2);
1974		return NS_UNAVAIL;
1975	}
1976
1977	res = __res_get_state();
1978	if (res == NULL) {
1979		free(buf);
1980		free(buf2);
1981		return NS_NOTFOUND;
1982	}
1983
1984	if (res_searchN(name, &q, res) < 0) {
1985		__res_put_state(res);
1986		free(buf);
1987		free(buf2);
1988		return NS_NOTFOUND;
1989	}
1990	ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1991	if (ai) {
1992		cur->ai_next = ai;
1993		while (cur && cur->ai_next)
1994			cur = cur->ai_next;
1995	}
1996	if (q.next) {
1997		ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1998		if (ai)
1999			cur->ai_next = ai;
2000	}
2001	free(buf);
2002	free(buf2);
2003	if (sentinel.ai_next == NULL) {
2004		__res_put_state(res);
2005		switch (h_errno) {
2006		case HOST_NOT_FOUND:
2007			return NS_NOTFOUND;
2008		case TRY_AGAIN:
2009			return NS_TRYAGAIN;
2010		default:
2011			return NS_UNAVAIL;
2012		}
2013	}
2014
2015	_rfc3484_sort(&sentinel);
2016
2017	__res_put_state(res);
2018
2019	*((struct addrinfo **)rv) = sentinel.ai_next;
2020	return NS_SUCCESS;
2021}
2022
2023static void
2024_sethtent(FILE **hostf)
2025{
2026
2027	if (!*hostf)
2028		*hostf = fopen(_PATH_HOSTS, "r" );
2029	else
2030		rewind(*hostf);
2031}
2032
2033static void
2034_endhtent(FILE **hostf)
2035{
2036
2037	if (*hostf) {
2038		(void) fclose(*hostf);
2039		*hostf = NULL;
2040	}
2041}
2042
2043static struct addrinfo *
2044_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
2045{
2046	char *p;
2047	char *cp, *tname, *cname;
2048	struct addrinfo hints, *res0, *res;
2049	int error;
2050	const char *addr;
2051	char hostbuf[8*1024];
2052
2053//	fprintf(stderr, "_gethtent() name = '%s'\n", name);
2054	assert(name != NULL);
2055	assert(pai != NULL);
2056
2057	if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" )))
2058		return (NULL);
2059 again:
2060	if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
2061		return (NULL);
2062	if (*p == '#')
2063		goto again;
2064	if (!(cp = strpbrk(p, "#\n")))
2065		goto again;
2066	*cp = '\0';
2067	if (!(cp = strpbrk(p, " \t")))
2068		goto again;
2069	*cp++ = '\0';
2070	addr = p;
2071	/* if this is not something we're looking for, skip it. */
2072	cname = NULL;
2073	while (cp && *cp) {
2074		if (*cp == ' ' || *cp == '\t') {
2075			cp++;
2076			continue;
2077		}
2078		if (!cname)
2079			cname = cp;
2080		tname = cp;
2081		if ((cp = strpbrk(cp, " \t")) != NULL)
2082			*cp++ = '\0';
2083//		fprintf(stderr, "\ttname = '%s'", tname);
2084		if (strcasecmp(name, tname) == 0)
2085			goto found;
2086	}
2087	goto again;
2088
2089found:
2090	hints = *pai;
2091	hints.ai_flags = AI_NUMERICHOST;
2092	error = getaddrinfo(addr, NULL, &hints, &res0);
2093	if (error)
2094		goto again;
2095	for (res = res0; res; res = res->ai_next) {
2096		/* cover it up */
2097		res->ai_flags = pai->ai_flags;
2098
2099		if (pai->ai_flags & AI_CANONNAME) {
2100			if (get_canonname(pai, res, cname) != 0) {
2101				freeaddrinfo(res0);
2102				goto again;
2103			}
2104		}
2105	}
2106	return res0;
2107}
2108
2109/*ARGSUSED*/
2110static int
2111_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
2112{
2113	const char *name;
2114	const struct addrinfo *pai;
2115	struct addrinfo sentinel, *cur;
2116	struct addrinfo *p;
2117	FILE *hostf = NULL;
2118
2119	name = va_arg(ap, char *);
2120	pai = va_arg(ap, struct addrinfo *);
2121
2122//	fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name);
2123	memset(&sentinel, 0, sizeof(sentinel));
2124	cur = &sentinel;
2125
2126	_sethtent(&hostf);
2127	while ((p = _gethtent(&hostf, name, pai)) != NULL) {
2128		cur->ai_next = p;
2129		while (cur && cur->ai_next)
2130			cur = cur->ai_next;
2131	}
2132	_endhtent(&hostf);
2133
2134	*((struct addrinfo **)rv) = sentinel.ai_next;
2135	if (sentinel.ai_next == NULL)
2136		return NS_NOTFOUND;
2137	return NS_SUCCESS;
2138}
2139
2140/* resolver logic */
2141
2142/*
2143 * Formulate a normal query, send, and await answer.
2144 * Returned answer is placed in supplied buffer "answer".
2145 * Perform preliminary check of answer, returning success only
2146 * if no error is indicated and the answer count is nonzero.
2147 * Return the size of the response on success, -1 on error.
2148 * Error number is left in h_errno.
2149 *
2150 * Caller must parse answer and determine whether it answers the question.
2151 */
2152static int
2153res_queryN(const char *name, /* domain name */ struct res_target *target,
2154    res_state res)
2155{
2156	u_char buf[MAXPACKET];
2157	HEADER *hp;
2158	int n;
2159	struct res_target *t;
2160	int rcode;
2161	int ancount;
2162
2163	assert(name != NULL);
2164	/* XXX: target may be NULL??? */
2165
2166	rcode = NOERROR;
2167	ancount = 0;
2168
2169	for (t = target; t; t = t->next) {
2170		int class, type;
2171		u_char *answer;
2172		int anslen;
2173
2174		hp = (HEADER *)(void *)t->answer;
2175		hp->rcode = NOERROR;	/* default */
2176
2177		/* make it easier... */
2178		class = t->qclass;
2179		type = t->qtype;
2180		answer = t->answer;
2181		anslen = t->anslen;
2182#ifdef DEBUG
2183		if (res->options & RES_DEBUG)
2184			printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
2185#endif
2186
2187		n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
2188		    buf, sizeof(buf));
2189#ifdef RES_USE_EDNS0
2190		if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
2191			n = res_nopt(res, n, buf, sizeof(buf), anslen);
2192#endif
2193		if (n <= 0) {
2194#ifdef DEBUG
2195			if (res->options & RES_DEBUG)
2196				printf(";; res_nquery: mkquery failed\n");
2197#endif
2198			h_errno = NO_RECOVERY;
2199			return n;
2200		}
2201		n = res_nsend(res, buf, n, answer, anslen);
2202#if 0
2203		if (n < 0) {
2204#ifdef DEBUG
2205			if (res->options & RES_DEBUG)
2206				printf(";; res_query: send error\n");
2207#endif
2208			h_errno = TRY_AGAIN;
2209			return n;
2210		}
2211#endif
2212
2213		if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
2214			rcode = hp->rcode;	/* record most recent error */
2215#ifdef DEBUG
2216			if (res->options & RES_DEBUG)
2217				printf(";; rcode = %u, ancount=%u\n", hp->rcode,
2218				    ntohs(hp->ancount));
2219#endif
2220			continue;
2221		}
2222
2223		ancount += ntohs(hp->ancount);
2224
2225		t->n = n;
2226	}
2227
2228	if (ancount == 0) {
2229		switch (rcode) {
2230		case NXDOMAIN:
2231			h_errno = HOST_NOT_FOUND;
2232			break;
2233		case SERVFAIL:
2234			h_errno = TRY_AGAIN;
2235			break;
2236		case NOERROR:
2237			h_errno = NO_DATA;
2238			break;
2239		case FORMERR:
2240		case NOTIMP:
2241		case REFUSED:
2242		default:
2243			h_errno = NO_RECOVERY;
2244			break;
2245		}
2246		return -1;
2247	}
2248	return ancount;
2249}
2250
2251/*
2252 * Formulate a normal query, send, and retrieve answer in supplied buffer.
2253 * Return the size of the response on success, -1 on error.
2254 * If enabled, implement search rules until answer or unrecoverable failure
2255 * is detected.  Error code, if any, is left in h_errno.
2256 */
2257static int
2258res_searchN(const char *name, struct res_target *target, res_state res)
2259{
2260	const char *cp, * const *domain;
2261	HEADER *hp;
2262	u_int dots;
2263	int trailing_dot, ret, saved_herrno;
2264	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
2265
2266	assert(name != NULL);
2267	assert(target != NULL);
2268
2269	hp = (HEADER *)(void *)target->answer;	/*XXX*/
2270
2271	errno = 0;
2272	h_errno = HOST_NOT_FOUND;	/* default, if we never query */
2273	dots = 0;
2274	for (cp = name; *cp; cp++)
2275		dots += (*cp == '.');
2276	trailing_dot = 0;
2277	if (cp > name && *--cp == '.')
2278		trailing_dot++;
2279
2280
2281        //fprintf(stderr, "res_searchN() name = '%s'\n", name);
2282
2283	/*
2284	 * if there aren't any dots, it could be a user-level alias
2285	 */
2286	if (!dots && (cp = __hostalias(name)) != NULL) {
2287		ret = res_queryN(cp, target, res);
2288		return ret;
2289	}
2290
2291	/*
2292	 * If there are dots in the name already, let's just give it a try
2293	 * 'as is'.  The threshold can be set with the "ndots" option.
2294	 */
2295	saved_herrno = -1;
2296	if (dots >= res->ndots) {
2297		ret = res_querydomainN(name, NULL, target, res);
2298		if (ret > 0)
2299			return (ret);
2300		saved_herrno = h_errno;
2301		tried_as_is++;
2302	}
2303
2304	/*
2305	 * We do at least one level of search if
2306	 *	- there is no dot and RES_DEFNAME is set, or
2307	 *	- there is at least one dot, there is no trailing dot,
2308	 *	  and RES_DNSRCH is set.
2309	 */
2310	if ((!dots && (res->options & RES_DEFNAMES)) ||
2311	    (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
2312		int done = 0;
2313
2314		for (domain = (const char * const *)res->dnsrch;
2315		   *domain && !done;
2316		   domain++) {
2317
2318			ret = res_querydomainN(name, *domain, target, res);
2319			if (ret > 0)
2320				return ret;
2321
2322			/*
2323			 * If no server present, give up.
2324			 * If name isn't found in this domain,
2325			 * keep trying higher domains in the search list
2326			 * (if that's enabled).
2327			 * On a NO_DATA error, keep trying, otherwise
2328			 * a wildcard entry of another type could keep us
2329			 * from finding this entry higher in the domain.
2330			 * If we get some other error (negative answer or
2331			 * server failure), then stop searching up,
2332			 * but try the input name below in case it's
2333			 * fully-qualified.
2334			 */
2335			if (errno == ECONNREFUSED) {
2336				h_errno = TRY_AGAIN;
2337				return -1;
2338			}
2339
2340			switch (h_errno) {
2341			case NO_DATA:
2342				got_nodata++;
2343				/* FALLTHROUGH */
2344			case HOST_NOT_FOUND:
2345				/* keep trying */
2346				break;
2347			case TRY_AGAIN:
2348				if (hp->rcode == SERVFAIL) {
2349					/* try next search element, if any */
2350					got_servfail++;
2351					break;
2352				}
2353				/* FALLTHROUGH */
2354			default:
2355				/* anything else implies that we're done */
2356				done++;
2357			}
2358			/*
2359			 * if we got here for some reason other than DNSRCH,
2360			 * we only wanted one iteration of the loop, so stop.
2361			 */
2362			if (!(res->options & RES_DNSRCH))
2363			        done++;
2364		}
2365	}
2366
2367	/*
2368	 * if we have not already tried the name "as is", do that now.
2369	 * note that we do this regardless of how many dots were in the
2370	 * name or whether it ends with a dot.
2371	 */
2372	if (!tried_as_is) {
2373		ret = res_querydomainN(name, NULL, target, res);
2374		if (ret > 0)
2375			return ret;
2376	}
2377
2378	/*
2379	 * if we got here, we didn't satisfy the search.
2380	 * if we did an initial full query, return that query's h_errno
2381	 * (note that we wouldn't be here if that query had succeeded).
2382	 * else if we ever got a nodata, send that back as the reason.
2383	 * else send back meaningless h_errno, that being the one from
2384	 * the last DNSRCH we did.
2385	 */
2386	if (saved_herrno != -1)
2387		h_errno = saved_herrno;
2388	else if (got_nodata)
2389		h_errno = NO_DATA;
2390	else if (got_servfail)
2391		h_errno = TRY_AGAIN;
2392	return -1;
2393}
2394
2395/*
2396 * Perform a call on res_query on the concatenation of name and domain,
2397 * removing a trailing dot from name if domain is NULL.
2398 */
2399static int
2400res_querydomainN(const char *name, const char *domain,
2401    struct res_target *target, res_state res)
2402{
2403	char nbuf[MAXDNAME];
2404	const char *longname = nbuf;
2405	size_t n, d;
2406
2407	assert(name != NULL);
2408	/* XXX: target may be NULL??? */
2409
2410#ifdef DEBUG
2411	if (res->options & RES_DEBUG)
2412		printf(";; res_querydomain(%s, %s)\n",
2413			name, domain?domain:"<Nil>");
2414#endif
2415	if (domain == NULL) {
2416		/*
2417		 * Check for trailing '.';
2418		 * copy without '.' if present.
2419		 */
2420		n = strlen(name);
2421		if (n + 1 > sizeof(nbuf)) {
2422			h_errno = NO_RECOVERY;
2423			return -1;
2424		}
2425		if (n > 0 && name[--n] == '.') {
2426			strncpy(nbuf, name, n);
2427			nbuf[n] = '\0';
2428		} else
2429			longname = name;
2430	} else {
2431		n = strlen(name);
2432		d = strlen(domain);
2433		if (n + 1 + d + 1 > sizeof(nbuf)) {
2434			h_errno = NO_RECOVERY;
2435			return -1;
2436		}
2437		snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
2438	}
2439	return res_queryN(longname, target, res);
2440}
2441