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