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