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