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