blob: 6fd825c38809afcf4b241190682f427d83900a76 [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"
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100110#include "private/bionic_defs.h"
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800111
Tom Marshall310e4a42016-06-17 16:38:12 -0700112#include "hosts_cache.h"
113
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -0700114typedef union sockaddr_union {
115 struct sockaddr generic;
116 struct sockaddr_in in;
117 struct sockaddr_in6 in6;
118} sockaddr_union;
119
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800120#define SUCCESS 0
121#define ANY 0
122#define YES 1
123#define NO 0
124
125static const char in_addrany[] = { 0, 0, 0, 0 };
126static const char in_loopback[] = { 127, 0, 0, 1 };
127#ifdef INET6
128static const char in6_addrany[] = {
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
130};
131static const char in6_loopback[] = {
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
133};
134#endif
135
Dan Willemsen7ec52b12016-11-28 17:02:25 -0800136#if defined(__ANDROID__)
Selim Gurun06e18312012-02-27 15:58:54 -0800137// This should be synchronized to ResponseCode.h
138static const int DnsProxyQueryResult = 222;
Dan Willemsen7ec52b12016-11-28 17:02:25 -0800139#endif
Selim Gurun06e18312012-02-27 15:58:54 -0800140
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800141static const struct afd {
142 int a_af;
143 int a_addrlen;
144 int a_socklen;
145 int a_off;
146 const char *a_addrany;
147 const char *a_loopback;
148 int a_scoped;
149} afdl [] = {
150#ifdef INET6
151 {PF_INET6, sizeof(struct in6_addr),
152 sizeof(struct sockaddr_in6),
153 offsetof(struct sockaddr_in6, sin6_addr),
154 in6_addrany, in6_loopback, 1},
155#endif
156 {PF_INET, sizeof(struct in_addr),
157 sizeof(struct sockaddr_in),
158 offsetof(struct sockaddr_in, sin_addr),
159 in_addrany, in_loopback, 0},
160 {0, 0, 0, 0, NULL, NULL, 0},
161};
162
163struct explore {
164 int e_af;
165 int e_socktype;
166 int e_protocol;
167 const char *e_protostr;
168 int e_wild;
169#define WILD_AF(ex) ((ex)->e_wild & 0x01)
170#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
171#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
172};
173
174static const struct explore explore[] = {
175#if 0
176 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
177#endif
178#ifdef INET6
179 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
180 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
181 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
182#endif
183 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
184 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
185 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
186 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
187 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
188 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
189 { -1, 0, 0, NULL, 0 },
190};
191
192#ifdef INET6
193#define PTON_MAX 16
194#else
195#define PTON_MAX 4
196#endif
197
198static const ns_src default_dns_files[] = {
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700199 { NSSRC_FILES, NS_SUCCESS },
200 { NSSRC_DNS, NS_SUCCESS },
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800201 { 0, 0 }
202};
203
Ben Schwartz47fb0e82018-01-31 13:35:03 -0500204#define MAXPACKET (8*1024)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800205
206typedef union {
207 HEADER hdr;
208 u_char buf[MAXPACKET];
209} querybuf;
210
211struct res_target {
212 struct res_target *next;
213 const char *name; /* domain name */
214 int qclass, qtype; /* class and type of query */
215 u_char *answer; /* buffer to put answer */
216 int anslen; /* size of answer buffer */
217 int n; /* result length */
218};
219
220static int str2number(const char *);
221static int explore_fqdn(const struct addrinfo *, const char *,
Erik Kline01e37c92015-06-25 14:27:34 +0900222 const char *, struct addrinfo **, const struct android_net_context *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800223static int explore_null(const struct addrinfo *,
224 const char *, struct addrinfo **);
225static int explore_numeric(const struct addrinfo *, const char *,
226 const char *, struct addrinfo **, const char *);
227static int explore_numeric_scope(const struct addrinfo *, const char *,
228 const char *, struct addrinfo **);
229static int get_canonname(const struct addrinfo *,
230 struct addrinfo *, const char *);
231static struct addrinfo *get_ai(const struct addrinfo *,
232 const struct afd *, const char *);
233static int get_portmatch(const struct addrinfo *, const char *);
234static int get_port(const struct addrinfo *, const char *, int);
235static const struct afd *find_afd(int);
236#ifdef INET6
237static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
238#endif
239
240static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
241 const struct addrinfo *);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800242static int _dns_getaddrinfo(void *, void *, va_list);
243static void _sethtent(FILE **);
244static void _endhtent(FILE **);
245static struct addrinfo *_gethtent(FILE **, const char *,
246 const struct addrinfo *);
247static int _files_getaddrinfo(void *, void *, va_list);
Erik Kline01e37c92015-06-25 14:27:34 +0900248static int _find_src_addr(const struct sockaddr *, struct sockaddr *, unsigned , uid_t);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800249
250static int res_queryN(const char *, struct res_target *, res_state);
251static int res_searchN(const char *, struct res_target *, res_state);
252static int res_querydomainN(const char *, const char *,
253 struct res_target *, res_state);
254
255static const char * const ai_errlist[] = {
256 "Success",
257 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
258 "Temporary failure in name resolution", /* EAI_AGAIN */
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700259 "Invalid value for ai_flags", /* EAI_BADFLAGS */
260 "Non-recoverable failure in name resolution", /* EAI_FAIL */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800261 "ai_family not supported", /* EAI_FAMILY */
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700262 "Memory allocation failure", /* EAI_MEMORY */
263 "No address associated with hostname", /* EAI_NODATA */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800264 "hostname nor servname provided, or not known", /* EAI_NONAME */
265 "servname not supported for ai_socktype", /* EAI_SERVICE */
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700266 "ai_socktype not supported", /* EAI_SOCKTYPE */
267 "System error returned in errno", /* EAI_SYSTEM */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800268 "Invalid value for hints", /* EAI_BADHINTS */
269 "Resolved protocol is unknown", /* EAI_PROTOCOL */
270 "Argument buffer overflow", /* EAI_OVERFLOW */
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700271 "Unknown error", /* EAI_MAX */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800272};
273
274/* XXX macros that make external reference is BAD. */
275
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700276#define GET_AI(ai, afd, addr) \
277do { \
278 /* external reference: pai, error, and label free */ \
279 (ai) = get_ai(pai, (afd), (addr)); \
280 if ((ai) == NULL) { \
281 error = EAI_MEMORY; \
282 goto free; \
283 } \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800284} while (/*CONSTCOND*/0)
285
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700286#define GET_PORT(ai, serv) \
287do { \
288 /* external reference: error and label free */ \
289 error = get_port((ai), (serv), 0); \
290 if (error != 0) \
291 goto free; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800292} while (/*CONSTCOND*/0)
293
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700294#define GET_CANONNAME(ai, str) \
295do { \
296 /* external reference: pai, error and label free */ \
297 error = get_canonname(pai, (ai), (str)); \
298 if (error != 0) \
299 goto free; \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800300} while (/*CONSTCOND*/0)
301
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700302#define ERR(err) \
303do { \
304 /* external reference: error, and label bad */ \
305 error = (err); \
306 goto bad; \
307 /*NOTREACHED*/ \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800308} while (/*CONSTCOND*/0)
309
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700310#define MATCH_FAMILY(x, y, w) \
311 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800312 (y) == PF_UNSPEC)))
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700313#define MATCH(x, y, w) \
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800314 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
315
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100316__BIONIC_WEAK_FOR_NATIVE_BRIDGE
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800317const char *
318gai_strerror(int ecode)
319{
320 if (ecode < 0 || ecode > EAI_MAX)
321 ecode = EAI_MAX;
322 return ai_errlist[ecode];
323}
324
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100325__BIONIC_WEAK_FOR_NATIVE_BRIDGE
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800326void
327freeaddrinfo(struct addrinfo *ai)
328{
329 struct addrinfo *next;
330
Elliott Hughesa9209d72016-09-16 18:16:47 -0700331#if defined(__BIONIC__)
Elliott Hughesc62a4b52015-01-08 17:28:46 -0800332 if (ai == NULL) return;
333#else
334 _DIAGASSERT(ai != NULL);
335#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800336
337 do {
338 next = ai->ai_next;
339 if (ai->ai_canonname)
340 free(ai->ai_canonname);
341 /* no need to free(ai->ai_addr) */
342 free(ai);
343 ai = next;
344 } while (ai);
345}
346
347static int
348str2number(const char *p)
349{
350 char *ep;
351 unsigned long v;
352
353 assert(p != NULL);
354
355 if (*p == '\0')
356 return -1;
357 ep = NULL;
358 errno = 0;
359 v = strtoul(p, &ep, 10);
360 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
361 return v;
362 else
363 return -1;
364}
365
Lorenzo Colittiba96e302011-01-14 12:26:05 -0800366/*
Lorenzo Colittiba96e302011-01-14 12:26:05 -0800367 * The following functions determine whether IPv4 or IPv6 connectivity is
368 * available in order to implement AI_ADDRCONFIG.
369 *
370 * Strictly speaking, AI_ADDRCONFIG should not look at whether connectivity is
371 * available, but whether addresses of the specified family are "configured
372 * on the local system". However, bionic doesn't currently support getifaddrs,
373 * so checking for connectivity is the next best thing.
374 */
375static int
Erik Kline01e37c92015-06-25 14:27:34 +0900376_have_ipv6(unsigned mark, uid_t uid) {
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700377 static const struct sockaddr_in6 sin6_test = {
378 .sin6_family = AF_INET6,
379 .sin6_addr.s6_addr = { // 2000::
380 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
381 };
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500382 sockaddr_union addr = { .in6 = sin6_test };
Erik Kline01e37c92015-06-25 14:27:34 +0900383 return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
Lorenzo Colittiba96e302011-01-14 12:26:05 -0800384}
385
386static int
Erik Kline01e37c92015-06-25 14:27:34 +0900387_have_ipv4(unsigned mark, uid_t uid) {
Lorenzo Colittib82532d2011-09-28 19:28:32 -0700388 static const struct sockaddr_in sin_test = {
389 .sin_family = AF_INET,
390 .sin_addr.s_addr = __constant_htonl(0x08080808L) // 8.8.8.8
391 };
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500392 sockaddr_union addr = { .in = sin_test };
Erik Kline01e37c92015-06-25 14:27:34 +0900393 return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
Lorenzo Colitti3d8f4ad2009-08-03 22:36:31 -0700394}
395
Elliott Hughes55293c12014-11-12 17:00:30 -0800396bool readBE32(FILE* fp, int32_t* result) {
397 int32_t tmp;
398 if (fread(&tmp, sizeof(tmp), 1, fp) != 1) {
399 return false;
400 }
401 *result = ntohl(tmp);
402 return true;
403}
404
Dan Willemsen7ec52b12016-11-28 17:02:25 -0800405#if defined(__ANDROID__)
Mattias Falkc63e5902011-08-23 14:34:14 +0200406// Returns 0 on success, else returns on error.
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700407static int
408android_getaddrinfo_proxy(
409 const char *hostname, const char *servname,
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500410 const struct addrinfo *hints, struct addrinfo **res, unsigned netid)
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700411{
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700412 int success = 0;
413
414 // Clear this at start, as we use its non-NULLness later (in the
415 // error path) to decide if we have to free up any memory we
416 // allocated in the process (before failing).
417 *res = NULL;
418
Mattias Falkc63e5902011-08-23 14:34:14 +0200419 // Bogus things we can't serialize. Don't use the proxy. These will fail - let them.
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700420 if ((hostname != NULL &&
421 strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) ||
422 (servname != NULL &&
423 strcspn(servname, " \n\r\t^'\"") != strlen(servname))) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200424 return EAI_NODATA;
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700425 }
426
Elliott Hughes9773fa32014-12-10 14:56:46 -0800427 FILE* proxy = android_open_proxy();
428 if (proxy == NULL) {
429 return EAI_SYSTEM;
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700430 }
431
Paul Jensen559c7842014-05-15 14:43:07 -0400432 netid = __netdClientDispatch.netIdForResolv(netid);
433
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700434 // Send the request.
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500435 if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d %u",
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700436 hostname == NULL ? "^" : hostname,
437 servname == NULL ? "^" : servname,
438 hints == NULL ? -1 : hints->ai_flags,
439 hints == NULL ? -1 : hints->ai_family,
440 hints == NULL ? -1 : hints->ai_socktype,
Mattias Falkc63e5902011-08-23 14:34:14 +0200441 hints == NULL ? -1 : hints->ai_protocol,
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500442 netid) < 0) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700443 goto exit;
444 }
445 // literal NULL byte at end, required by FrameworkListener
446 if (fputc(0, proxy) == EOF ||
447 fflush(proxy) != 0) {
448 goto exit;
449 }
450
Robert Greenwaltc59ba452012-03-09 11:34:27 -0800451 char buf[4];
Selim Gurun06e18312012-02-27 15:58:54 -0800452 // read result code for gethostbyaddr
453 if (fread(buf, 1, sizeof(buf), proxy) != sizeof(buf)) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700454 goto exit;
455 }
456
Selim Gurun06e18312012-02-27 15:58:54 -0800457 int result_code = (int)strtol(buf, NULL, 10);
458 // verify the code itself
Erik Kline01e37c92015-06-25 14:27:34 +0900459 if (result_code != DnsProxyQueryResult) {
Mattias Falkc63e5902011-08-23 14:34:14 +0200460 fread(buf, 1, sizeof(buf), proxy);
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700461 goto exit;
462 }
463
464 struct addrinfo* ai = NULL;
465 struct addrinfo** nextres = res;
466 while (1) {
Elliott Hughes55293c12014-11-12 17:00:30 -0800467 int32_t have_more;
468 if (!readBE32(proxy, &have_more)) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700469 break;
470 }
Elliott Hughes55293c12014-11-12 17:00:30 -0800471 if (have_more == 0) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700472 success = 1;
473 break;
474 }
475
Elliott Hughes55293c12014-11-12 17:00:30 -0800476 struct addrinfo* ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700477 if (ai == NULL) {
478 break;
479 }
Elliott Hughes55293c12014-11-12 17:00:30 -0800480 ai->ai_addr = (struct sockaddr*)(ai + 1);
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700481
Elliott Hughes55293c12014-11-12 17:00:30 -0800482 // struct addrinfo {
483 // int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
484 // int ai_family; /* PF_xxx */
485 // int ai_socktype; /* SOCK_xxx */
486 // int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
487 // socklen_t ai_addrlen; /* length of ai_addr */
488 // char *ai_canonname; /* canonical name for hostname */
489 // struct sockaddr *ai_addr; /* binary address */
490 // struct addrinfo *ai_next; /* next structure in linked list */
491 // };
492
493 // Read the struct piece by piece because we might be a 32-bit process
494 // talking to a 64-bit netd.
495 int32_t addr_len;
496 bool success =
497 readBE32(proxy, &ai->ai_flags) &&
498 readBE32(proxy, &ai->ai_family) &&
499 readBE32(proxy, &ai->ai_socktype) &&
500 readBE32(proxy, &ai->ai_protocol) &&
501 readBE32(proxy, &addr_len);
502 if (!success) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700503 break;
504 }
505
Elliott Hughes55293c12014-11-12 17:00:30 -0800506 // Set ai_addrlen and read the ai_addr data.
507 ai->ai_addrlen = addr_len;
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700508 if (addr_len != 0) {
Elliott Hughes55293c12014-11-12 17:00:30 -0800509 if ((size_t) addr_len > sizeof(struct sockaddr_storage)) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700510 // Bogus; too big.
511 break;
512 }
Elliott Hughes55293c12014-11-12 17:00:30 -0800513 if (fread(ai->ai_addr, addr_len, 1, proxy) != 1) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700514 break;
515 }
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700516 }
517
Elliott Hughes55293c12014-11-12 17:00:30 -0800518 // The string for ai_cannonname.
519 int32_t name_len;
520 if (!readBE32(proxy, &name_len)) {
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700521 break;
522 }
523 if (name_len != 0) {
524 ai->ai_canonname = (char*) malloc(name_len);
525 if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) {
526 break;
527 }
528 if (ai->ai_canonname[name_len - 1] != '\0') {
529 // The proxy should be returning this
530 // NULL-terminated.
531 break;
532 }
533 }
534
535 *nextres = ai;
536 nextres = &ai->ai_next;
537 ai = NULL;
538 }
539
540 if (ai != NULL) {
541 // Clean up partially-built addrinfo that we never ended up
542 // attaching to the response.
543 freeaddrinfo(ai);
544 }
545exit:
546 if (proxy != NULL) {
547 fclose(proxy);
548 }
549
550 if (success) {
551 return 0;
552 }
553
Mattias Falkc63e5902011-08-23 14:34:14 +0200554 // Proxy failed;
555 // clean up memory we might've allocated.
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700556 if (*res) {
557 freeaddrinfo(*res);
558 *res = NULL;
559 }
Mattias Falkc63e5902011-08-23 14:34:14 +0200560 return EAI_NODATA;
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700561}
Dan Willemsen7ec52b12016-11-28 17:02:25 -0800562#endif
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700563
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100564__BIONIC_WEAK_FOR_NATIVE_BRIDGE
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800565int
566getaddrinfo(const char *hostname, const char *servname,
567 const struct addrinfo *hints, struct addrinfo **res)
568{
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500569 return android_getaddrinfofornet(hostname, servname, hints, NETID_UNSET, MARK_UNSET, res);
Mattias Falkc63e5902011-08-23 14:34:14 +0200570}
571
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100572__BIONIC_WEAK_FOR_NATIVE_BRIDGE
Mattias Falkc63e5902011-08-23 14:34:14 +0200573int
Szymon Jakubczakea9bf672014-02-14 17:07:23 -0500574android_getaddrinfofornet(const char *hostname, const char *servname,
575 const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
Mattias Falkc63e5902011-08-23 14:34:14 +0200576{
Erik Kline01e37c92015-06-25 14:27:34 +0900577 struct android_net_context netcontext = {
578 .app_netid = netid,
579 .app_mark = mark,
580 .dns_netid = netid,
581 .dns_mark = mark,
582 .uid = NET_CONTEXT_INVALID_UID,
583 };
584 return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
585}
586
Victor Khimenko5a6b9562018-03-14 17:41:22 +0100587__BIONIC_WEAK_FOR_NATIVE_BRIDGE
Erik Kline01e37c92015-06-25 14:27:34 +0900588int
589android_getaddrinfofornetcontext(const char *hostname, const char *servname,
590 const struct addrinfo *hints, const struct android_net_context *netcontext,
591 struct addrinfo **res)
592{
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800593 struct addrinfo sentinel;
594 struct addrinfo *cur;
595 int error = 0;
596 struct addrinfo ai;
597 struct addrinfo ai0;
598 struct addrinfo *pai;
599 const struct explore *ex;
600
601 /* hostname is allowed to be NULL */
602 /* servname is allowed to be NULL */
603 /* hints is allowed to be NULL */
604 assert(res != NULL);
Erik Kline01e37c92015-06-25 14:27:34 +0900605 assert(netcontext != NULL);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800606 memset(&sentinel, 0, sizeof(sentinel));
607 cur = &sentinel;
608 pai = &ai;
609 pai->ai_flags = 0;
610 pai->ai_family = PF_UNSPEC;
611 pai->ai_socktype = ANY;
612 pai->ai_protocol = ANY;
613 pai->ai_addrlen = 0;
614 pai->ai_canonname = NULL;
615 pai->ai_addr = NULL;
616 pai->ai_next = NULL;
617
618 if (hostname == NULL && servname == NULL)
619 return EAI_NONAME;
620 if (hints) {
621 /* error check for hints */
622 if (hints->ai_addrlen || hints->ai_canonname ||
623 hints->ai_addr || hints->ai_next)
624 ERR(EAI_BADHINTS); /* xxx */
625 if (hints->ai_flags & ~AI_MASK)
626 ERR(EAI_BADFLAGS);
627 switch (hints->ai_family) {
628 case PF_UNSPEC:
629 case PF_INET:
630#ifdef INET6
631 case PF_INET6:
632#endif
633 break;
634 default:
635 ERR(EAI_FAMILY);
636 }
637 memcpy(pai, hints, sizeof(*pai));
638
639 /*
640 * if both socktype/protocol are specified, check if they
641 * are meaningful combination.
642 */
643 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
644 for (ex = explore; ex->e_af >= 0; ex++) {
645 if (pai->ai_family != ex->e_af)
646 continue;
647 if (ex->e_socktype == ANY)
648 continue;
649 if (ex->e_protocol == ANY)
650 continue;
651 if (pai->ai_socktype == ex->e_socktype
652 && pai->ai_protocol != ex->e_protocol) {
653 ERR(EAI_BADHINTS);
654 }
655 }
656 }
657 }
658
659 /*
660 * check for special cases. (1) numeric servname is disallowed if
661 * socktype/protocol are left unspecified. (2) servname is disallowed
662 * for raw and other inet{,6} sockets.
663 */
664 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
665#ifdef PF_INET6
666 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
667#endif
668 ) {
669 ai0 = *pai; /* backup *pai */
670
671 if (pai->ai_family == PF_UNSPEC) {
672#ifdef PF_INET6
673 pai->ai_family = PF_INET6;
674#else
675 pai->ai_family = PF_INET;
676#endif
677 }
678 error = get_portmatch(pai, servname);
679 if (error)
680 ERR(error);
681
682 *pai = ai0;
683 }
684
685 ai0 = *pai;
686
687 /* NULL hostname, or numeric hostname */
688 for (ex = explore; ex->e_af >= 0; ex++) {
689 *pai = ai0;
690
691 /* PF_UNSPEC entries are prepared for DNS queries only */
692 if (ex->e_af == PF_UNSPEC)
693 continue;
694
695 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
696 continue;
697 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
698 continue;
699 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
700 continue;
701
702 if (pai->ai_family == PF_UNSPEC)
703 pai->ai_family = ex->e_af;
704 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
705 pai->ai_socktype = ex->e_socktype;
706 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
707 pai->ai_protocol = ex->e_protocol;
708
709 if (hostname == NULL)
710 error = explore_null(pai, servname, &cur->ai_next);
711 else
712 error = explore_numeric_scope(pai, hostname, servname,
713 &cur->ai_next);
714
715 if (error)
716 goto free;
717
718 while (cur->ai_next)
719 cur = cur->ai_next;
720 }
721
722 /*
723 * XXX
724 * If numeric representation of AF1 can be interpreted as FQDN
725 * representation of AF2, we need to think again about the code below.
726 */
727 if (sentinel.ai_next)
728 goto good;
729
730 if (hostname == NULL)
731 ERR(EAI_NODATA);
732 if (pai->ai_flags & AI_NUMERICHOST)
733 ERR(EAI_NONAME);
734
Elliott Hughes9773fa32014-12-10 14:56:46 -0800735#if defined(__ANDROID__)
Erik Kline01e37c92015-06-25 14:27:34 +0900736 int gai_error = android_getaddrinfo_proxy(
737 hostname, servname, hints, res, netcontext->app_netid);
Elliott Hughes9773fa32014-12-10 14:56:46 -0800738 if (gai_error != EAI_SYSTEM) {
739 return gai_error;
Mattias Falkc63e5902011-08-23 14:34:14 +0200740 }
Elliott Hughes9773fa32014-12-10 14:56:46 -0800741#endif
Brad Fitzpatricka1dbf0b2010-10-27 10:36:36 -0700742
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800743 /*
744 * hostname as alphabetical name.
745 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
746 * outer loop by AFs.
747 */
748 for (ex = explore; ex->e_af >= 0; ex++) {
749 *pai = ai0;
750
751 /* require exact match for family field */
752 if (pai->ai_family != ex->e_af)
753 continue;
754
755 if (!MATCH(pai->ai_socktype, ex->e_socktype,
756 WILD_SOCKTYPE(ex))) {
757 continue;
758 }
759 if (!MATCH(pai->ai_protocol, ex->e_protocol,
760 WILD_PROTOCOL(ex))) {
761 continue;
762 }
763
764 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
765 pai->ai_socktype = ex->e_socktype;
766 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
767 pai->ai_protocol = ex->e_protocol;
768
Erik Kline01e37c92015-06-25 14:27:34 +0900769 error = explore_fqdn(
770 pai, hostname, servname, &cur->ai_next, netcontext);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800771
772 while (cur && cur->ai_next)
773 cur = cur->ai_next;
774 }
775
776 /* XXX */
777 if (sentinel.ai_next)
778 error = 0;
779
780 if (error)
781 goto free;
782 if (error == 0) {
783 if (sentinel.ai_next) {
784 good:
785 *res = sentinel.ai_next;
786 return SUCCESS;
787 } else
788 error = EAI_FAIL;
789 }
790 free:
791 bad:
792 if (sentinel.ai_next)
793 freeaddrinfo(sentinel.ai_next);
794 *res = NULL;
795 return error;
796}
797
798/*
799 * FQDN hostname, DNS lookup
800 */
801static int
802explore_fqdn(const struct addrinfo *pai, const char *hostname,
Erik Kline01e37c92015-06-25 14:27:34 +0900803 const char *servname, struct addrinfo **res,
804 const struct android_net_context *netcontext)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800805{
806 struct addrinfo *result;
807 struct addrinfo *cur;
808 int error = 0;
809 static const ns_dtab dtab[] = {
810 NS_FILES_CB(_files_getaddrinfo, NULL)
811 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
812 NS_NIS_CB(_yp_getaddrinfo, NULL)
813 { 0, 0, 0 }
814 };
815
816 assert(pai != NULL);
817 /* hostname may be NULL */
818 /* servname may be NULL */
819 assert(res != NULL);
820
821 result = NULL;
822
823 /*
824 * if the servname does not match socktype/protocol, ignore it.
825 */
826 if (get_portmatch(pai, servname) != 0)
827 return 0;
828
829 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
Erik Kline01e37c92015-06-25 14:27:34 +0900830 default_dns_files, hostname, pai, netcontext)) {
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800831 case NS_TRYAGAIN:
832 error = EAI_AGAIN;
833 goto free;
834 case NS_UNAVAIL:
835 error = EAI_FAIL;
836 goto free;
837 case NS_NOTFOUND:
838 error = EAI_NODATA;
839 goto free;
840 case NS_SUCCESS:
841 error = 0;
842 for (cur = result; cur; cur = cur->ai_next) {
843 GET_PORT(cur, servname);
844 /* canonname should be filled already */
845 }
846 break;
847 }
848
849 *res = result;
850
851 return 0;
852
853free:
854 if (result)
855 freeaddrinfo(result);
856 return error;
857}
858
859/*
860 * hostname == NULL.
861 * passive socket -> anyaddr (0.0.0.0 or ::)
862 * non-passive socket -> localhost (127.0.0.1 or ::1)
863 */
864static int
865explore_null(const struct addrinfo *pai, const char *servname,
866 struct addrinfo **res)
867{
868 int s;
869 const struct afd *afd;
870 struct addrinfo *cur;
871 struct addrinfo sentinel;
872 int error;
873
874 assert(pai != NULL);
875 /* servname may be NULL */
876 assert(res != NULL);
877
878 *res = NULL;
879 sentinel.ai_next = NULL;
880 cur = &sentinel;
881
882 /*
883 * filter out AFs that are not supported by the kernel
884 * XXX errno?
885 */
Nick Kralevich1781ed72014-06-29 20:46:17 -0700886 s = socket(pai->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800887 if (s < 0) {
888 if (errno != EMFILE)
889 return 0;
890 } else
891 close(s);
892
893 /*
894 * if the servname does not match socktype/protocol, ignore it.
895 */
896 if (get_portmatch(pai, servname) != 0)
897 return 0;
898
899 afd = find_afd(pai->ai_family);
900 if (afd == NULL)
901 return 0;
902
903 if (pai->ai_flags & AI_PASSIVE) {
904 GET_AI(cur->ai_next, afd, afd->a_addrany);
905 /* xxx meaningless?
906 * GET_CANONNAME(cur->ai_next, "anyaddr");
907 */
908 GET_PORT(cur->ai_next, servname);
909 } else {
910 GET_AI(cur->ai_next, afd, afd->a_loopback);
911 /* xxx meaningless?
912 * GET_CANONNAME(cur->ai_next, "localhost");
913 */
914 GET_PORT(cur->ai_next, servname);
915 }
916 cur = cur->ai_next;
917
918 *res = sentinel.ai_next;
919 return 0;
920
921free:
922 if (sentinel.ai_next)
923 freeaddrinfo(sentinel.ai_next);
924 return error;
925}
926
927/*
928 * numeric hostname
929 */
930static int
931explore_numeric(const struct addrinfo *pai, const char *hostname,
932 const char *servname, struct addrinfo **res, const char *canonname)
933{
934 const struct afd *afd;
935 struct addrinfo *cur;
936 struct addrinfo sentinel;
937 int error;
938 char pton[PTON_MAX];
939
940 assert(pai != NULL);
941 /* hostname may be NULL */
942 /* servname may be NULL */
943 assert(res != NULL);
944
945 *res = NULL;
946 sentinel.ai_next = NULL;
947 cur = &sentinel;
948
949 /*
950 * if the servname does not match socktype/protocol, ignore it.
951 */
952 if (get_portmatch(pai, servname) != 0)
953 return 0;
954
955 afd = find_afd(pai->ai_family);
956 if (afd == NULL)
957 return 0;
958
959 switch (afd->a_af) {
960#if 0 /*X/Open spec*/
961 case AF_INET:
962 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
963 if (pai->ai_family == afd->a_af ||
964 pai->ai_family == PF_UNSPEC /*?*/) {
965 GET_AI(cur->ai_next, afd, pton);
966 GET_PORT(cur->ai_next, servname);
967 if ((pai->ai_flags & AI_CANONNAME)) {
968 /*
969 * Set the numeric address itself as
970 * the canonical name, based on a
971 * clarification in rfc2553bis-03.
972 */
973 GET_CANONNAME(cur->ai_next, canonname);
974 }
975 while (cur && cur->ai_next)
976 cur = cur->ai_next;
977 } else
978 ERR(EAI_FAMILY); /*xxx*/
979 }
980 break;
981#endif
982 default:
983 if (inet_pton(afd->a_af, hostname, pton) == 1) {
984 if (pai->ai_family == afd->a_af ||
985 pai->ai_family == PF_UNSPEC /*?*/) {
986 GET_AI(cur->ai_next, afd, pton);
987 GET_PORT(cur->ai_next, servname);
988 if ((pai->ai_flags & AI_CANONNAME)) {
989 /*
990 * Set the numeric address itself as
991 * the canonical name, based on a
992 * clarification in rfc2553bis-03.
993 */
994 GET_CANONNAME(cur->ai_next, canonname);
995 }
996 while (cur->ai_next)
997 cur = cur->ai_next;
998 } else
999 ERR(EAI_FAMILY); /*xxx*/
1000 }
1001 break;
1002 }
1003
1004 *res = sentinel.ai_next;
1005 return 0;
1006
1007free:
1008bad:
1009 if (sentinel.ai_next)
1010 freeaddrinfo(sentinel.ai_next);
1011 return error;
1012}
1013
1014/*
1015 * numeric hostname with scope
1016 */
1017static int
1018explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
1019 const char *servname, struct addrinfo **res)
1020{
1021#if !defined(SCOPE_DELIMITER) || !defined(INET6)
1022 return explore_numeric(pai, hostname, servname, res, hostname);
1023#else
1024 const struct afd *afd;
1025 struct addrinfo *cur;
1026 int error;
1027 char *cp, *hostname2 = NULL, *scope, *addr;
1028 struct sockaddr_in6 *sin6;
1029
1030 assert(pai != NULL);
1031 /* hostname may be NULL */
1032 /* servname may be NULL */
1033 assert(res != NULL);
1034
1035 /*
1036 * if the servname does not match socktype/protocol, ignore it.
1037 */
1038 if (get_portmatch(pai, servname) != 0)
1039 return 0;
1040
1041 afd = find_afd(pai->ai_family);
1042 if (afd == NULL)
1043 return 0;
1044
1045 if (!afd->a_scoped)
1046 return explore_numeric(pai, hostname, servname, res, hostname);
1047
1048 cp = strchr(hostname, SCOPE_DELIMITER);
1049 if (cp == NULL)
1050 return explore_numeric(pai, hostname, servname, res, hostname);
1051
1052 /*
1053 * Handle special case of <scoped_address><delimiter><scope id>
1054 */
1055 hostname2 = strdup(hostname);
1056 if (hostname2 == NULL)
1057 return EAI_MEMORY;
1058 /* terminate at the delimiter */
1059 hostname2[cp - hostname] = '\0';
1060 addr = hostname2;
1061 scope = cp + 1;
1062
1063 error = explore_numeric(pai, addr, servname, res, hostname);
1064 if (error == 0) {
1065 u_int32_t scopeid;
1066
1067 for (cur = *res; cur; cur = cur->ai_next) {
1068 if (cur->ai_family != AF_INET6)
1069 continue;
1070 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
1071 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
1072 free(hostname2);
1073 return(EAI_NODATA); /* XXX: is return OK? */
1074 }
1075 sin6->sin6_scope_id = scopeid;
1076 }
1077 }
1078
1079 free(hostname2);
1080
1081 return error;
1082#endif
1083}
1084
1085static int
1086get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
1087{
1088
1089 assert(pai != NULL);
1090 assert(ai != NULL);
1091 assert(str != NULL);
1092
1093 if ((pai->ai_flags & AI_CANONNAME) != 0) {
1094 ai->ai_canonname = strdup(str);
1095 if (ai->ai_canonname == NULL)
1096 return EAI_MEMORY;
1097 }
1098 return 0;
1099}
1100
1101static struct addrinfo *
1102get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
1103{
1104 char *p;
1105 struct addrinfo *ai;
1106
1107 assert(pai != NULL);
1108 assert(afd != NULL);
1109 assert(addr != NULL);
1110
1111 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
1112 + (afd->a_socklen));
1113 if (ai == NULL)
1114 return NULL;
1115
1116 memcpy(ai, pai, sizeof(struct addrinfo));
1117 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
1118 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
1119
1120#ifdef HAVE_SA_LEN
1121 ai->ai_addr->sa_len = afd->a_socklen;
1122#endif
1123
1124 ai->ai_addrlen = afd->a_socklen;
1125#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__)
1126 ai->__ai_pad0 = 0;
1127#endif
1128 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1129 p = (char *)(void *)(ai->ai_addr);
1130 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
1131 return ai;
1132}
1133
1134static int
1135get_portmatch(const struct addrinfo *ai, const char *servname)
1136{
1137
1138 assert(ai != NULL);
1139 /* servname may be NULL */
1140
1141 return get_port(ai, servname, 1);
1142}
1143
1144static int
1145get_port(const struct addrinfo *ai, const char *servname, int matchonly)
1146{
1147 const char *proto;
1148 struct servent *sp;
1149 int port;
1150 int allownumeric;
1151
1152 assert(ai != NULL);
1153 /* servname may be NULL */
1154
1155 if (servname == NULL)
1156 return 0;
1157 switch (ai->ai_family) {
1158 case AF_INET:
1159#ifdef AF_INET6
1160 case AF_INET6:
1161#endif
1162 break;
1163 default:
1164 return 0;
1165 }
1166
1167 switch (ai->ai_socktype) {
1168 case SOCK_RAW:
1169 return EAI_SERVICE;
1170 case SOCK_DGRAM:
1171 case SOCK_STREAM:
1172 allownumeric = 1;
1173 break;
1174 case ANY:
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001175#if 1 /* ANDROID-SPECIFIC CHANGE TO MATCH GLIBC */
David 'Digit' Turner5e563702009-05-05 15:50:24 +02001176 allownumeric = 1;
1177#else
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001178 allownumeric = 0;
David 'Digit' Turner5e563702009-05-05 15:50:24 +02001179#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001180 break;
1181 default:
1182 return EAI_SOCKTYPE;
1183 }
1184
1185 port = str2number(servname);
1186 if (port >= 0) {
1187 if (!allownumeric)
1188 return EAI_SERVICE;
1189 if (port < 0 || port > 65535)
1190 return EAI_SERVICE;
1191 port = htons(port);
1192 } else {
1193 if (ai->ai_flags & AI_NUMERICSERV)
1194 return EAI_NONAME;
1195
1196 switch (ai->ai_socktype) {
1197 case SOCK_DGRAM:
1198 proto = "udp";
1199 break;
1200 case SOCK_STREAM:
1201 proto = "tcp";
1202 break;
1203 default:
1204 proto = NULL;
1205 break;
1206 }
1207
1208 if ((sp = getservbyname(servname, proto)) == NULL)
1209 return EAI_SERVICE;
1210 port = sp->s_port;
1211 }
1212
1213 if (!matchonly) {
1214 switch (ai->ai_family) {
1215 case AF_INET:
1216 ((struct sockaddr_in *)(void *)
1217 ai->ai_addr)->sin_port = port;
1218 break;
1219#ifdef INET6
1220 case AF_INET6:
1221 ((struct sockaddr_in6 *)(void *)
1222 ai->ai_addr)->sin6_port = port;
1223 break;
1224#endif
1225 }
1226 }
1227
1228 return 0;
1229}
1230
1231static const struct afd *
1232find_afd(int af)
1233{
1234 const struct afd *afd;
1235
1236 if (af == PF_UNSPEC)
1237 return NULL;
1238 for (afd = afdl; afd->a_af; afd++) {
1239 if (afd->a_af == af)
1240 return afd;
1241 }
1242 return NULL;
1243}
1244
1245#ifdef INET6
1246/* convert a string to a scope identifier. XXX: IPv6 specific */
1247static int
1248ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
1249{
1250 u_long lscopeid;
1251 struct in6_addr *a6;
1252 char *ep;
1253
1254 assert(scope != NULL);
1255 assert(sin6 != NULL);
1256 assert(scopeid != NULL);
1257
1258 a6 = &sin6->sin6_addr;
1259
1260 /* empty scopeid portion is invalid */
1261 if (*scope == '\0')
1262 return -1;
1263
1264 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1265 /*
1266 * We currently assume a one-to-one mapping between links
1267 * and interfaces, so we simply use interface indices for
1268 * like-local scopes.
1269 */
1270 *scopeid = if_nametoindex(scope);
1271 if (*scopeid == 0)
1272 goto trynumeric;
1273 return 0;
1274 }
1275
1276 /* still unclear about literal, allow numeric only - placeholder */
1277 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1278 goto trynumeric;
1279 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1280 goto trynumeric;
1281 else
1282 goto trynumeric; /* global */
1283
1284 /* try to convert to a numeric id as a last resort */
1285 trynumeric:
1286 errno = 0;
1287 lscopeid = strtoul(scope, &ep, 10);
1288 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1289 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1290 return 0;
1291 else
1292 return -1;
1293}
1294#endif
1295
1296/* code duplicate with gethnamaddr.c */
1297
1298static const char AskedForGot[] =
1299 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1300
Elliott Hughes87c0dba2016-11-14 13:56:32 -08001301#define BOUNDED_INCR(x) \
1302 do { \
1303 BOUNDS_CHECK(cp, x); \
1304 cp += (x); \
1305 } while (/*CONSTCOND*/0)
1306
1307#define BOUNDS_CHECK(ptr, count) \
1308 do { \
1309 if (eom - (ptr) < (count)) { h_errno = NO_RECOVERY; return NULL; } \
1310 } while (/*CONSTCOND*/0)
1311
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001312static 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;
Elliott Hughes87c0dba2016-11-14 13:56:32 -08001357 cp = answer->buf;
1358 BOUNDED_INCR(HFIXEDSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001359 if (qdcount != 1) {
1360 h_errno = NO_RECOVERY;
1361 return (NULL);
1362 }
1363 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1364 if ((n < 0) || !(*name_ok)(bp)) {
1365 h_errno = NO_RECOVERY;
1366 return (NULL);
1367 }
Elliott Hughes87c0dba2016-11-14 13:56:32 -08001368 BOUNDED_INCR(n + QFIXEDSZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001369 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1370 /* res_send() has already verified that the query name is the
1371 * same as the one we sent; this just gets the expanded name
1372 * (i.e., with the succeeding search-domain tacked on).
1373 */
1374 n = strlen(bp) + 1; /* for the \0 */
1375 if (n >= MAXHOSTNAMELEN) {
1376 h_errno = NO_RECOVERY;
1377 return (NULL);
1378 }
1379 canonname = bp;
1380 bp += n;
1381 /* The qname can be abbreviated, but h_name is now absolute. */
1382 qname = canonname;
1383 }
1384 haveanswer = 0;
1385 had_error = 0;
1386 while (ancount-- > 0 && cp < eom && !had_error) {
1387 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1388 if ((n < 0) || !(*name_ok)(bp)) {
1389 had_error++;
1390 continue;
1391 }
1392 cp += n; /* name */
Elliott Hughes87c0dba2016-11-14 13:56:32 -08001393 BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001394 type = _getshort(cp);
Lorenzo Colittib82532d2011-09-28 19:28:32 -07001395 cp += INT16SZ; /* type */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001396 class = _getshort(cp);
Lorenzo Colittib82532d2011-09-28 19:28:32 -07001397 cp += INT16SZ + INT32SZ; /* class, TTL */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001398 n = _getshort(cp);
1399 cp += INT16SZ; /* len */
Elliott Hughes87c0dba2016-11-14 13:56:32 -08001400 BOUNDS_CHECK(cp, n);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001401 if (class != C_IN) {
1402 /* XXX - debug? syslog? */
1403 cp += n;
1404 continue; /* XXX - had_error++ ? */
1405 }
1406 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1407 type == T_CNAME) {
1408 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1409 if ((n < 0) || !(*name_ok)(tbuf)) {
1410 had_error++;
1411 continue;
1412 }
1413 cp += n;
1414 /* Get canonical name. */
1415 n = strlen(tbuf) + 1; /* for the \0 */
1416 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1417 had_error++;
1418 continue;
1419 }
1420 strlcpy(bp, tbuf, (size_t)(ep - bp));
1421 canonname = bp;
1422 bp += n;
1423 continue;
1424 }
1425 if (qtype == T_ANY) {
1426 if (!(type == T_A || type == T_AAAA)) {
1427 cp += n;
1428 continue;
1429 }
1430 } else if (type != qtype) {
1431 if (type != T_KEY && type != T_SIG)
1432 syslog(LOG_NOTICE|LOG_AUTH,
1433 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1434 qname, p_class(C_IN), p_type(qtype),
1435 p_type(type));
1436 cp += n;
1437 continue; /* XXX - had_error++ ? */
1438 }
1439 switch (type) {
1440 case T_A:
1441 case T_AAAA:
1442 if (strcasecmp(canonname, bp) != 0) {
1443 syslog(LOG_NOTICE|LOG_AUTH,
1444 AskedForGot, canonname, bp);
1445 cp += n;
1446 continue; /* XXX - had_error++ ? */
1447 }
1448 if (type == T_A && n != INADDRSZ) {
1449 cp += n;
1450 continue;
1451 }
1452 if (type == T_AAAA && n != IN6ADDRSZ) {
1453 cp += n;
1454 continue;
1455 }
1456 if (type == T_AAAA) {
1457 struct in6_addr in6;
1458 memcpy(&in6, cp, IN6ADDRSZ);
1459 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1460 cp += n;
1461 continue;
1462 }
1463 }
1464 if (!haveanswer) {
1465 int nn;
1466
1467 canonname = bp;
1468 nn = strlen(bp) + 1; /* for the \0 */
1469 bp += nn;
1470 }
1471
1472 /* don't overwrite pai */
1473 ai = *pai;
1474 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1475 afd = find_afd(ai.ai_family);
1476 if (afd == NULL) {
1477 cp += n;
1478 continue;
1479 }
1480 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1481 if (cur->ai_next == NULL)
1482 had_error++;
1483 while (cur && cur->ai_next)
1484 cur = cur->ai_next;
1485 cp += n;
1486 break;
1487 default:
1488 abort();
1489 }
1490 if (!had_error)
1491 haveanswer++;
1492 }
1493 if (haveanswer) {
1494 if (!canonname)
1495 (void)get_canonname(pai, sentinel.ai_next, qname);
1496 else
1497 (void)get_canonname(pai, sentinel.ai_next, canonname);
1498 h_errno = NETDB_SUCCESS;
1499 return sentinel.ai_next;
1500 }
1501
1502 h_errno = NO_RECOVERY;
1503 return NULL;
1504}
1505
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001506struct addrinfo_sort_elem {
1507 struct addrinfo *ai;
1508 int has_src_addr;
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001509 sockaddr_union src_addr;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001510 int original_order;
1511};
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001512
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001513/*ARGSUSED*/
1514static int
1515_get_scope(const struct sockaddr *addr)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001516{
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001517 if (addr->sa_family == AF_INET6) {
1518 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
1519 if (IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) {
1520 return IPV6_ADDR_MC_SCOPE(&addr6->sin6_addr);
1521 } else if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr) ||
1522 IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
1523 /*
1524 * RFC 4291 section 2.5.3 says loopback is to be treated as having
1525 * link-local scope.
1526 */
1527 return IPV6_ADDR_SCOPE_LINKLOCAL;
1528 } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
1529 return IPV6_ADDR_SCOPE_SITELOCAL;
1530 } else {
1531 return IPV6_ADDR_SCOPE_GLOBAL;
1532 }
1533 } else if (addr->sa_family == AF_INET) {
1534 const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
1535 unsigned long int na = ntohl(addr4->sin_addr.s_addr);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001536
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001537 if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */
1538 (na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */
1539 return IPV6_ADDR_SCOPE_LINKLOCAL;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001540 } else {
Steinar H. Gundersond1624ad2010-12-20 11:15:33 +01001541 /*
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001542 * RFC 6724 section 3.2. Other IPv4 addresses, including private addresses
1543 * and shared addresses (100.64.0.0/10), are assigned global scope.
Steinar H. Gundersond1624ad2010-12-20 11:15:33 +01001544 */
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001545 return IPV6_ADDR_SCOPE_GLOBAL;
1546 }
1547 } else {
1548 /*
1549 * This should never happen.
1550 * Return a scope with low priority as a last resort.
1551 */
1552 return IPV6_ADDR_SCOPE_NODELOCAL;
1553 }
1554}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001555
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001556/* These macros are modelled after the ones in <netinet/in6.h>. */
1557
1558/* RFC 4380, section 2.6 */
1559#define IN6_IS_ADDR_TEREDO(a) \
1560 ((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == ntohl(0x20010000)))
1561
1562/* RFC 3056, section 2. */
1563#define IN6_IS_ADDR_6TO4(a) \
1564 (((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
1565
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001566/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
1567#define IN6_IS_ADDR_6BONE(a) \
1568 (((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
1569
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001570/*
1571 * Get the label for a given IPv4/IPv6 address.
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001572 * RFC 6724, section 2.1.
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001573 */
1574
1575/*ARGSUSED*/
1576static int
1577_get_label(const struct sockaddr *addr)
1578{
1579 if (addr->sa_family == AF_INET) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001580 return 4;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001581 } else if (addr->sa_family == AF_INET6) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001582 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001583 if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
1584 return 0;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001585 } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001586 return 4;
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001587 } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
1588 return 2;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001589 } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
1590 return 5;
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001591 } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
1592 return 13;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001593 } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001594 return 3;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001595 } else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
1596 return 11;
1597 } else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
1598 return 12;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001599 } else {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001600 /* All other IPv6 addresses, including global unicast addresses. */
1601 return 1;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001602 }
1603 } else {
1604 /*
1605 * This should never happen.
1606 * Return a semi-random label as a last resort.
1607 */
1608 return 1;
1609 }
1610}
1611
1612/*
1613 * Get the precedence for a given IPv4/IPv6 address.
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001614 * RFC 6724, section 2.1.
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001615 */
1616
1617/*ARGSUSED*/
1618static int
1619_get_precedence(const struct sockaddr *addr)
1620{
1621 if (addr->sa_family == AF_INET) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001622 return 35;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001623 } else if (addr->sa_family == AF_INET6) {
1624 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
1625 if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
1626 return 50;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001627 } else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001628 return 35;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001629 } else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001630 return 30;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001631 } else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001632 return 5;
1633 } else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
1634 return 3;
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001635 } else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
Lorenzo Colittib82532d2011-09-28 19:28:32 -07001636 IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
1637 IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001638 return 1;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001639 } else {
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001640 /* All other IPv6 addresses, including global unicast addresses. */
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001641 return 40;
1642 }
1643 } else {
Steinar H. Gunderson2e23e292010-12-20 11:48:07 +01001644 return 1;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001645 }
1646}
1647
1648/*
1649 * Find number of matching initial bits between the two addresses a1 and a2.
1650 */
1651
1652/*ARGSUSED*/
1653static int
1654_common_prefix_len(const struct in6_addr *a1, const struct in6_addr *a2)
1655{
1656 const char *p1 = (const char *)a1;
1657 const char *p2 = (const char *)a2;
1658 unsigned i;
1659
1660 for (i = 0; i < sizeof(*a1); ++i) {
1661 int x, j;
1662
1663 if (p1[i] == p2[i]) {
1664 continue;
1665 }
1666 x = p1[i] ^ p2[i];
1667 for (j = 0; j < CHAR_BIT; ++j) {
1668 if (x & (1 << (CHAR_BIT - 1))) {
1669 return i * CHAR_BIT + j;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001670 }
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001671 x <<= 1;
1672 }
1673 }
1674 return sizeof(*a1) * CHAR_BIT;
1675}
1676
1677/*
1678 * Compare two source/destination address pairs.
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001679 * RFC 6724, section 6.
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001680 */
1681
1682/*ARGSUSED*/
1683static int
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001684_rfc6724_compare(const void *ptr1, const void* ptr2)
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001685{
1686 const struct addrinfo_sort_elem *a1 = (const struct addrinfo_sort_elem *)ptr1;
1687 const struct addrinfo_sort_elem *a2 = (const struct addrinfo_sort_elem *)ptr2;
1688 int scope_src1, scope_dst1, scope_match1;
1689 int scope_src2, scope_dst2, scope_match2;
1690 int label_src1, label_dst1, label_match1;
1691 int label_src2, label_dst2, label_match2;
1692 int precedence1, precedence2;
1693 int prefixlen1, prefixlen2;
1694
1695 /* Rule 1: Avoid unusable destinations. */
1696 if (a1->has_src_addr != a2->has_src_addr) {
1697 return a2->has_src_addr - a1->has_src_addr;
1698 }
1699
1700 /* Rule 2: Prefer matching scope. */
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001701 scope_src1 = _get_scope(&a1->src_addr.generic);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001702 scope_dst1 = _get_scope(a1->ai->ai_addr);
1703 scope_match1 = (scope_src1 == scope_dst1);
1704
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001705 scope_src2 = _get_scope(&a2->src_addr.generic);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001706 scope_dst2 = _get_scope(a2->ai->ai_addr);
1707 scope_match2 = (scope_src2 == scope_dst2);
1708
1709 if (scope_match1 != scope_match2) {
1710 return scope_match2 - scope_match1;
1711 }
1712
1713 /*
1714 * Rule 3: Avoid deprecated addresses.
1715 * TODO(sesse): We don't currently have a good way of finding this.
1716 */
1717
1718 /*
1719 * Rule 4: Prefer home addresses.
1720 * TODO(sesse): We don't currently have a good way of finding this.
1721 */
1722
1723 /* Rule 5: Prefer matching label. */
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001724 label_src1 = _get_label(&a1->src_addr.generic);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001725 label_dst1 = _get_label(a1->ai->ai_addr);
1726 label_match1 = (label_src1 == label_dst1);
1727
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001728 label_src2 = _get_label(&a2->src_addr.generic);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001729 label_dst2 = _get_label(a2->ai->ai_addr);
1730 label_match2 = (label_src2 == label_dst2);
1731
1732 if (label_match1 != label_match2) {
1733 return label_match2 - label_match1;
1734 }
1735
1736 /* Rule 6: Prefer higher precedence. */
1737 precedence1 = _get_precedence(a1->ai->ai_addr);
1738 precedence2 = _get_precedence(a2->ai->ai_addr);
1739 if (precedence1 != precedence2) {
1740 return precedence2 - precedence1;
1741 }
1742
1743 /*
1744 * Rule 7: Prefer native transport.
1745 * TODO(sesse): We don't currently have a good way of finding this.
1746 */
1747
1748 /* Rule 8: Prefer smaller scope. */
1749 if (scope_dst1 != scope_dst2) {
1750 return scope_dst1 - scope_dst2;
1751 }
1752
1753 /*
1754 * Rule 9: Use longest matching prefix.
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001755 * We implement this for IPv6 only, as the rules in RFC 6724 don't seem
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001756 * to work very well directly applied to IPv4. (glibc uses information from
1757 * the routing table for a custom IPv4 implementation here.)
1758 */
1759 if (a1->has_src_addr && a1->ai->ai_addr->sa_family == AF_INET6 &&
1760 a2->has_src_addr && a2->ai->ai_addr->sa_family == AF_INET6) {
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001761 const struct sockaddr_in6 *a1_src = &a1->src_addr.in6;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001762 const struct sockaddr_in6 *a1_dst = (const struct sockaddr_in6 *)a1->ai->ai_addr;
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -07001763 const struct sockaddr_in6 *a2_src = &a2->src_addr.in6;
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001764 const struct sockaddr_in6 *a2_dst = (const struct sockaddr_in6 *)a2->ai->ai_addr;
1765 prefixlen1 = _common_prefix_len(&a1_src->sin6_addr, &a1_dst->sin6_addr);
Kenny Root7e0bfb52010-03-24 18:06:20 -07001766 prefixlen2 = _common_prefix_len(&a2_src->sin6_addr, &a2_dst->sin6_addr);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001767 if (prefixlen1 != prefixlen2) {
1768 return prefixlen2 - prefixlen1;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001769 }
1770 }
1771
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001772 /*
1773 * Rule 10: Leave the order unchanged.
1774 * We need this since qsort() is not necessarily stable.
1775 */
1776 return a1->original_order - a2->original_order;
1777}
1778
1779/*
1780 * Find the source address that will be used if trying to connect to the given
1781 * address. src_addr must be large enough to hold a struct sockaddr_in6.
1782 *
1783 * Returns 1 if a source address was found, 0 if the address is unreachable,
Erik Kline01e37c92015-06-25 14:27:34 +09001784 * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001785 * undefined.
1786 */
1787
1788/*ARGSUSED*/
1789static int
Erik Kline01e37c92015-06-25 14:27:34 +09001790_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark, uid_t uid)
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001791{
1792 int sock;
1793 int ret;
1794 socklen_t len;
1795
1796 switch (addr->sa_family) {
1797 case AF_INET:
1798 len = sizeof(struct sockaddr_in);
1799 break;
1800 case AF_INET6:
1801 len = sizeof(struct sockaddr_in6);
1802 break;
1803 default:
1804 /* No known usable source address for non-INET families. */
1805 return 0;
1806 }
1807
Nick Kralevich1781ed72014-06-29 20:46:17 -07001808 sock = socket(addr->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001809 if (sock == -1) {
1810 if (errno == EAFNOSUPPORT) {
1811 return 0;
1812 } else {
1813 return -1;
1814 }
1815 }
Erik Kline7bbb1812016-03-04 17:16:55 +09001816 if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0) {
1817 close(sock);
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001818 return 0;
Erik Kline7bbb1812016-03-04 17:16:55 +09001819 }
1820 if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0) {
1821 close(sock);
Erik Kline01e37c92015-06-25 14:27:34 +09001822 return 0;
Erik Kline7bbb1812016-03-04 17:16:55 +09001823 }
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001824 do {
Paul Jensen31ad0372014-05-29 16:28:30 -04001825 ret = __connect(sock, addr, len);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001826 } while (ret == -1 && errno == EINTR);
1827
1828 if (ret == -1) {
1829 close(sock);
1830 return 0;
1831 }
1832
Erik Kline01e37c92015-06-25 14:27:34 +09001833 if (src_addr && getsockname(sock, src_addr, &len) == -1) {
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001834 close(sock);
1835 return -1;
1836 }
1837 close(sock);
1838 return 1;
1839}
1840
1841/*
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001842 * Sort the linked list starting at sentinel->ai_next in RFC6724 order.
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001843 * Will leave the list unchanged if an error occurs.
1844 */
1845
1846/*ARGSUSED*/
1847static void
Erik Kline01e37c92015-06-25 14:27:34 +09001848_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001849{
1850 struct addrinfo *cur;
1851 int nelem = 0, i;
1852 struct addrinfo_sort_elem *elems;
1853
1854 cur = list_sentinel->ai_next;
1855 while (cur) {
1856 ++nelem;
1857 cur = cur->ai_next;
1858 }
1859
1860 elems = (struct addrinfo_sort_elem *)malloc(nelem * sizeof(struct addrinfo_sort_elem));
1861 if (elems == NULL) {
1862 goto error;
1863 }
1864
1865 /*
1866 * Convert the linked list to an array that also contains the candidate
1867 * source address for each destination address.
1868 */
1869 for (i = 0, cur = list_sentinel->ai_next; i < nelem; ++i, cur = cur->ai_next) {
1870 int has_src_addr;
1871 assert(cur != NULL);
1872 elems[i].ai = cur;
1873 elems[i].original_order = i;
1874
Erik Kline01e37c92015-06-25 14:27:34 +09001875 has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark, uid);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001876 if (has_src_addr == -1) {
1877 goto error;
1878 }
1879 elems[i].has_src_addr = has_src_addr;
1880 }
1881
1882 /* Sort the addresses, and rearrange the linked list so it matches the sorted order. */
Lorenzo Colitti378b0e12013-03-30 12:24:19 +09001883 qsort((void *)elems, nelem, sizeof(struct addrinfo_sort_elem), _rfc6724_compare);
Steinar H. Gunderson9ab75d42010-02-11 15:44:55 +01001884
1885 list_sentinel->ai_next = elems[0].ai;
1886 for (i = 0; i < nelem - 1; ++i) {
1887 elems[i].ai->ai_next = elems[i + 1].ai;
1888 }
1889 elems[nelem - 1].ai->ai_next = NULL;
1890
1891error:
1892 free(elems);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001893}
1894
1895/*ARGSUSED*/
1896static int
1897_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
1898{
1899 struct addrinfo *ai;
1900 querybuf *buf, *buf2;
1901 const char *name;
1902 const struct addrinfo *pai;
1903 struct addrinfo sentinel, *cur;
1904 struct res_target q, q2;
1905 res_state res;
Erik Kline01e37c92015-06-25 14:27:34 +09001906 const struct android_net_context *netcontext;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001907
1908 name = va_arg(ap, char *);
1909 pai = va_arg(ap, const struct addrinfo *);
Erik Kline01e37c92015-06-25 14:27:34 +09001910 netcontext = va_arg(ap, const struct android_net_context *);
David 'Digit' Turner5e563702009-05-05 15:50:24 +02001911 //fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001912
1913 memset(&q, 0, sizeof(q));
1914 memset(&q2, 0, sizeof(q2));
1915 memset(&sentinel, 0, sizeof(sentinel));
1916 cur = &sentinel;
1917
1918 buf = malloc(sizeof(*buf));
1919 if (buf == NULL) {
1920 h_errno = NETDB_INTERNAL;
1921 return NS_NOTFOUND;
1922 }
1923 buf2 = malloc(sizeof(*buf2));
1924 if (buf2 == NULL) {
1925 free(buf);
1926 h_errno = NETDB_INTERNAL;
1927 return NS_NOTFOUND;
1928 }
1929
1930 switch (pai->ai_family) {
1931 case AF_UNSPEC:
1932 /* prefer IPv6 */
1933 q.name = name;
1934 q.qclass = C_IN;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001935 q.answer = buf->buf;
1936 q.anslen = sizeof(buf->buf);
Lorenzo Colittiba96e302011-01-14 12:26:05 -08001937 int query_ipv6 = 1, query_ipv4 = 1;
1938 if (pai->ai_flags & AI_ADDRCONFIG) {
Erik Kline01e37c92015-06-25 14:27:34 +09001939 query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
1940 query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
Lorenzo Colittiba96e302011-01-14 12:26:05 -08001941 }
1942 if (query_ipv6) {
Lorenzo Colitti3d8f4ad2009-08-03 22:36:31 -07001943 q.qtype = T_AAAA;
Lorenzo Colittiba96e302011-01-14 12:26:05 -08001944 if (query_ipv4) {
1945 q.next = &q2;
1946 q2.name = name;
1947 q2.qclass = C_IN;
1948 q2.qtype = T_A;
1949 q2.answer = buf2->buf;
1950 q2.anslen = sizeof(buf2->buf);
1951 }
1952 } else if (query_ipv4) {
Lorenzo Colitti3d8f4ad2009-08-03 22:36:31 -07001953 q.qtype = T_A;
Lorenzo Colittiba96e302011-01-14 12:26:05 -08001954 } else {
1955 free(buf);
1956 free(buf2);
1957 return NS_NOTFOUND;
Lorenzo Colitti3d8f4ad2009-08-03 22:36:31 -07001958 }
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001959 break;
1960 case AF_INET:
1961 q.name = name;
1962 q.qclass = C_IN;
1963 q.qtype = T_A;
1964 q.answer = buf->buf;
1965 q.anslen = sizeof(buf->buf);
1966 break;
1967 case AF_INET6:
1968 q.name = name;
1969 q.qclass = C_IN;
1970 q.qtype = T_AAAA;
1971 q.answer = buf->buf;
1972 q.anslen = sizeof(buf->buf);
1973 break;
1974 default:
1975 free(buf);
1976 free(buf2);
1977 return NS_UNAVAIL;
1978 }
1979
1980 res = __res_get_state();
1981 if (res == NULL) {
1982 free(buf);
1983 free(buf2);
1984 return NS_NOTFOUND;
1985 }
1986
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05001987 /* this just sets our netid val in the thread private data so we don't have to
Mattias Falkc63e5902011-08-23 14:34:14 +02001988 * modify the api's all the way down to res_send.c's res_nsend. We could
1989 * fully populate the thread private data here, but if we get down there
1990 * and have a cache hit that would be wasted, so we do the rest there on miss
1991 */
Ben Schwartz90a83be2017-04-24 17:57:11 -04001992 res_setnetcontext(res, netcontext);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001993 if (res_searchN(name, &q, res) < 0) {
1994 __res_put_state(res);
1995 free(buf);
1996 free(buf2);
1997 return NS_NOTFOUND;
1998 }
1999 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
2000 if (ai) {
2001 cur->ai_next = ai;
2002 while (cur && cur->ai_next)
2003 cur = cur->ai_next;
2004 }
2005 if (q.next) {
2006 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
2007 if (ai)
2008 cur->ai_next = ai;
2009 }
2010 free(buf);
2011 free(buf2);
2012 if (sentinel.ai_next == NULL) {
2013 __res_put_state(res);
2014 switch (h_errno) {
2015 case HOST_NOT_FOUND:
2016 return NS_NOTFOUND;
2017 case TRY_AGAIN:
2018 return NS_TRYAGAIN;
2019 default:
2020 return NS_UNAVAIL;
2021 }
2022 }
2023
Erik Kline01e37c92015-06-25 14:27:34 +09002024 _rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002025
2026 __res_put_state(res);
2027
2028 *((struct addrinfo **)rv) = sentinel.ai_next;
2029 return NS_SUCCESS;
2030}
2031
2032static void
2033_sethtent(FILE **hostf)
2034{
2035
2036 if (!*hostf)
Elliott Hughesc674edb2014-08-26 15:56:54 -07002037 *hostf = fopen(_PATH_HOSTS, "re");
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002038 else
2039 rewind(*hostf);
2040}
2041
2042static void
2043_endhtent(FILE **hostf)
2044{
2045
2046 if (*hostf) {
2047 (void) fclose(*hostf);
2048 *hostf = NULL;
2049 }
2050}
2051
2052static struct addrinfo *
2053_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
2054{
2055 char *p;
2056 char *cp, *tname, *cname;
2057 struct addrinfo hints, *res0, *res;
2058 int error;
2059 const char *addr;
2060 char hostbuf[8*1024];
2061
2062// fprintf(stderr, "_gethtent() name = '%s'\n", name);
2063 assert(name != NULL);
2064 assert(pai != NULL);
2065
Elliott Hughesc674edb2014-08-26 15:56:54 -07002066 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re")))
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002067 return (NULL);
2068 again:
2069 if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
2070 return (NULL);
2071 if (*p == '#')
2072 goto again;
2073 if (!(cp = strpbrk(p, "#\n")))
2074 goto again;
2075 *cp = '\0';
2076 if (!(cp = strpbrk(p, " \t")))
2077 goto again;
2078 *cp++ = '\0';
2079 addr = p;
2080 /* if this is not something we're looking for, skip it. */
2081 cname = NULL;
2082 while (cp && *cp) {
2083 if (*cp == ' ' || *cp == '\t') {
2084 cp++;
2085 continue;
2086 }
2087 if (!cname)
2088 cname = cp;
2089 tname = cp;
2090 if ((cp = strpbrk(cp, " \t")) != NULL)
2091 *cp++ = '\0';
2092// fprintf(stderr, "\ttname = '%s'", tname);
2093 if (strcasecmp(name, tname) == 0)
2094 goto found;
2095 }
2096 goto again;
2097
2098found:
2099 hints = *pai;
2100 hints.ai_flags = AI_NUMERICHOST;
2101 error = getaddrinfo(addr, NULL, &hints, &res0);
2102 if (error)
2103 goto again;
2104 for (res = res0; res; res = res->ai_next) {
2105 /* cover it up */
2106 res->ai_flags = pai->ai_flags;
2107
2108 if (pai->ai_flags & AI_CANONNAME) {
2109 if (get_canonname(pai, res, cname) != 0) {
2110 freeaddrinfo(res0);
2111 goto again;
2112 }
2113 }
2114 }
2115 return res0;
2116}
2117
2118/*ARGSUSED*/
2119static int
2120_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
2121{
2122 const char *name;
2123 const struct addrinfo *pai;
2124 struct addrinfo sentinel, *cur;
2125 struct addrinfo *p;
2126 FILE *hostf = NULL;
2127
2128 name = va_arg(ap, char *);
2129 pai = va_arg(ap, struct addrinfo *);
2130
Tom Marshall310e4a42016-06-17 16:38:12 -07002131 memset(&sentinel, 0, sizeof(sentinel));
2132 cur = &sentinel;
2133 int gai_error = hc_getaddrinfo(name, NULL, pai, &cur);
2134 if (gai_error != EAI_SYSTEM) {
2135 *((struct addrinfo **)rv) = sentinel.ai_next;
2136 return (gai_error == 0 ? NS_SUCCESS : NS_NOTFOUND);
2137 }
2138
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002139// fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name);
2140 memset(&sentinel, 0, sizeof(sentinel));
2141 cur = &sentinel;
2142
2143 _sethtent(&hostf);
2144 while ((p = _gethtent(&hostf, name, pai)) != NULL) {
2145 cur->ai_next = p;
2146 while (cur && cur->ai_next)
2147 cur = cur->ai_next;
2148 }
2149 _endhtent(&hostf);
2150
2151 *((struct addrinfo **)rv) = sentinel.ai_next;
2152 if (sentinel.ai_next == NULL)
2153 return NS_NOTFOUND;
2154 return NS_SUCCESS;
2155}
2156
2157/* resolver logic */
2158
2159/*
2160 * Formulate a normal query, send, and await answer.
2161 * Returned answer is placed in supplied buffer "answer".
2162 * Perform preliminary check of answer, returning success only
2163 * if no error is indicated and the answer count is nonzero.
2164 * Return the size of the response on success, -1 on error.
2165 * Error number is left in h_errno.
2166 *
2167 * Caller must parse answer and determine whether it answers the question.
2168 */
2169static int
2170res_queryN(const char *name, /* domain name */ struct res_target *target,
2171 res_state res)
2172{
2173 u_char buf[MAXPACKET];
2174 HEADER *hp;
2175 int n;
2176 struct res_target *t;
2177 int rcode;
2178 int ancount;
2179
2180 assert(name != NULL);
2181 /* XXX: target may be NULL??? */
2182
2183 rcode = NOERROR;
2184 ancount = 0;
2185
2186 for (t = target; t; t = t->next) {
2187 int class, type;
2188 u_char *answer;
2189 int anslen;
Ben Schwartz98645642017-10-02 12:26:05 -04002190 u_int oflags;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002191
2192 hp = (HEADER *)(void *)t->answer;
Ben Schwartz98645642017-10-02 12:26:05 -04002193 oflags = res->_flags;
2194
2195again:
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002196 hp->rcode = NOERROR; /* default */
2197
2198 /* make it easier... */
2199 class = t->qclass;
2200 type = t->qtype;
2201 answer = t->answer;
2202 anslen = t->anslen;
2203#ifdef DEBUG
2204 if (res->options & RES_DEBUG)
2205 printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
2206#endif
2207
2208 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
2209 buf, sizeof(buf));
2210#ifdef RES_USE_EDNS0
Ben Schwartz98645642017-10-02 12:26:05 -04002211 if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
2212 (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002213 n = res_nopt(res, n, buf, sizeof(buf), anslen);
2214#endif
2215 if (n <= 0) {
2216#ifdef DEBUG
2217 if (res->options & RES_DEBUG)
2218 printf(";; res_nquery: mkquery failed\n");
2219#endif
2220 h_errno = NO_RECOVERY;
2221 return n;
2222 }
2223 n = res_nsend(res, buf, n, answer, anslen);
2224#if 0
2225 if (n < 0) {
2226#ifdef DEBUG
2227 if (res->options & RES_DEBUG)
2228 printf(";; res_query: send error\n");
2229#endif
2230 h_errno = TRY_AGAIN;
2231 return n;
2232 }
2233#endif
2234
2235 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
2236 rcode = hp->rcode; /* record most recent error */
Ben Schwartz98645642017-10-02 12:26:05 -04002237#ifdef RES_USE_EDNS0
2238 /* if the query choked with EDNS0, retry without EDNS0 */
2239 if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 &&
2240 ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
2241 res->_flags |= RES_F_EDNS0ERR;
2242#ifdef DEBUG
2243 if (res->options & RES_DEBUG)
2244 printf(";; res_nquery: retry without EDNS0\n");
2245#endif
2246 goto again;
2247 }
2248#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002249#ifdef DEBUG
2250 if (res->options & RES_DEBUG)
2251 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
2252 ntohs(hp->ancount));
2253#endif
2254 continue;
2255 }
2256
2257 ancount += ntohs(hp->ancount);
2258
2259 t->n = n;
2260 }
2261
2262 if (ancount == 0) {
2263 switch (rcode) {
2264 case NXDOMAIN:
2265 h_errno = HOST_NOT_FOUND;
2266 break;
2267 case SERVFAIL:
2268 h_errno = TRY_AGAIN;
2269 break;
2270 case NOERROR:
2271 h_errno = NO_DATA;
2272 break;
2273 case FORMERR:
2274 case NOTIMP:
2275 case REFUSED:
2276 default:
2277 h_errno = NO_RECOVERY;
2278 break;
2279 }
2280 return -1;
2281 }
2282 return ancount;
2283}
2284
2285/*
2286 * Formulate a normal query, send, and retrieve answer in supplied buffer.
2287 * Return the size of the response on success, -1 on error.
2288 * If enabled, implement search rules until answer or unrecoverable failure
2289 * is detected. Error code, if any, is left in h_errno.
2290 */
2291static int
2292res_searchN(const char *name, struct res_target *target, res_state res)
2293{
2294 const char *cp, * const *domain;
2295 HEADER *hp;
2296 u_int dots;
2297 int trailing_dot, ret, saved_herrno;
2298 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
2299
2300 assert(name != NULL);
2301 assert(target != NULL);
2302
2303 hp = (HEADER *)(void *)target->answer; /*XXX*/
2304
2305 errno = 0;
2306 h_errno = HOST_NOT_FOUND; /* default, if we never query */
2307 dots = 0;
2308 for (cp = name; *cp; cp++)
2309 dots += (*cp == '.');
2310 trailing_dot = 0;
2311 if (cp > name && *--cp == '.')
2312 trailing_dot++;
2313
2314
David 'Digit' Turner5e563702009-05-05 15:50:24 +02002315 //fprintf(stderr, "res_searchN() name = '%s'\n", name);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002316
2317 /*
2318 * if there aren't any dots, it could be a user-level alias
2319 */
2320 if (!dots && (cp = __hostalias(name)) != NULL) {
2321 ret = res_queryN(cp, target, res);
2322 return ret;
2323 }
2324
2325 /*
2326 * If there are dots in the name already, let's just give it a try
2327 * 'as is'. The threshold can be set with the "ndots" option.
2328 */
2329 saved_herrno = -1;
2330 if (dots >= res->ndots) {
2331 ret = res_querydomainN(name, NULL, target, res);
2332 if (ret > 0)
2333 return (ret);
2334 saved_herrno = h_errno;
2335 tried_as_is++;
2336 }
2337
2338 /*
2339 * We do at least one level of search if
2340 * - there is no dot and RES_DEFNAME is set, or
2341 * - there is at least one dot, there is no trailing dot,
2342 * and RES_DNSRCH is set.
2343 */
2344 if ((!dots && (res->options & RES_DEFNAMES)) ||
2345 (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
2346 int done = 0;
2347
Robert Greenwalte0805a92013-07-31 16:53:46 -07002348 /* Unfortunately we need to set stuff up before
2349 * the domain stuff is tried. Will have a better
2350 * fix after thread pools are used.
2351 */
Szymon Jakubczakea9bf672014-02-14 17:07:23 -05002352 _resolv_populate_res_for_net(res);
Robert Greenwalte0805a92013-07-31 16:53:46 -07002353
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002354 for (domain = (const char * const *)res->dnsrch;
2355 *domain && !done;
2356 domain++) {
2357
2358 ret = res_querydomainN(name, *domain, target, res);
2359 if (ret > 0)
2360 return ret;
2361
2362 /*
2363 * If no server present, give up.
2364 * If name isn't found in this domain,
2365 * keep trying higher domains in the search list
2366 * (if that's enabled).
2367 * On a NO_DATA error, keep trying, otherwise
2368 * a wildcard entry of another type could keep us
2369 * from finding this entry higher in the domain.
2370 * If we get some other error (negative answer or
2371 * server failure), then stop searching up,
2372 * but try the input name below in case it's
2373 * fully-qualified.
2374 */
2375 if (errno == ECONNREFUSED) {
2376 h_errno = TRY_AGAIN;
2377 return -1;
2378 }
2379
2380 switch (h_errno) {
2381 case NO_DATA:
2382 got_nodata++;
2383 /* FALLTHROUGH */
2384 case HOST_NOT_FOUND:
2385 /* keep trying */
2386 break;
2387 case TRY_AGAIN:
2388 if (hp->rcode == SERVFAIL) {
2389 /* try next search element, if any */
2390 got_servfail++;
2391 break;
2392 }
2393 /* FALLTHROUGH */
2394 default:
2395 /* anything else implies that we're done */
2396 done++;
2397 }
2398 /*
2399 * if we got here for some reason other than DNSRCH,
2400 * we only wanted one iteration of the loop, so stop.
2401 */
2402 if (!(res->options & RES_DNSRCH))
Lorenzo Colittib82532d2011-09-28 19:28:32 -07002403 done++;
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08002404 }
2405 }
2406
2407 /*
2408 * if we have not already tried the name "as is", do that now.
2409 * note that we do this regardless of how many dots were in the
2410 * name or whether it ends with a dot.
2411 */
2412 if (!tried_as_is) {
2413 ret = res_querydomainN(name, NULL, target, res);
2414 if (ret > 0)
2415 return ret;
2416 }
2417
2418 /*
2419 * if we got here, we didn't satisfy the search.
2420 * if we did an initial full query, return that query's h_errno
2421 * (note that we wouldn't be here if that query had succeeded).
2422 * else if we ever got a nodata, send that back as the reason.
2423 * else send back meaningless h_errno, that being the one from
2424 * the last DNSRCH we did.
2425 */
2426 if (saved_herrno != -1)
2427 h_errno = saved_herrno;
2428 else if (got_nodata)
2429 h_errno = NO_DATA;
2430 else if (got_servfail)
2431 h_errno = TRY_AGAIN;
2432 return -1;
2433}
2434
2435/*
2436 * Perform a call on res_query on the concatenation of name and domain,
2437 * removing a trailing dot from name if domain is NULL.
2438 */
2439static int
2440res_querydomainN(const char *name, const char *domain,
2441 struct res_target *target, res_state res)
2442{
2443 char nbuf[MAXDNAME];
2444 const char *longname = nbuf;
2445 size_t n, d;
2446
2447 assert(name != NULL);
2448 /* XXX: target may be NULL??? */
2449
2450#ifdef DEBUG
2451 if (res->options & RES_DEBUG)
2452 printf(";; res_querydomain(%s, %s)\n",
2453 name, domain?domain:"<Nil>");
2454#endif
2455 if (domain == NULL) {
2456 /*
2457 * Check for trailing '.';
2458 * copy without '.' if present.
2459 */
2460 n = strlen(name);
2461 if (n + 1 > sizeof(nbuf)) {
2462 h_errno = NO_RECOVERY;
2463 return -1;
2464 }
2465 if (n > 0 && name[--n] == '.') {
2466 strncpy(nbuf, name, n);
2467 nbuf[n] = '\0';
2468 } else
2469 longname = name;
2470 } else {
2471 n = strlen(name);
2472 d = strlen(domain);
2473 if (n + 1 + d + 1 > sizeof(nbuf)) {
2474 h_errno = NO_RECOVERY;
2475 return -1;
2476 }
2477 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
2478 }
2479 return res_queryN(longname, target, res);
2480}