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