]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - lib/libc/net/getaddrinfo.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / lib / libc / net / getaddrinfo.c
1 /*      $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $    */
2
3 /*
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 /*
33  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
34  *
35  * Issues to be discussed:
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  * - freeaddrinfo(NULL).  RFC2553 is silent about it.  XNET 5.2 says it is
40  *   invalid.  current code - SEGV on freeaddrinfo(NULL)
41  *
42  * Note:
43  * - The code filters out AFs that are not supported by the kernel,
44  *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
45  *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
46  *   in ai_flags?
47  * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
48  *   (1) what should we do against numeric hostname (2) what should we do
49  *   against NULL hostname (3) what is AI_ADDRCONFIG itself.  AF not ready?
50  *   non-loopback address configured?  global address configured?
51  *
52  * OS specific notes for freebsd4:
53  * - FreeBSD supported $GAI.  The code does not.
54  */
55
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
58
59 #include "namespace.h"
60 #include <sys/types.h>
61 #include <sys/param.h>
62 #include <sys/socket.h>
63 #include <net/if.h>
64 #include <netinet/in.h>
65 #include <sys/queue.h>
66 #ifdef INET6
67 #include <net/if_var.h>
68 #include <sys/sysctl.h>
69 #include <sys/ioctl.h>
70 #include <netinet6/in6_var.h>   /* XXX */
71 #endif
72 #include <arpa/inet.h>
73 #include <arpa/nameser.h>
74 #include <rpc/rpc.h>
75 #include <rpcsvc/yp_prot.h>
76 #include <rpcsvc/ypclnt.h>
77 #include <netdb.h>
78 #include <resolv.h>
79 #include <string.h>
80 #include <stdlib.h>
81 #include <stddef.h>
82 #include <ctype.h>
83 #include <unistd.h>
84 #include <stdio.h>
85 #include <errno.h>
86
87 #include "res_config.h"
88
89 #ifdef DEBUG
90 #include <syslog.h>
91 #endif
92
93 #include <stdarg.h>
94 #include <nsswitch.h>
95 #include "un-namespace.h"
96 #include "libc_private.h"
97 #ifdef NS_CACHING
98 #include "nscache.h"
99 #endif
100
101 #if defined(__KAME__) && defined(INET6)
102 # define FAITH
103 #endif
104
105 #define ANY 0
106 #define YES 1
107 #define NO  0
108
109 static const char in_addrany[] = { 0, 0, 0, 0 };
110 static const char in_loopback[] = { 127, 0, 0, 1 };
111 #ifdef INET6
112 static const char in6_addrany[] = {
113         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
114 };
115 static const char in6_loopback[] = {
116         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
117 };
118 #endif
119
120 struct policyqueue {
121         TAILQ_ENTRY(policyqueue) pc_entry;
122 #ifdef INET6
123         struct in6_addrpolicy pc_policy;
124 #endif
125 };
126 TAILQ_HEAD(policyhead, policyqueue);
127
128 static const struct afd {
129         int a_af;
130         int a_addrlen;
131         socklen_t a_socklen;
132         int a_off;
133         const char *a_addrany;
134         const char *a_loopback;
135         int a_scoped;
136 } afdl [] = {
137 #ifdef INET6
138 #define N_INET6 0
139         {PF_INET6, sizeof(struct in6_addr),
140          sizeof(struct sockaddr_in6),
141          offsetof(struct sockaddr_in6, sin6_addr),
142          in6_addrany, in6_loopback, 1},
143 #define N_INET 1
144 #else
145 #define N_INET 0
146 #endif
147         {PF_INET, sizeof(struct in_addr),
148          sizeof(struct sockaddr_in),
149          offsetof(struct sockaddr_in, sin_addr),
150          in_addrany, in_loopback, 0},
151         {0, 0, 0, 0, NULL, NULL, 0},
152 };
153
154 struct explore {
155         int e_af;
156         int e_socktype;
157         int e_protocol;
158         int e_wild;
159 #define WILD_AF(ex)             ((ex)->e_wild & 0x01)
160 #define WILD_SOCKTYPE(ex)       ((ex)->e_wild & 0x02)
161 #define WILD_PROTOCOL(ex)       ((ex)->e_wild & 0x04)
162 };
163
164 static const struct explore explore[] = {
165 #if 0
166         { PF_LOCAL, ANY, ANY, 0x01 },
167 #endif
168 #ifdef INET6
169         { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
170         { PF_INET6, SOCK_STREAM, IPPROTO_TCP, 0x07 },
171         { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
172         { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
173         { PF_INET6, SOCK_RAW, ANY, 0x05 },
174 #endif
175         { PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0x07 },
176         { PF_INET, SOCK_STREAM, IPPROTO_TCP, 0x07 },
177         { PF_INET, SOCK_STREAM, IPPROTO_SCTP, 0x03 },
178         { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, 0x07 },
179         { PF_INET, SOCK_RAW, ANY, 0x05 },
180         { -1, 0, 0, 0 },
181 };
182
183 #ifdef INET6
184 #define PTON_MAX        16
185 #else
186 #define PTON_MAX        4
187 #endif
188
189 #define AIO_SRCFLAG_DEPRECATED  0x1
190
191 struct ai_order {
192         union {
193                 struct sockaddr_storage aiou_ss;
194                 struct sockaddr aiou_sa;
195         } aio_src_un;
196 #define aio_srcsa aio_src_un.aiou_sa
197         u_int32_t aio_srcflag;
198         int aio_srcscope;
199         int aio_dstscope;
200         struct policyqueue *aio_srcpolicy;
201         struct policyqueue *aio_dstpolicy;
202         struct addrinfo *aio_ai;
203         int aio_matchlen;
204 };
205
206 static const ns_src default_dns_files[] = {
207         { NSSRC_FILES,  NS_SUCCESS },
208         { NSSRC_DNS,    NS_SUCCESS },
209         { 0 }
210 };
211
212 struct res_target {
213         struct res_target *next;
214         const char *name;       /* domain name */
215         int qclass, qtype;      /* class and type of query */
216         u_char *answer;         /* buffer to put answer */
217         int anslen;             /* size of answer buffer */
218         int n;                  /* result length */
219 };
220
221 #define MAXPACKET       (64*1024)
222
223 typedef union {
224         HEADER hdr;
225         u_char buf[MAXPACKET];
226 } querybuf;
227
228 static int str2number(const char *, int *);
229 static int explore_copy(const struct addrinfo *, const struct addrinfo *,
230         struct addrinfo **);
231 static int explore_null(const struct addrinfo *,
232         const char *, struct addrinfo **);
233 static int explore_numeric(const struct addrinfo *, const char *,
234         const char *, struct addrinfo **, const char *);
235 static int explore_numeric_scope(const struct addrinfo *, const char *,
236         const char *, struct addrinfo **);
237 static int get_canonname(const struct addrinfo *,
238         struct addrinfo *, const char *);
239 static struct addrinfo *get_ai(const struct addrinfo *,
240         const struct afd *, const char *);
241 static struct addrinfo *copy_ai(const struct addrinfo *);
242 static int get_portmatch(const struct addrinfo *, const char *);
243 static int get_port(struct addrinfo *, const char *, int);
244 static const struct afd *find_afd(int);
245 static int addrconfig(struct addrinfo *);
246 static void set_source(struct ai_order *, struct policyhead *);
247 static int comp_dst(const void *, const void *);
248 #ifdef INET6
249 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
250 #endif
251 static int gai_addr2scopetype(struct sockaddr *);
252
253 static int explore_fqdn(const struct addrinfo *, const char *,
254         const char *, struct addrinfo **);
255
256 static int reorder(struct addrinfo *);
257 static int get_addrselectpolicy(struct policyhead *);
258 static void free_addrselectpolicy(struct policyhead *);
259 static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
260         struct policyhead *);
261 static int matchlen(struct sockaddr *, struct sockaddr *);
262
263 static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
264         const struct addrinfo *, res_state);
265 #if defined(RESOLVSORT)
266 static int addr4sort(struct addrinfo *, res_state);
267 #endif
268 static int _dns_getaddrinfo(void *, void *, va_list);
269 static void _sethtent(FILE **);
270 static void _endhtent(FILE **);
271 static struct addrinfo *_gethtent(FILE **, const char *,
272         const struct addrinfo *);
273 static int _files_getaddrinfo(void *, void *, va_list);
274 #ifdef YP
275 static struct addrinfo *_yphostent(char *, const struct addrinfo *);
276 static int _yp_getaddrinfo(void *, void *, va_list);
277 #endif
278 #ifdef NS_CACHING
279 static int addrinfo_id_func(char *, size_t *, va_list, void *);
280 static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *);
281 static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *);
282 #endif
283
284 static int res_queryN(const char *, struct res_target *, res_state);
285 static int res_searchN(const char *, struct res_target *, res_state);
286 static int res_querydomainN(const char *, const char *,
287         struct res_target *, res_state);
288
289 /* XXX macros that make external reference is BAD. */
290
291 #define GET_AI(ai, afd, addr) \
292 do { \
293         /* external reference: pai, error, and label free */ \
294         (ai) = get_ai(pai, (afd), (addr)); \
295         if ((ai) == NULL) { \
296                 error = EAI_MEMORY; \
297                 goto free; \
298         } \
299 } while (/*CONSTCOND*/0)
300
301 #define GET_PORT(ai, serv) \
302 do { \
303         /* external reference: error and label free */ \
304         error = get_port((ai), (serv), 0); \
305         if (error != 0) \
306                 goto free; \
307 } while (/*CONSTCOND*/0)
308
309 #define GET_CANONNAME(ai, str) \
310 do { \
311         /* external reference: pai, error and label free */ \
312         error = get_canonname(pai, (ai), (str)); \
313         if (error != 0) \
314                 goto free; \
315 } while (/*CONSTCOND*/0)
316
317 #define ERR(err) \
318 do { \
319         /* external reference: error, and label bad */ \
320         error = (err); \
321         goto bad; \
322         /*NOTREACHED*/ \
323 } while (/*CONSTCOND*/0)
324
325 #define MATCH_FAMILY(x, y, w) \
326         ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
327 #define MATCH(x, y, w) \
328         ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
329
330 void
331 freeaddrinfo(struct addrinfo *ai)
332 {
333         struct addrinfo *next;
334
335         do {
336                 next = ai->ai_next;
337                 if (ai->ai_canonname)
338                         free(ai->ai_canonname);
339                 /* no need to free(ai->ai_addr) */
340                 free(ai);
341                 ai = next;
342         } while (ai);
343 }
344
345 static int
346 str2number(const char *p, int *portp)
347 {
348         char *ep;
349         unsigned long v;
350
351         if (*p == '\0')
352                 return -1;
353         ep = NULL;
354         errno = 0;
355         v = strtoul(p, &ep, 10);
356         if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) {
357                 *portp = v;
358                 return 0;
359         } else
360                 return -1;
361 }
362
363 int
364 getaddrinfo(const char *hostname, const char *servname,
365     const struct addrinfo *hints, struct addrinfo **res)
366 {
367         struct addrinfo sentinel;
368         struct addrinfo *cur;
369         int error = 0;
370         struct addrinfo ai, ai0, *afai;
371         struct addrinfo *pai;
372         const struct afd *afd;
373         const struct explore *ex;
374         struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
375         struct addrinfo *afai_unspec;
376         int found;
377         int numeric = 0;
378
379         /* ensure we return NULL on errors */
380         *res = NULL;
381
382         memset(&ai, 0, sizeof(ai));
383
384         memset(afailist, 0, sizeof(afailist));
385         afai_unspec = NULL;
386
387         memset(&sentinel, 0, sizeof(sentinel));
388         cur = &sentinel;
389         pai = &ai;
390         pai->ai_flags = 0;
391         pai->ai_family = PF_UNSPEC;
392         pai->ai_socktype = ANY;
393         pai->ai_protocol = ANY;
394         pai->ai_addrlen = 0;
395         pai->ai_canonname = NULL;
396         pai->ai_addr = NULL;
397         pai->ai_next = NULL;
398
399         if (hostname == NULL && servname == NULL)
400                 return EAI_NONAME;
401         if (hints) {
402                 /* error check for hints */
403                 if (hints->ai_addrlen || hints->ai_canonname ||
404                     hints->ai_addr || hints->ai_next)
405                         ERR(EAI_BADHINTS); /* xxx */
406                 if (hints->ai_flags & ~AI_MASK)
407                         ERR(EAI_BADFLAGS);
408                 switch (hints->ai_family) {
409                 case PF_UNSPEC:
410                 case PF_INET:
411 #ifdef INET6
412                 case PF_INET6:
413 #endif
414                         break;
415                 default:
416                         ERR(EAI_FAMILY);
417                 }
418                 memcpy(pai, hints, sizeof(*pai));
419
420                 /*
421                  * if both socktype/protocol are specified, check if they
422                  * are meaningful combination.
423                  */
424                 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
425                         for (ex = explore; ex->e_af >= 0; ex++) {
426                                 if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
427                                     WILD_AF(ex)))
428                                         continue;
429                                 if (!MATCH(pai->ai_socktype, ex->e_socktype,
430                                     WILD_SOCKTYPE(ex)))
431                                         continue;
432                                 if (!MATCH(pai->ai_protocol, ex->e_protocol,
433                                     WILD_PROTOCOL(ex)))
434                                         continue;
435
436                                 /* matched */
437                                 break;
438                         }
439
440                         if (ex->e_af < 0)
441                                 ERR(EAI_BADHINTS);
442                 }
443         }
444
445         /*
446          * check for special cases.  (1) numeric servname is disallowed if
447          * socktype/protocol are left unspecified. (2) servname is disallowed
448          * for raw and other inet{,6} sockets.
449          */
450         if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
451 #ifdef PF_INET6
452             || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
453 #endif
454             ) {
455                 ai0 = *pai;     /* backup *pai */
456
457                 if (pai->ai_family == PF_UNSPEC) {
458 #ifdef PF_INET6
459                         pai->ai_family = PF_INET6;
460 #else
461                         pai->ai_family = PF_INET;
462 #endif
463                 }
464                 error = get_portmatch(pai, servname);
465                 if (error)
466                         goto bad;
467
468                 *pai = ai0;
469         }
470
471         ai0 = *pai;
472
473         /*
474          * NULL hostname, or numeric hostname.
475          * If numeric representation of AF1 can be interpreted as FQDN
476          * representation of AF2, we need to think again about the code below.
477          */
478         found = 0;
479         for (afd = afdl; afd->a_af; afd++) {
480                 *pai = ai0;
481
482                 if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
483                         continue;
484
485                 if (pai->ai_family == PF_UNSPEC)
486                         pai->ai_family = afd->a_af;
487
488                 if (hostname == NULL) {
489                         error = explore_null(pai, servname,
490                             &afailist[afd - afdl]);
491
492                         /*
493                          * Errors from explore_null should be unexpected and
494                          * be caught to avoid returning an incomplete result.
495                          */
496                         if (error != 0)
497                                 goto bad;
498                 } else {
499                         error = explore_numeric_scope(pai, hostname, servname,
500                             &afailist[afd - afdl]);
501
502                         /*
503                          * explore_numeric_scope returns an error for address
504                          * families that do not match that of hostname.
505                          * Thus we should not catch the error at this moment. 
506                          */
507                 }
508
509                 if (!error && afailist[afd - afdl])
510                         found++;
511         }
512         if (found) {
513                 numeric = 1;
514                 goto globcopy;
515         }
516
517         if (hostname == NULL)
518                 ERR(EAI_NONAME);        /* used to be EAI_NODATA */
519         if (pai->ai_flags & AI_NUMERICHOST)
520                 ERR(EAI_NONAME);
521
522         if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
523                 ERR(EAI_FAIL);
524
525         /*
526          * hostname as alphabetical name.
527          */
528         *pai = ai0;
529         error = explore_fqdn(pai, hostname, servname, &afai_unspec);
530
531 globcopy:
532         for (ex = explore; ex->e_af >= 0; ex++) {
533                 *pai = ai0;
534
535                 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
536                         continue;
537                 if (!MATCH(pai->ai_socktype, ex->e_socktype,
538                     WILD_SOCKTYPE(ex)))
539                         continue;
540                 if (!MATCH(pai->ai_protocol, ex->e_protocol,
541                     WILD_PROTOCOL(ex)))
542                         continue;
543
544                 if (pai->ai_family == PF_UNSPEC)
545                         pai->ai_family = ex->e_af;
546                 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
547                         pai->ai_socktype = ex->e_socktype;
548                 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
549                         pai->ai_protocol = ex->e_protocol;
550
551                 /*
552                  * if the servname does not match socktype/protocol, ignore it.
553                  */
554                 if (get_portmatch(pai, servname) != 0)
555                         continue;
556
557                 if (afai_unspec)
558                         afai = afai_unspec;
559                 else {
560                         if ((afd = find_afd(pai->ai_family)) == NULL)
561                                 continue;
562                         /* XXX assumes that afd points inside afdl[] */
563                         afai = afailist[afd - afdl];
564                 }
565                 if (!afai)
566                         continue;
567
568                 error = explore_copy(pai, afai, &cur->ai_next);
569                 if (error != 0)
570                         goto bad;
571
572                 while (cur && cur->ai_next)
573                         cur = cur->ai_next;
574         }
575
576         /*
577          * ensure we return either:
578          * - error == 0, non-NULL *res
579          * - error != 0, NULL *res
580          */
581         if (error == 0) {
582                 if (sentinel.ai_next) {
583                         /*
584                          * If the returned entry is for an active connection,
585                          * and the given name is not numeric, reorder the
586                          * list, so that the application would try the list
587                          * in the most efficient order.  Since the head entry
588                          * of the original list may contain ai_canonname and
589                          * that entry may be moved elsewhere in the new list,
590                          * we keep the pointer and will  restore it in the new
591                          * head entry.  (Note that RFC3493 requires the head
592                          * entry store it when requested by the caller).
593                          */
594                         if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) {
595                                 if (!numeric) {
596                                         char *canonname;
597
598                                         canonname =
599                                             sentinel.ai_next->ai_canonname;
600                                         sentinel.ai_next->ai_canonname = NULL;
601                                         (void)reorder(&sentinel);
602                                         if (sentinel.ai_next->ai_canonname ==
603                                             NULL) {
604                                                 sentinel.ai_next->ai_canonname
605                                                     = canonname;
606                                         } else if (canonname != NULL)
607                                                 free(canonname);
608                                 }
609                         }
610                         *res = sentinel.ai_next;
611                 } else
612                         error = EAI_FAIL;
613         }
614
615 bad:
616         if (afai_unspec)
617                 freeaddrinfo(afai_unspec);
618         for (afd = afdl; afd->a_af; afd++) {
619                 if (afailist[afd - afdl])
620                         freeaddrinfo(afailist[afd - afdl]);
621         }
622         if (!*res)
623                 if (sentinel.ai_next)
624                         freeaddrinfo(sentinel.ai_next);
625
626         return (error);
627 }
628
629 static int
630 reorder(struct addrinfo *sentinel)
631 {
632         struct addrinfo *ai, **aip;
633         struct ai_order *aio;
634         int i, n;
635         struct policyhead policyhead;
636
637         /* count the number of addrinfo elements for sorting. */
638         for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++)
639                 ;
640
641         /*
642          * If the number is small enough, we can skip the reordering process.
643          */
644         if (n <= 1)
645                 return(n);
646
647         /* allocate a temporary array for sort and initialization of it. */
648         if ((aio = malloc(sizeof(*aio) * n)) == NULL)
649                 return(n);      /* give up reordering */
650         memset(aio, 0, sizeof(*aio) * n);
651
652         /* retrieve address selection policy from the kernel */
653         TAILQ_INIT(&policyhead);
654         if (!get_addrselectpolicy(&policyhead)) {
655                 /* no policy is installed into kernel, we don't sort. */
656                 free(aio);
657                 return (n);
658         }
659
660         for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) {
661                 aio[i].aio_ai = ai;
662                 aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr);
663                 aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
664                                                               &policyhead);
665                 set_source(&aio[i], &policyhead);
666         }
667
668         /* perform sorting. */
669         qsort(aio, n, sizeof(*aio), comp_dst);
670
671         /* reorder the addrinfo chain. */
672         for (i = 0, aip = &sentinel->ai_next; i < n; i++) {
673                 *aip = aio[i].aio_ai;
674                 aip = &aio[i].aio_ai->ai_next;
675         }
676         *aip = NULL;
677
678         /* cleanup and return */
679         free(aio);
680         free_addrselectpolicy(&policyhead);
681         return(n);
682 }
683
684 static int
685 get_addrselectpolicy(struct policyhead *head)
686 {
687 #ifdef INET6
688         int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
689         size_t l;
690         char *buf;
691         struct in6_addrpolicy *pol, *ep;
692
693         if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
694                 return (0);
695         if (l == 0)
696                 return (0);
697         if ((buf = malloc(l)) == NULL)
698                 return (0);
699         if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
700                 free(buf);
701                 return (0);
702         }
703
704         ep = (struct in6_addrpolicy *)(buf + l);
705         for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
706                 struct policyqueue *new;
707
708                 if ((new = malloc(sizeof(*new))) == NULL) {
709                         free_addrselectpolicy(head); /* make the list empty */
710                         break;
711                 }
712                 new->pc_policy = *pol;
713                 TAILQ_INSERT_TAIL(head, new, pc_entry);
714         }
715
716         free(buf);
717         return (1);
718 #else
719         return (0);
720 #endif
721 }
722
723 static void
724 free_addrselectpolicy(struct policyhead *head)
725 {
726         struct policyqueue *ent, *nent;
727
728         for (ent = TAILQ_FIRST(head); ent; ent = nent) {
729                 nent = TAILQ_NEXT(ent, pc_entry);
730                 TAILQ_REMOVE(head, ent, pc_entry);
731                 free(ent);
732         }
733 }
734
735 static struct policyqueue *
736 match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
737 {
738 #ifdef INET6
739         struct policyqueue *ent, *bestent = NULL;
740         struct in6_addrpolicy *pol;
741         int matchlen, bestmatchlen = -1;
742         u_char *mp, *ep, *k, *p, m;
743         struct sockaddr_in6 key;
744
745         switch(addr->sa_family) {
746         case AF_INET6:
747                 key = *(struct sockaddr_in6 *)addr;
748                 break;
749         case AF_INET:
750                 /* convert the address into IPv4-mapped IPv6 address. */
751                 memset(&key, 0, sizeof(key));
752                 key.sin6_family = AF_INET6;
753                 key.sin6_len = sizeof(key);
754                 key.sin6_addr.s6_addr[10] = 0xff;
755                 key.sin6_addr.s6_addr[11] = 0xff;
756                 memcpy(&key.sin6_addr.s6_addr[12],
757                        &((struct sockaddr_in *)addr)->sin_addr, 4);
758                 break;
759         default:
760                 return(NULL);
761         }
762
763         for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
764                 pol = &ent->pc_policy;
765                 matchlen = 0;
766
767                 mp = (u_char *)&pol->addrmask.sin6_addr;
768                 ep = mp + 16;   /* XXX: scope field? */
769                 k = (u_char *)&key.sin6_addr;
770                 p = (u_char *)&pol->addr.sin6_addr;
771                 for (; mp < ep && *mp; mp++, k++, p++) {
772                         m = *mp;
773                         if ((*k & m) != *p)
774                                 goto next; /* not match */
775                         if (m == 0xff) /* short cut for a typical case */
776                                 matchlen += 8;
777                         else {
778                                 while (m >= 0x80) {
779                                         matchlen++;
780                                         m <<= 1;
781                                 }
782                         }
783                 }
784
785                 /* matched.  check if this is better than the current best. */
786                 if (matchlen > bestmatchlen) {
787                         bestent = ent;
788                         bestmatchlen = matchlen;
789                 }
790
791           next:
792                 continue;
793         }
794
795         return(bestent);
796 #else
797         return(NULL);
798 #endif
799
800 }
801
802 static void
803 set_source(struct ai_order *aio, struct policyhead *ph)
804 {
805         struct addrinfo ai = *aio->aio_ai;
806         struct sockaddr_storage ss;
807         socklen_t srclen;
808         int s;
809
810         /* set unspec ("no source is available"), just in case */
811         aio->aio_srcsa.sa_family = AF_UNSPEC;
812         aio->aio_srcscope = -1;
813
814         switch(ai.ai_family) {
815         case AF_INET:
816 #ifdef INET6
817         case AF_INET6:
818 #endif
819                 break;
820         default:                /* ignore unsupported AFs explicitly */
821                 return;
822         }
823
824         /* XXX: make a dummy addrinfo to call connect() */
825         ai.ai_socktype = SOCK_DGRAM;
826         ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */
827         ai.ai_next = NULL;
828         memset(&ss, 0, sizeof(ss));
829         memcpy(&ss, ai.ai_addr, ai.ai_addrlen);
830         ai.ai_addr = (struct sockaddr *)&ss;
831         get_port(&ai, "1", 0);
832
833         /* open a socket to get the source address for the given dst */
834         if ((s = _socket(ai.ai_family, ai.ai_socktype | SOCK_CLOEXEC,
835             ai.ai_protocol)) < 0)
836                 return;         /* give up */
837         if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
838                 goto cleanup;
839         srclen = ai.ai_addrlen;
840         if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
841                 aio->aio_srcsa.sa_family = AF_UNSPEC;
842                 goto cleanup;
843         }
844         aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
845         aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
846         aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr);
847 #ifdef INET6
848         if (ai.ai_family == AF_INET6) {
849                 struct in6_ifreq ifr6;
850                 u_int32_t flags6;
851
852                 memset(&ifr6, 0, sizeof(ifr6));
853                 memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
854                 if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
855                         flags6 = ifr6.ifr_ifru.ifru_flags6;
856                         if ((flags6 & IN6_IFF_DEPRECATED))
857                                 aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
858                 }
859         }
860 #endif
861
862   cleanup:
863         _close(s);
864         return;
865 }
866
867 static int
868 matchlen(struct sockaddr *src, struct sockaddr *dst)
869 {
870         int match = 0;
871         u_char *s, *d;
872         u_char *lim, r;
873         int addrlen;
874
875         switch (src->sa_family) {
876 #ifdef INET6
877         case AF_INET6:
878                 s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
879                 d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
880                 addrlen = sizeof(struct in6_addr);
881                 lim = s + addrlen;
882                 break;
883 #endif
884         case AF_INET:
885                 s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
886                 d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
887                 addrlen = sizeof(struct in_addr);
888                 lim = s + addrlen;
889                 break;
890         default:
891                 return(0);
892         }
893
894         while (s < lim)
895                 if ((r = (*d++ ^ *s++)) != 0) {
896                         while (r < addrlen * 8) {
897                                 match++;
898                                 r <<= 1;
899                         }
900                         break;
901                 } else
902                         match += 8;
903         return(match);
904 }
905
906 static int
907 comp_dst(const void *arg1, const void *arg2)
908 {
909         const struct ai_order *dst1 = arg1, *dst2 = arg2;
910
911         /*
912          * Rule 1: Avoid unusable destinations.
913          * XXX: we currently do not consider if an appropriate route exists.
914          */
915         if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
916             dst2->aio_srcsa.sa_family == AF_UNSPEC) {
917                 return(-1);
918         }
919         if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
920             dst2->aio_srcsa.sa_family != AF_UNSPEC) {
921                 return(1);
922         }
923
924         /* Rule 2: Prefer matching scope. */
925         if (dst1->aio_dstscope == dst1->aio_srcscope &&
926             dst2->aio_dstscope != dst2->aio_srcscope) {
927                 return(-1);
928         }
929         if (dst1->aio_dstscope != dst1->aio_srcscope &&
930             dst2->aio_dstscope == dst2->aio_srcscope) {
931                 return(1);
932         }
933
934         /* Rule 3: Avoid deprecated addresses. */
935         if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
936             dst2->aio_srcsa.sa_family != AF_UNSPEC) {
937                 if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
938                     (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
939                         return(-1);
940                 }
941                 if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
942                     !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
943                         return(1);
944                 }
945         }
946
947         /* Rule 4: Prefer home addresses. */
948         /* XXX: not implemented yet */
949
950         /* Rule 5: Prefer matching label. */
951 #ifdef INET6
952         if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
953             dst1->aio_srcpolicy->pc_policy.label ==
954             dst1->aio_dstpolicy->pc_policy.label &&
955             (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
956              dst2->aio_srcpolicy->pc_policy.label !=
957              dst2->aio_dstpolicy->pc_policy.label)) {
958                 return(-1);
959         }
960         if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
961             dst2->aio_srcpolicy->pc_policy.label ==
962             dst2->aio_dstpolicy->pc_policy.label &&
963             (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
964              dst1->aio_srcpolicy->pc_policy.label !=
965              dst1->aio_dstpolicy->pc_policy.label)) {
966                 return(1);
967         }
968 #endif
969
970         /* Rule 6: Prefer higher precedence. */
971 #ifdef INET6
972         if (dst1->aio_dstpolicy &&
973             (dst2->aio_dstpolicy == NULL ||
974              dst1->aio_dstpolicy->pc_policy.preced >
975              dst2->aio_dstpolicy->pc_policy.preced)) {
976                 return(-1);
977         }
978         if (dst2->aio_dstpolicy &&
979             (dst1->aio_dstpolicy == NULL ||
980              dst2->aio_dstpolicy->pc_policy.preced >
981              dst1->aio_dstpolicy->pc_policy.preced)) {
982                 return(1);
983         }
984 #endif
985
986         /* Rule 7: Prefer native transport. */
987         /* XXX: not implemented yet */
988
989         /* Rule 8: Prefer smaller scope. */
990         if (dst1->aio_dstscope >= 0 &&
991             dst1->aio_dstscope < dst2->aio_dstscope) {
992                 return(-1);
993         }
994         if (dst2->aio_dstscope >= 0 &&
995             dst2->aio_dstscope < dst1->aio_dstscope) {
996                 return(1);
997         }
998
999         /*
1000          * Rule 9: Use longest matching prefix.
1001          * We compare the match length in a same AF only.
1002          */
1003         if (dst1->aio_ai->ai_addr->sa_family ==
1004             dst2->aio_ai->ai_addr->sa_family) {
1005                 if (dst1->aio_matchlen > dst2->aio_matchlen) {
1006                         return(-1);
1007                 }
1008                 if (dst1->aio_matchlen < dst2->aio_matchlen) {
1009                         return(1);
1010                 }
1011         }
1012
1013         /* Rule 10: Otherwise, leave the order unchanged. */
1014         return(-1);
1015 }
1016
1017 /*
1018  * Copy from scope.c.
1019  * XXX: we should standardize the functions and link them as standard
1020  * library.
1021  */
1022 static int
1023 gai_addr2scopetype(struct sockaddr *sa)
1024 {
1025 #ifdef INET6
1026         struct sockaddr_in6 *sa6;
1027 #endif
1028         struct sockaddr_in *sa4;
1029
1030         switch(sa->sa_family) {
1031 #ifdef INET6
1032         case AF_INET6:
1033                 sa6 = (struct sockaddr_in6 *)sa;
1034                 if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
1035                         /* just use the scope field of the multicast address */
1036                         return(sa6->sin6_addr.s6_addr[2] & 0x0f);
1037                 }
1038                 /*
1039                  * Unicast addresses: map scope type to corresponding scope
1040                  * value defined for multcast addresses.
1041                  * XXX: hardcoded scope type values are bad...
1042                  */
1043                 if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
1044                         return(1); /* node local scope */
1045                 if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
1046                         return(2); /* link-local scope */
1047                 if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
1048                         return(5); /* site-local scope */
1049                 return(14);     /* global scope */
1050                 break;
1051 #endif
1052         case AF_INET:
1053                 /*
1054                  * IPv4 pseudo scoping according to RFC 3484.
1055                  */
1056                 sa4 = (struct sockaddr_in *)sa;
1057                 /* IPv4 autoconfiguration addresses have link-local scope. */
1058                 if (((u_char *)&sa4->sin_addr)[0] == 169 &&
1059                     ((u_char *)&sa4->sin_addr)[1] == 254)
1060                         return(2);
1061                 /* Private addresses have site-local scope. */
1062                 if (((u_char *)&sa4->sin_addr)[0] == 10 ||
1063                     (((u_char *)&sa4->sin_addr)[0] == 172 &&
1064                      (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
1065                     (((u_char *)&sa4->sin_addr)[0] == 192 &&
1066                      ((u_char *)&sa4->sin_addr)[1] == 168))
1067                         return(14);     /* XXX: It should be 5 unless NAT */
1068                 /* Loopback addresses have link-local scope. */
1069                 if (((u_char *)&sa4->sin_addr)[0] == 127)
1070                         return(2);
1071                 return(14);
1072                 break;
1073         default:
1074                 errno = EAFNOSUPPORT; /* is this a good error? */
1075                 return(-1);
1076         }
1077 }
1078
1079 static int
1080 explore_copy(const struct addrinfo *pai, const struct addrinfo *src0,
1081     struct addrinfo **res)
1082 {
1083         int error;
1084         struct addrinfo sentinel, *cur;
1085         const struct addrinfo *src;
1086
1087         error = 0;
1088         sentinel.ai_next = NULL;
1089         cur = &sentinel;
1090
1091         for (src = src0; src != NULL; src = src->ai_next) {
1092                 if (src->ai_family != pai->ai_family)
1093                         continue;
1094
1095                 cur->ai_next = copy_ai(src);
1096                 if (!cur->ai_next) {
1097                         error = EAI_MEMORY;
1098                         goto fail;
1099                 }
1100
1101                 cur->ai_next->ai_socktype = pai->ai_socktype;
1102                 cur->ai_next->ai_protocol = pai->ai_protocol;
1103                 cur = cur->ai_next;
1104         }
1105
1106         *res = sentinel.ai_next;
1107         return 0;
1108
1109 fail:
1110         freeaddrinfo(sentinel.ai_next);
1111         return error;
1112 }
1113
1114 /*
1115  * hostname == NULL.
1116  * passive socket -> anyaddr (0.0.0.0 or ::)
1117  * non-passive socket -> localhost (127.0.0.1 or ::1)
1118  */
1119 static int
1120 explore_null(const struct addrinfo *pai, const char *servname,
1121     struct addrinfo **res)
1122 {
1123         int s;
1124         const struct afd *afd;
1125         struct addrinfo *ai;
1126         int error;
1127
1128         *res = NULL;
1129         ai = NULL;
1130
1131         /*
1132          * filter out AFs that are not supported by the kernel
1133          * XXX errno?
1134          */
1135         s = _socket(pai->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1136         if (s < 0) {
1137                 if (errno != EMFILE)
1138                         return 0;
1139         } else
1140                 _close(s);
1141
1142         afd = find_afd(pai->ai_family);
1143         if (afd == NULL)
1144                 return 0;
1145
1146         if (pai->ai_flags & AI_PASSIVE) {
1147                 GET_AI(ai, afd, afd->a_addrany);
1148                 GET_PORT(ai, servname);
1149         } else {
1150                 GET_AI(ai, afd, afd->a_loopback);
1151                 GET_PORT(ai, servname);
1152         }
1153
1154         *res = ai;
1155         return 0;
1156
1157 free:
1158         if (ai != NULL)
1159                 freeaddrinfo(ai);
1160         return error;
1161 }
1162
1163 /*
1164  * numeric hostname
1165  */
1166 static int
1167 explore_numeric(const struct addrinfo *pai, const char *hostname,
1168     const char *servname, struct addrinfo **res, const char *canonname)
1169 {
1170         const struct afd *afd;
1171         struct addrinfo *ai;
1172         int error;
1173         char pton[PTON_MAX];
1174
1175         *res = NULL;
1176         ai = NULL;
1177
1178         afd = find_afd(pai->ai_family);
1179         if (afd == NULL)
1180                 return 0;
1181
1182         switch (afd->a_af) {
1183         case AF_INET:
1184                 /*
1185                  * RFC3493 requires getaddrinfo() to accept AF_INET formats
1186                  * that are accepted by inet_addr() and its family.  The
1187                  * accepted forms includes the "classful" one, which inet_pton
1188                  * does not accept.  So we need to separate the case for
1189                  * AF_INET.
1190                  */
1191                 if (inet_aton(hostname, (struct in_addr *)pton) != 1)
1192                         return 0;
1193                 break;
1194         default:
1195                 if (inet_pton(afd->a_af, hostname, pton) != 1)
1196                         return 0;
1197                 break;
1198         }
1199
1200         if (pai->ai_family == afd->a_af) {
1201                 GET_AI(ai, afd, pton);
1202                 GET_PORT(ai, servname);
1203                 if ((pai->ai_flags & AI_CANONNAME)) {
1204                         /*
1205                          * Set the numeric address itself as the canonical
1206                          * name, based on a clarification in RFC3493.
1207                          */
1208                         GET_CANONNAME(ai, canonname);
1209                 }
1210         } else {
1211                 /*
1212                  * XXX: This should not happen since we already matched the AF
1213                  * by find_afd.
1214                  */
1215                 ERR(EAI_FAMILY);
1216         }
1217
1218         *res = ai;
1219         return 0;
1220
1221 free:
1222 bad:
1223         if (ai != NULL)
1224                 freeaddrinfo(ai);
1225         return error;
1226 }
1227
1228 /*
1229  * numeric hostname with scope
1230  */
1231 static int
1232 explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
1233     const char *servname, struct addrinfo **res)
1234 {
1235 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
1236         return explore_numeric(pai, hostname, servname, res, hostname);
1237 #else
1238         const struct afd *afd;
1239         struct addrinfo *cur;
1240         int error;
1241         char *cp, *hostname2 = NULL, *scope, *addr;
1242         struct sockaddr_in6 *sin6;
1243
1244         afd = find_afd(pai->ai_family);
1245         if (afd == NULL)
1246                 return 0;
1247
1248         if (!afd->a_scoped)
1249                 return explore_numeric(pai, hostname, servname, res, hostname);
1250
1251         cp = strchr(hostname, SCOPE_DELIMITER);
1252         if (cp == NULL)
1253                 return explore_numeric(pai, hostname, servname, res, hostname);
1254
1255         /*
1256          * Handle special case of <scoped_address><delimiter><scope id>
1257          */
1258         hostname2 = strdup(hostname);
1259         if (hostname2 == NULL)
1260                 return EAI_MEMORY;
1261         /* terminate at the delimiter */
1262         hostname2[cp - hostname] = '\0';
1263         addr = hostname2;
1264         scope = cp + 1;
1265
1266         error = explore_numeric(pai, addr, servname, res, hostname);
1267         if (error == 0) {
1268                 u_int32_t scopeid;
1269
1270                 for (cur = *res; cur; cur = cur->ai_next) {
1271                         if (cur->ai_family != AF_INET6)
1272                                 continue;
1273                         sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
1274                         if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
1275                                 free(hostname2);
1276                                 freeaddrinfo(*res);
1277                                 *res = NULL;
1278                                 return(EAI_NONAME); /* XXX: is return OK? */
1279                         }
1280                         sin6->sin6_scope_id = scopeid;
1281                 }
1282         }
1283
1284         free(hostname2);
1285
1286         if (error && *res) {
1287                 freeaddrinfo(*res);
1288                 *res = NULL;
1289         }
1290         return error;
1291 #endif
1292 }
1293
1294 static int
1295 get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
1296 {
1297         if ((pai->ai_flags & AI_CANONNAME) != 0) {
1298                 ai->ai_canonname = strdup(str);
1299                 if (ai->ai_canonname == NULL)
1300                         return EAI_MEMORY;
1301         }
1302         return 0;
1303 }
1304
1305 static struct addrinfo *
1306 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
1307 {
1308         char *p;
1309         struct addrinfo *ai;
1310 #ifdef FAITH
1311         struct in6_addr faith_prefix;
1312         char *fp_str;
1313         int translate = 0;
1314 #endif
1315
1316 #ifdef FAITH
1317         /*
1318          * Transfrom an IPv4 addr into a special IPv6 addr format for
1319          * IPv6->IPv4 translation gateway. (only TCP is supported now)
1320          *
1321          * +-----------------------------------+------------+
1322          * | faith prefix part (12 bytes)      | embedded   |
1323          * |                                   | IPv4 addr part (4 bytes)
1324          * +-----------------------------------+------------+
1325          *
1326          * faith prefix part is specified as ascii IPv6 addr format
1327          * in environmental variable GAI.
1328          * For FAITH to work correctly, routing to faith prefix must be
1329          * setup toward a machine where a FAITH daemon operates.
1330          * Also, the machine must enable some mechanizm
1331          * (e.g. faith interface hack) to divert those packet with
1332          * faith prefixed destination addr to user-land FAITH daemon.
1333          */
1334         fp_str = getenv("GAI");
1335         if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
1336             afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
1337                 u_int32_t v4a;
1338                 u_int8_t v4a_top;
1339
1340                 memcpy(&v4a, addr, sizeof v4a);
1341                 v4a_top = v4a >> IN_CLASSA_NSHIFT;
1342                 if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
1343                     v4a_top != 0 && v4a != IN_LOOPBACKNET) {
1344                         afd = &afdl[N_INET6];
1345                         memcpy(&faith_prefix.s6_addr[12], addr,
1346                                sizeof(struct in_addr));
1347                         translate = 1;
1348                 }
1349         }
1350 #endif
1351
1352         ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
1353                 + (afd->a_socklen));
1354         if (ai == NULL)
1355                 return NULL;
1356
1357         memcpy(ai, pai, sizeof(struct addrinfo));
1358         ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
1359         memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
1360         ai->ai_addr->sa_len = afd->a_socklen;
1361         ai->ai_addrlen = afd->a_socklen;
1362         ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1363         p = (char *)(void *)(ai->ai_addr);
1364 #ifdef FAITH
1365         if (translate == 1)
1366                 memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
1367         else
1368 #endif
1369         memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
1370         return ai;
1371 }
1372
1373 /* XXX need to malloc() the same way we do from other functions! */
1374 static struct addrinfo *
1375 copy_ai(const struct addrinfo *pai)
1376 {
1377         struct addrinfo *ai;
1378         size_t l;
1379
1380         l = sizeof(*ai) + pai->ai_addrlen;
1381         if ((ai = (struct addrinfo *)malloc(l)) == NULL)
1382                 return NULL;
1383         memset(ai, 0, l);
1384         memcpy(ai, pai, sizeof(*ai));
1385         ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
1386         memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
1387
1388         if (pai->ai_canonname) {
1389                 l = strlen(pai->ai_canonname) + 1;
1390                 if ((ai->ai_canonname = malloc(l)) == NULL) {
1391                         free(ai);
1392                         return NULL;
1393                 }
1394                 strlcpy(ai->ai_canonname, pai->ai_canonname, l);
1395         } else {
1396                 /* just to make sure */
1397                 ai->ai_canonname = NULL;
1398         }
1399
1400         ai->ai_next = NULL;
1401
1402         return ai;
1403 }
1404
1405 static int
1406 get_portmatch(const struct addrinfo *ai, const char *servname)
1407 {
1408
1409         /* get_port does not touch first argument when matchonly == 1. */
1410         /* LINTED const cast */
1411         return get_port((struct addrinfo *)ai, servname, 1);
1412 }
1413
1414 static int
1415 get_port(struct addrinfo *ai, const char *servname, int matchonly)
1416 {
1417         const char *proto;
1418         struct servent *sp;
1419         int port, error;
1420         int allownumeric;
1421
1422         if (servname == NULL)
1423                 return 0;
1424         switch (ai->ai_family) {
1425         case AF_INET:
1426 #ifdef AF_INET6
1427         case AF_INET6:
1428 #endif
1429                 break;
1430         default:
1431                 return 0;
1432         }
1433
1434         switch (ai->ai_socktype) {
1435         case SOCK_RAW:
1436                 return EAI_SERVICE;
1437         case SOCK_DGRAM:
1438         case SOCK_STREAM:
1439         case SOCK_SEQPACKET:
1440                 allownumeric = 1;
1441                 break;
1442         case ANY:
1443                 switch (ai->ai_family) {
1444                 case AF_INET:
1445 #ifdef AF_INET6
1446                 case AF_INET6:
1447 #endif
1448                         allownumeric = 1;
1449                         break;
1450                 default:
1451                         allownumeric = 0;
1452                         break;
1453                 }
1454                 break;
1455         default:
1456                 return EAI_SOCKTYPE;
1457         }
1458
1459         error = str2number(servname, &port);
1460         if (error == 0) {
1461                 if (!allownumeric)
1462                         return EAI_SERVICE;
1463                 if (port < 0 || port > 65535)
1464                         return EAI_SERVICE;
1465                 port = htons(port);
1466         } else {
1467                 if (ai->ai_flags & AI_NUMERICSERV)
1468                         return EAI_NONAME;
1469
1470                 switch (ai->ai_protocol) {
1471                 case IPPROTO_UDP:
1472                         proto = "udp";
1473                         break;
1474                 case IPPROTO_TCP:
1475                         proto = "tcp";
1476                         break;
1477                 case IPPROTO_SCTP:
1478                         proto = "sctp";
1479                         break;
1480                 default:
1481                         proto = NULL;
1482                         break;
1483                 }
1484
1485                 if ((sp = getservbyname(servname, proto)) == NULL)
1486                         return EAI_SERVICE;
1487                 port = sp->s_port;
1488         }
1489
1490         if (!matchonly) {
1491                 switch (ai->ai_family) {
1492                 case AF_INET:
1493                         ((struct sockaddr_in *)(void *)
1494                             ai->ai_addr)->sin_port = port;
1495                         break;
1496 #ifdef INET6
1497                 case AF_INET6:
1498                         ((struct sockaddr_in6 *)(void *)
1499                             ai->ai_addr)->sin6_port = port;
1500                         break;
1501 #endif
1502                 }
1503         }
1504
1505         return 0;
1506 }
1507
1508 static const struct afd *
1509 find_afd(int af)
1510 {
1511         const struct afd *afd;
1512
1513         if (af == PF_UNSPEC)
1514                 return NULL;
1515         for (afd = afdl; afd->a_af; afd++) {
1516                 if (afd->a_af == af)
1517                         return afd;
1518         }
1519         return NULL;
1520 }
1521
1522 /*
1523  * post-2553: AI_ADDRCONFIG check.  if we use getipnodeby* as backend, backend
1524  * will take care of it.
1525  * the semantics of AI_ADDRCONFIG is not defined well.  we are not sure
1526  * if the code is right or not.
1527  *
1528  * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
1529  * _dns_getaddrinfo.
1530  */
1531 static int
1532 addrconfig(struct addrinfo *pai)
1533 {
1534         int s, af;
1535
1536         /*
1537          * TODO:
1538          * Note that implementation dependent test for address
1539          * configuration should be done everytime called
1540          * (or apropriate interval),
1541          * because addresses will be dynamically assigned or deleted.
1542          */
1543         af = pai->ai_family;
1544         if (af == AF_UNSPEC) {
1545                 if ((s = _socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
1546                         af = AF_INET;
1547                 else {
1548                         _close(s);
1549                         if ((s = _socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC,
1550                             0)) < 0)
1551                                 af = AF_INET6;
1552                         else
1553                                 _close(s);
1554                 }
1555         }
1556         if (af != AF_UNSPEC) {
1557                 if ((s = _socket(af, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
1558                         return 0;
1559                 _close(s);
1560         }
1561         pai->ai_family = af;
1562         return 1;
1563 }
1564
1565 #ifdef INET6
1566 /* convert a string to a scope identifier. XXX: IPv6 specific */
1567 static int
1568 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
1569 {
1570         u_long lscopeid;
1571         struct in6_addr *a6;
1572         char *ep;
1573
1574         a6 = &sin6->sin6_addr;
1575
1576         /* empty scopeid portion is invalid */
1577         if (*scope == '\0')
1578                 return -1;
1579
1580         if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
1581             IN6_IS_ADDR_MC_NODELOCAL(a6)) {
1582                 /*
1583                  * We currently assume a one-to-one mapping between links
1584                  * and interfaces, so we simply use interface indices for
1585                  * like-local scopes.
1586                  */
1587                 *scopeid = if_nametoindex(scope);
1588                 if (*scopeid == 0)
1589                         goto trynumeric;
1590                 return 0;
1591         }
1592
1593         /* still unclear about literal, allow numeric only - placeholder */
1594         if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1595                 goto trynumeric;
1596         if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1597                 goto trynumeric;
1598         else
1599                 goto trynumeric;        /* global */
1600
1601         /* try to convert to a numeric id as a last resort */
1602   trynumeric:
1603         errno = 0;
1604         lscopeid = strtoul(scope, &ep, 10);
1605         *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1606         if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1607                 return 0;
1608         else
1609                 return -1;
1610 }
1611 #endif
1612
1613
1614 #ifdef NS_CACHING
1615 static int
1616 addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap,
1617     void *cache_mdata)
1618 {
1619         res_state statp;
1620         u_long res_options;
1621
1622         const int op_id = 0;    /* identifies the getaddrinfo for the cache */
1623         char *hostname;
1624         struct addrinfo *hints;
1625
1626         char *p;
1627         int ai_flags, ai_family, ai_socktype, ai_protocol;
1628         size_t desired_size, size;
1629
1630         statp = __res_state();
1631         res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
1632             RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
1633
1634         hostname = va_arg(ap, char *);
1635         hints = va_arg(ap, struct addrinfo *);
1636
1637         desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4;
1638         if (hostname != NULL) {
1639                 size = strlen(hostname);
1640                 desired_size += size + 1;
1641         } else
1642                 size = 0;
1643
1644         if (desired_size > *buffer_size) {
1645                 *buffer_size = desired_size;
1646                 return (NS_RETURN);
1647         }
1648
1649         if (hints == NULL)
1650                 ai_flags = ai_family = ai_socktype = ai_protocol = 0;
1651         else {
1652                 ai_flags = hints->ai_flags;
1653                 ai_family = hints->ai_family;
1654                 ai_socktype = hints->ai_socktype;
1655                 ai_protocol = hints->ai_protocol;
1656         }
1657
1658         p = buffer;
1659         memcpy(p, &res_options, sizeof(res_options));
1660         p += sizeof(res_options);
1661
1662         memcpy(p, &op_id, sizeof(int));
1663         p += sizeof(int);
1664
1665         memcpy(p, &ai_flags, sizeof(int));
1666         p += sizeof(int);
1667
1668         memcpy(p, &ai_family, sizeof(int));
1669         p += sizeof(int);
1670
1671         memcpy(p, &ai_socktype, sizeof(int));
1672         p += sizeof(int);
1673
1674         memcpy(p, &ai_protocol, sizeof(int));
1675         p += sizeof(int);
1676
1677         if (hostname != NULL)
1678                 memcpy(p, hostname, size);
1679
1680         *buffer_size = desired_size;
1681         return (NS_SUCCESS);
1682 }
1683
1684 static int
1685 addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval,
1686     va_list ap, void *cache_mdata)
1687 {
1688         struct addrinfo *ai, *cai;
1689         char *p;
1690         size_t desired_size, size, ai_size;
1691
1692         ai = *((struct addrinfo **)retval);
1693
1694         desired_size = sizeof(size_t);
1695         ai_size = 0;
1696         for (cai = ai; cai != NULL; cai = cai->ai_next) {
1697                 desired_size += sizeof(struct addrinfo) + cai->ai_addrlen;
1698                 if (cai->ai_canonname != NULL)
1699                         desired_size += sizeof(size_t) +
1700                             strlen(cai->ai_canonname);
1701                 ++ai_size;
1702         }
1703
1704         if (desired_size > *buffer_size) {
1705                 /* this assignment is here for future use */
1706                 errno = ERANGE;
1707                 *buffer_size = desired_size;
1708                 return (NS_RETURN);
1709         }
1710
1711         memset(buffer, 0, desired_size);
1712         p = buffer;
1713
1714         memcpy(p, &ai_size, sizeof(size_t));
1715         p += sizeof(size_t);
1716         for (cai = ai; cai != NULL; cai = cai->ai_next) {
1717                 memcpy(p, cai, sizeof(struct addrinfo));
1718                 p += sizeof(struct addrinfo);
1719
1720                 memcpy(p, cai->ai_addr, cai->ai_addrlen);
1721                 p += cai->ai_addrlen;
1722
1723                 if (cai->ai_canonname != NULL) {
1724                         size = strlen(cai->ai_canonname);
1725                         memcpy(p, &size, sizeof(size_t));
1726                         p += sizeof(size_t);
1727
1728                         memcpy(p, cai->ai_canonname, size);
1729                         p += size;
1730                 }
1731         }
1732
1733         return (NS_SUCCESS);
1734 }
1735
1736 static int
1737 addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
1738     va_list ap, void *cache_mdata)
1739 {
1740         struct addrinfo new_ai, *result, *sentinel, *lasts;
1741
1742         char *p;
1743         size_t ai_size, ai_i, size;
1744
1745         p = buffer;
1746         memcpy(&ai_size, p, sizeof(size_t));
1747         p += sizeof(size_t);
1748
1749         result = NULL;
1750         lasts = NULL;
1751         for (ai_i = 0; ai_i < ai_size; ++ai_i) {
1752                 memcpy(&new_ai, p, sizeof(struct addrinfo));
1753                 p += sizeof(struct addrinfo);
1754                 size = new_ai.ai_addrlen + sizeof(struct addrinfo) +
1755                         _ALIGNBYTES;
1756
1757                 sentinel = (struct addrinfo *)malloc(size);
1758                 memset(sentinel, 0, size);
1759
1760                 memcpy(sentinel, &new_ai, sizeof(struct addrinfo));
1761                 sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel +
1762                     sizeof(struct addrinfo));
1763
1764                 memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen);
1765                 p += new_ai.ai_addrlen;
1766
1767                 if (new_ai.ai_canonname != NULL) {
1768                         memcpy(&size, p, sizeof(size_t));
1769                         p += sizeof(size_t);
1770
1771                         sentinel->ai_canonname = (char *)malloc(size + 1);
1772                         memset(sentinel->ai_canonname, 0, size + 1);
1773
1774                         memcpy(sentinel->ai_canonname, p, size);
1775                         p += size;
1776                 }
1777
1778                 if (result == NULL) {
1779                         result = sentinel;
1780                         lasts = sentinel;
1781                 } else {
1782                         lasts->ai_next = sentinel;
1783                         lasts = sentinel;
1784                 }
1785         }
1786
1787         *((struct addrinfo **)retval) = result;
1788         return (NS_SUCCESS);
1789 }
1790 #endif /* NS_CACHING */
1791
1792 /*
1793  * FQDN hostname, DNS lookup
1794  */
1795 static int
1796 explore_fqdn(const struct addrinfo *pai, const char *hostname,
1797     const char *servname, struct addrinfo **res)
1798 {
1799         struct addrinfo *result;
1800         struct addrinfo *cur;
1801         int error = 0;
1802
1803 #ifdef NS_CACHING
1804         static const nss_cache_info cache_info =
1805         NS_COMMON_CACHE_INFO_INITIALIZER(
1806                 hosts, NULL, addrinfo_id_func, addrinfo_marshal_func,
1807                 addrinfo_unmarshal_func);
1808 #endif
1809         static const ns_dtab dtab[] = {
1810                 NS_FILES_CB(_files_getaddrinfo, NULL)
1811                 { NSSRC_DNS, _dns_getaddrinfo, NULL },  /* force -DHESIOD */
1812                 NS_NIS_CB(_yp_getaddrinfo, NULL)
1813 #ifdef NS_CACHING
1814                 NS_CACHE_CB(&cache_info)
1815 #endif
1816                 { 0 }
1817         };
1818
1819         result = NULL;
1820
1821         /*
1822          * if the servname does not match socktype/protocol, ignore it.
1823          */
1824         if (get_portmatch(pai, servname) != 0)
1825                 return 0;
1826
1827         switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
1828                         default_dns_files, hostname, pai)) {
1829         case NS_TRYAGAIN:
1830                 error = EAI_AGAIN;
1831                 goto free;
1832         case NS_UNAVAIL:
1833                 error = EAI_FAIL;
1834                 goto free;
1835         case NS_NOTFOUND:
1836                 error = EAI_NONAME;
1837                 goto free;
1838         case NS_SUCCESS:
1839                 error = 0;
1840                 for (cur = result; cur; cur = cur->ai_next) {
1841                         GET_PORT(cur, servname);
1842                         /* canonname should be filled already */
1843                 }
1844                 break;
1845         }
1846
1847         *res = result;
1848
1849         return 0;
1850
1851 free:
1852         if (result)
1853                 freeaddrinfo(result);
1854         return error;
1855 }
1856
1857 #ifdef DEBUG
1858 static const char AskedForGot[] =
1859         "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1860 #endif
1861
1862 static struct addrinfo *
1863 getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
1864     const struct addrinfo *pai, res_state res)
1865 {
1866         struct addrinfo sentinel, *cur;
1867         struct addrinfo ai;
1868         const struct afd *afd;
1869         char *canonname;
1870         const HEADER *hp;
1871         const u_char *cp;
1872         int n;
1873         const u_char *eom;
1874         char *bp, *ep;
1875         int type, class, ancount, qdcount;
1876         int haveanswer, had_error;
1877         char tbuf[MAXDNAME];
1878         int (*name_ok)(const char *);
1879         char hostbuf[8*1024];
1880
1881         memset(&sentinel, 0, sizeof(sentinel));
1882         cur = &sentinel;
1883
1884         canonname = NULL;
1885         eom = answer->buf + anslen;
1886         switch (qtype) {
1887         case T_A:
1888         case T_AAAA:
1889         case T_ANY:     /*use T_ANY only for T_A/T_AAAA lookup*/
1890                 name_ok = res_hnok;
1891                 break;
1892         default:
1893                 return (NULL);  /* XXX should be abort(); */
1894         }
1895         /*
1896          * find first satisfactory answer
1897          */
1898         hp = &answer->hdr;
1899         ancount = ntohs(hp->ancount);
1900         qdcount = ntohs(hp->qdcount);
1901         bp = hostbuf;
1902         ep = hostbuf + sizeof hostbuf;
1903         cp = answer->buf + HFIXEDSZ;
1904         if (qdcount != 1) {
1905                 RES_SET_H_ERRNO(res, NO_RECOVERY);
1906                 return (NULL);
1907         }
1908         n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1909         if ((n < 0) || !(*name_ok)(bp)) {
1910                 RES_SET_H_ERRNO(res, NO_RECOVERY);
1911                 return (NULL);
1912         }
1913         cp += n + QFIXEDSZ;
1914         if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1915                 /* res_send() has already verified that the query name is the
1916                  * same as the one we sent; this just gets the expanded name
1917                  * (i.e., with the succeeding search-domain tacked on).
1918                  */
1919                 n = strlen(bp) + 1;             /* for the \0 */
1920                 if (n >= MAXHOSTNAMELEN) {
1921                         RES_SET_H_ERRNO(res, NO_RECOVERY);
1922                         return (NULL);
1923                 }
1924                 canonname = bp;
1925                 bp += n;
1926                 /* The qname can be abbreviated, but h_name is now absolute. */
1927                 qname = canonname;
1928         }
1929         haveanswer = 0;
1930         had_error = 0;
1931         while (ancount-- > 0 && cp < eom && !had_error) {
1932                 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1933                 if ((n < 0) || !(*name_ok)(bp)) {
1934                         had_error++;
1935                         continue;
1936                 }
1937                 cp += n;                        /* name */
1938                 type = _getshort(cp);
1939                 cp += INT16SZ;                  /* type */
1940                 class = _getshort(cp);
1941                 cp += INT16SZ + INT32SZ;        /* class, TTL */
1942                 n = _getshort(cp);
1943                 cp += INT16SZ;                  /* len */
1944                 if (class != C_IN) {
1945                         /* XXX - debug? syslog? */
1946                         cp += n;
1947                         continue;               /* XXX - had_error++ ? */
1948                 }
1949                 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1950                     type == T_CNAME) {
1951                         n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1952                         if ((n < 0) || !(*name_ok)(tbuf)) {
1953                                 had_error++;
1954                                 continue;
1955                         }
1956                         cp += n;
1957                         /* Get canonical name. */
1958                         n = strlen(tbuf) + 1;   /* for the \0 */
1959                         if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1960                                 had_error++;
1961                                 continue;
1962                         }
1963                         strlcpy(bp, tbuf, ep - bp);
1964                         canonname = bp;
1965                         bp += n;
1966                         continue;
1967                 }
1968                 if (qtype == T_ANY) {
1969                         if (!(type == T_A || type == T_AAAA)) {
1970                                 cp += n;
1971                                 continue;
1972                         }
1973                 } else if (type != qtype) {
1974 #ifdef DEBUG
1975                         if (type != T_KEY && type != T_SIG &&
1976                             type != ns_t_dname)
1977                                 syslog(LOG_NOTICE|LOG_AUTH,
1978                "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1979                                        qname, p_class(C_IN), p_type(qtype),
1980                                        p_type(type));
1981 #endif
1982                         cp += n;
1983                         continue;               /* XXX - had_error++ ? */
1984                 }
1985                 switch (type) {
1986                 case T_A:
1987                 case T_AAAA:
1988                         if (strcasecmp(canonname, bp) != 0) {
1989 #ifdef DEBUG
1990                                 syslog(LOG_NOTICE|LOG_AUTH,
1991                                        AskedForGot, canonname, bp);
1992 #endif
1993                                 cp += n;
1994                                 continue;       /* XXX - had_error++ ? */
1995                         }
1996                         if (type == T_A && n != INADDRSZ) {
1997                                 cp += n;
1998                                 continue;
1999                         }
2000                         if (type == T_AAAA && n != IN6ADDRSZ) {
2001                                 cp += n;
2002                                 continue;
2003                         }
2004 #ifdef FILTER_V4MAPPED
2005                         if (type == T_AAAA) {
2006                                 struct in6_addr in6;
2007                                 memcpy(&in6, cp, sizeof(in6));
2008                                 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
2009                                         cp += n;
2010                                         continue;
2011                                 }
2012                         }
2013 #endif
2014                         if (!haveanswer) {
2015                                 int nn;
2016
2017                                 canonname = bp;
2018                                 nn = strlen(bp) + 1;    /* for the \0 */
2019                                 bp += nn;
2020                         }
2021
2022                         /* don't overwrite pai */
2023                         ai = *pai;
2024                         ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
2025                         afd = find_afd(ai.ai_family);
2026                         if (afd == NULL) {
2027                                 cp += n;
2028                                 continue;
2029                         }
2030                         cur->ai_next = get_ai(&ai, afd, (const char *)cp);
2031                         if (cur->ai_next == NULL)
2032                                 had_error++;
2033                         while (cur && cur->ai_next)
2034                                 cur = cur->ai_next;
2035                         cp += n;
2036                         break;
2037                 default:
2038                         abort();
2039                 }
2040                 if (!had_error)
2041                         haveanswer++;
2042         }
2043         if (haveanswer) {
2044 #if defined(RESOLVSORT)
2045                 /*
2046                  * We support only IPv4 address for backward
2047                  * compatibility against gethostbyname(3).
2048                  */
2049                 if (res->nsort && qtype == T_A) {
2050                         if (addr4sort(&sentinel, res) < 0) {
2051                                 freeaddrinfo(sentinel.ai_next);
2052                                 RES_SET_H_ERRNO(res, NO_RECOVERY);
2053                                 return NULL;
2054                         }
2055                 }
2056 #endif /*RESOLVSORT*/
2057                 if (!canonname)
2058                         (void)get_canonname(pai, sentinel.ai_next, qname);
2059                 else
2060                         (void)get_canonname(pai, sentinel.ai_next, canonname);
2061                 RES_SET_H_ERRNO(res, NETDB_SUCCESS);
2062                 return sentinel.ai_next;
2063         }
2064
2065         RES_SET_H_ERRNO(res, NO_RECOVERY);
2066         return NULL;
2067 }
2068
2069 #ifdef RESOLVSORT
2070 struct addr_ptr {
2071         struct addrinfo *ai;
2072         int aval;
2073 };
2074
2075 static int
2076 addr4sort(struct addrinfo *sentinel, res_state res)
2077 {
2078         struct addrinfo *ai;
2079         struct addr_ptr *addrs, addr;
2080         struct sockaddr_in *sin;
2081         int naddrs, i, j;
2082         int needsort = 0;
2083
2084         if (!sentinel)
2085                 return -1;
2086         naddrs = 0;
2087         for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
2088                 naddrs++;
2089         if (naddrs < 2)
2090                 return 0;               /* We don't need sorting. */
2091         if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
2092                 return -1;
2093         i = 0;
2094         for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
2095                 sin = (struct sockaddr_in *)ai->ai_addr;
2096                 for (j = 0; (unsigned)j < res->nsort; j++) {
2097                         if (res->sort_list[j].addr.s_addr ==
2098                             (sin->sin_addr.s_addr & res->sort_list[j].mask))
2099                                 break;
2100                 }
2101                 addrs[i].ai = ai;
2102                 addrs[i].aval = j;
2103                 if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
2104                         needsort = i;
2105                 i++;
2106         }
2107         if (!needsort) {
2108                 free(addrs);
2109                 return 0;
2110         }
2111
2112         while (needsort < naddrs) {
2113                 for (j = needsort - 1; j >= 0; j--) {
2114                         if (addrs[j].aval > addrs[j+1].aval) {
2115                                 addr = addrs[j];
2116                                 addrs[j] = addrs[j + 1];
2117                                 addrs[j + 1] = addr;
2118                         } else
2119                                 break;
2120                 }
2121                 needsort++;
2122         }
2123
2124         ai = sentinel;
2125         for (i = 0; i < naddrs; ++i) {
2126                 ai->ai_next = addrs[i].ai;
2127                 ai = ai->ai_next;
2128         }
2129         ai->ai_next = NULL;
2130         free(addrs);
2131         return 0;
2132 }
2133 #endif /*RESOLVSORT*/
2134
2135 /*ARGSUSED*/
2136 static int
2137 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
2138 {
2139         struct addrinfo *ai;
2140         querybuf *buf, *buf2;
2141         const char *hostname;
2142         const struct addrinfo *pai;
2143         struct addrinfo sentinel, *cur;
2144         struct res_target q, q2;
2145         res_state res;
2146
2147         hostname = va_arg(ap, char *);
2148         pai = va_arg(ap, const struct addrinfo *);
2149
2150         memset(&q, 0, sizeof(q));
2151         memset(&q2, 0, sizeof(q2));
2152         memset(&sentinel, 0, sizeof(sentinel));
2153         cur = &sentinel;
2154
2155         buf = malloc(sizeof(*buf));
2156         if (!buf) {
2157                 RES_SET_H_ERRNO(res, NETDB_INTERNAL);
2158                 return NS_NOTFOUND;
2159         }
2160         buf2 = malloc(sizeof(*buf2));
2161         if (!buf2) {
2162                 free(buf);
2163                 RES_SET_H_ERRNO(res, NETDB_INTERNAL);
2164                 return NS_NOTFOUND;
2165         }
2166
2167         switch (pai->ai_family) {
2168         case AF_UNSPEC:
2169                 q.name = hostname;
2170                 q.qclass = C_IN;
2171                 q.qtype = T_A;
2172                 q.answer = buf->buf;
2173                 q.anslen = sizeof(buf->buf);
2174                 q.next = &q2;
2175                 q2.name = hostname;
2176                 q2.qclass = C_IN;
2177                 q2.qtype = T_AAAA;
2178                 q2.answer = buf2->buf;
2179                 q2.anslen = sizeof(buf2->buf);
2180                 break;
2181         case AF_INET:
2182                 q.name = hostname;
2183                 q.qclass = C_IN;
2184                 q.qtype = T_A;
2185                 q.answer = buf->buf;
2186                 q.anslen = sizeof(buf->buf);
2187                 break;
2188         case AF_INET6:
2189                 q.name = hostname;
2190                 q.qclass = C_IN;
2191                 q.qtype = T_AAAA;
2192                 q.answer = buf->buf;
2193                 q.anslen = sizeof(buf->buf);
2194                 break;
2195         default:
2196                 free(buf);
2197                 free(buf2);
2198                 return NS_UNAVAIL;
2199         }
2200
2201         res = __res_state();
2202         if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) {
2203                 RES_SET_H_ERRNO(res, NETDB_INTERNAL);
2204                 free(buf);
2205                 free(buf2);
2206                 return NS_NOTFOUND;
2207         }
2208
2209         if (res_searchN(hostname, &q, res) < 0) {
2210                 free(buf);
2211                 free(buf2);
2212                 return NS_NOTFOUND;
2213         }
2214         /* prefer IPv6 */
2215         if (q.next) {
2216                 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res);
2217                 if (ai) {
2218                         cur->ai_next = ai;
2219                         while (cur && cur->ai_next)
2220                                 cur = cur->ai_next;
2221                 }
2222         }
2223         ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
2224         if (ai)
2225                 cur->ai_next = ai;
2226         free(buf);
2227         free(buf2);
2228         if (sentinel.ai_next == NULL)
2229                 switch (res->res_h_errno) {
2230                 case HOST_NOT_FOUND:
2231                         return NS_NOTFOUND;
2232                 case TRY_AGAIN:
2233                         return NS_TRYAGAIN;
2234                 default:
2235                         return NS_UNAVAIL;
2236                 }
2237         *((struct addrinfo **)rv) = sentinel.ai_next;
2238         return NS_SUCCESS;
2239 }
2240
2241 static void
2242 _sethtent(FILE **hostf)
2243 {
2244         if (!*hostf)
2245                 *hostf = fopen(_PATH_HOSTS, "re");
2246         else
2247                 rewind(*hostf);
2248 }
2249
2250 static void
2251 _endhtent(FILE **hostf)
2252 {
2253         if (*hostf) {
2254                 (void) fclose(*hostf);
2255                 *hostf = NULL;
2256         }
2257 }
2258
2259 static struct addrinfo *
2260 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
2261 {
2262         char *p;
2263         char *cp, *tname, *cname;
2264         struct addrinfo hints, *res0, *res;
2265         int error;
2266         const char *addr;
2267         char hostbuf[8*1024];
2268
2269         if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re")))
2270                 return (NULL);
2271 again:
2272         if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
2273                 return (NULL);
2274         if (*p == '#')
2275                 goto again;
2276         cp = strpbrk(p, "#\n");
2277         if (cp != NULL)
2278                 *cp = '\0';
2279         if (!(cp = strpbrk(p, " \t")))
2280                 goto again;
2281         *cp++ = '\0';
2282         addr = p;
2283         cname = NULL;
2284         /* if this is not something we're looking for, skip it. */
2285         while (cp && *cp) {
2286                 if (*cp == ' ' || *cp == '\t') {
2287                         cp++;
2288                         continue;
2289                 }
2290                 tname = cp;
2291                 if (cname == NULL)
2292                         cname = cp;
2293                 if ((cp = strpbrk(cp, " \t")) != NULL)
2294                         *cp++ = '\0';
2295                 if (strcasecmp(name, tname) == 0)
2296                         goto found;
2297         }
2298         goto again;
2299
2300 found:
2301         /* we should not glob socktype/protocol here */
2302         memset(&hints, 0, sizeof(hints));
2303         hints.ai_family = pai->ai_family;
2304         hints.ai_socktype = SOCK_DGRAM;
2305         hints.ai_protocol = 0;
2306         hints.ai_flags = AI_NUMERICHOST;
2307         error = getaddrinfo(addr, "0", &hints, &res0);
2308         if (error)
2309                 goto again;
2310 #ifdef FILTER_V4MAPPED
2311         /* XXX should check all items in the chain */
2312         if (res0->ai_family == AF_INET6 &&
2313             IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
2314                 freeaddrinfo(res0);
2315                 goto again;
2316         }
2317 #endif
2318         for (res = res0; res; res = res->ai_next) {
2319                 /* cover it up */
2320                 res->ai_flags = pai->ai_flags;
2321                 res->ai_socktype = pai->ai_socktype;
2322                 res->ai_protocol = pai->ai_protocol;
2323
2324                 if (pai->ai_flags & AI_CANONNAME) {
2325                         if (get_canonname(pai, res, cname) != 0) {
2326                                 freeaddrinfo(res0);
2327                                 goto again;
2328                         }
2329                 }
2330         }
2331         return res0;
2332 }
2333
2334 /*ARGSUSED*/
2335 static int
2336 _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
2337 {
2338         const char *name;
2339         const struct addrinfo *pai;
2340         struct addrinfo sentinel, *cur;
2341         struct addrinfo *p;
2342         FILE *hostf = NULL;
2343
2344         name = va_arg(ap, char *);
2345         pai = va_arg(ap, struct addrinfo *);
2346
2347         memset(&sentinel, 0, sizeof(sentinel));
2348         cur = &sentinel;
2349
2350         _sethtent(&hostf);
2351         while ((p = _gethtent(&hostf, name, pai)) != NULL) {
2352                 cur->ai_next = p;
2353                 while (cur && cur->ai_next)
2354                         cur = cur->ai_next;
2355         }
2356         _endhtent(&hostf);
2357
2358         *((struct addrinfo **)rv) = sentinel.ai_next;
2359         if (sentinel.ai_next == NULL)
2360                 return NS_NOTFOUND;
2361         return NS_SUCCESS;
2362 }
2363
2364 #ifdef YP
2365 /*ARGSUSED*/
2366 static struct addrinfo *
2367 _yphostent(char *line, const struct addrinfo *pai)
2368 {
2369         struct addrinfo sentinel, *cur;
2370         struct addrinfo hints, *res, *res0;
2371         int error;
2372         char *p = line;
2373         const char *addr, *canonname;
2374         char *nextline;
2375         char *cp;
2376
2377         addr = canonname = NULL;
2378
2379         memset(&sentinel, 0, sizeof(sentinel));
2380         cur = &sentinel;
2381
2382 nextline:
2383         /* terminate line */
2384         cp = strchr(p, '\n');
2385         if (cp) {
2386                 *cp++ = '\0';
2387                 nextline = cp;
2388         } else
2389                 nextline = NULL;
2390
2391         cp = strpbrk(p, " \t");
2392         if (cp == NULL) {
2393                 if (canonname == NULL)
2394                         return (NULL);
2395                 else
2396                         goto done;
2397         }
2398         *cp++ = '\0';
2399
2400         addr = p;
2401
2402         while (cp && *cp) {
2403                 if (*cp == ' ' || *cp == '\t') {
2404                         cp++;
2405                         continue;
2406                 }
2407                 if (!canonname)
2408                         canonname = cp;
2409                 if ((cp = strpbrk(cp, " \t")) != NULL)
2410                         *cp++ = '\0';
2411         }
2412
2413         hints = *pai;
2414         hints.ai_flags = AI_NUMERICHOST;
2415         error = getaddrinfo(addr, NULL, &hints, &res0);
2416         if (error == 0) {
2417                 for (res = res0; res; res = res->ai_next) {
2418                         /* cover it up */
2419                         res->ai_flags = pai->ai_flags;
2420
2421                         if (pai->ai_flags & AI_CANONNAME)
2422                                 (void)get_canonname(pai, res, canonname);
2423                 }
2424         } else
2425                 res0 = NULL;
2426         if (res0) {
2427                 cur->ai_next = res0;
2428                 while (cur && cur->ai_next)
2429                         cur = cur->ai_next;
2430         }
2431
2432         if (nextline) {
2433                 p = nextline;
2434                 goto nextline;
2435         }
2436
2437 done:
2438         return sentinel.ai_next;
2439 }
2440
2441 /*ARGSUSED*/
2442 static int
2443 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
2444 {
2445         struct addrinfo sentinel, *cur;
2446         struct addrinfo *ai = NULL;
2447         char *ypbuf;
2448         int ypbuflen, r;
2449         const char *name;
2450         const struct addrinfo *pai;
2451         char *ypdomain;
2452
2453         if (_yp_check(&ypdomain) == 0)
2454                 return NS_UNAVAIL;
2455
2456         name = va_arg(ap, char *);
2457         pai = va_arg(ap, const struct addrinfo *);
2458
2459         memset(&sentinel, 0, sizeof(sentinel));
2460         cur = &sentinel;
2461
2462         /* hosts.byname is only for IPv4 (Solaris8) */
2463         if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
2464                 r = yp_match(ypdomain, "hosts.byname", name,
2465                         (int)strlen(name), &ypbuf, &ypbuflen);
2466                 if (r == 0) {
2467                         struct addrinfo ai4;
2468
2469                         ai4 = *pai;
2470                         ai4.ai_family = AF_INET;
2471                         ai = _yphostent(ypbuf, &ai4);
2472                         if (ai) {
2473                                 cur->ai_next = ai;
2474                                 while (cur && cur->ai_next)
2475                                         cur = cur->ai_next;
2476                         }
2477                         free(ypbuf);
2478                 }
2479         }
2480
2481         /* ipnodes.byname can hold both IPv4/v6 */
2482         r = yp_match(ypdomain, "ipnodes.byname", name,
2483                 (int)strlen(name), &ypbuf, &ypbuflen);
2484         if (r == 0) {
2485                 ai = _yphostent(ypbuf, pai);
2486                 if (ai)
2487                         cur->ai_next = ai;
2488                 free(ypbuf);
2489         }
2490
2491         if (sentinel.ai_next == NULL) {
2492                 RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
2493                 return NS_NOTFOUND;
2494         }
2495         *((struct addrinfo **)rv) = sentinel.ai_next;
2496         return NS_SUCCESS;
2497 }
2498 #endif
2499
2500 /* resolver logic */
2501
2502 /*
2503  * Formulate a normal query, send, and await answer.
2504  * Returned answer is placed in supplied buffer "answer".
2505  * Perform preliminary check of answer, returning success only
2506  * if no error is indicated and the answer count is nonzero.
2507  * Return the size of the response on success, -1 on error.
2508  * Error number is left in h_errno.
2509  *
2510  * Caller must parse answer and determine whether it answers the question.
2511  */
2512 static int
2513 res_queryN(const char *name, struct res_target *target, res_state res)
2514 {
2515         u_char *buf;
2516         HEADER *hp;
2517         int n;
2518         u_int oflags;
2519         struct res_target *t;
2520         int rcode;
2521         int ancount;
2522
2523         rcode = NOERROR;
2524         ancount = 0;
2525
2526         buf = malloc(MAXPACKET);
2527         if (!buf) {
2528                 RES_SET_H_ERRNO(res, NETDB_INTERNAL);
2529                 return -1;
2530         }
2531
2532         for (t = target; t; t = t->next) {
2533                 int class, type;
2534                 u_char *answer;
2535                 int anslen;
2536
2537                 hp = (HEADER *)(void *)t->answer;
2538
2539                 /* make it easier... */
2540                 class = t->qclass;
2541                 type = t->qtype;
2542                 answer = t->answer;
2543                 anslen = t->anslen;
2544
2545                 oflags = res->_flags;
2546
2547 again:
2548                 hp->rcode = NOERROR;    /* default */
2549
2550 #ifdef DEBUG
2551                 if (res->options & RES_DEBUG)
2552                         printf(";; res_query(%s, %d, %d)\n", name, class, type);
2553 #endif
2554
2555                 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
2556                     buf, MAXPACKET);
2557                 if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
2558                     (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
2559                         n = res_nopt(res, n, buf, MAXPACKET, anslen);
2560                 if (n <= 0) {
2561 #ifdef DEBUG
2562                         if (res->options & RES_DEBUG)
2563                                 printf(";; res_query: mkquery failed\n");
2564 #endif
2565                         free(buf);
2566                         RES_SET_H_ERRNO(res, NO_RECOVERY);
2567                         return (n);
2568                 }
2569                 n = res_nsend(res, buf, n, answer, anslen);
2570                 if (n < 0) {
2571                         /*
2572                          * if the query choked with EDNS0, retry
2573                          * without EDNS0
2574                          */
2575                         if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC))
2576                             != 0U &&
2577                             ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
2578                                 res->_flags |= RES_F_EDNS0ERR;
2579                                 if (res->options & RES_DEBUG)
2580                                         printf(";; res_nquery: retry without EDNS0\n");
2581                                 goto again;
2582                         }
2583                         rcode = hp->rcode;      /* record most recent error */
2584 #ifdef DEBUG
2585                         if (res->options & RES_DEBUG)
2586                                 printf(";; res_query: send error\n");
2587 #endif
2588                         continue;
2589                 }
2590
2591                 if (n > anslen)
2592                         hp->rcode = FORMERR; /* XXX not very informative */
2593                 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
2594                         rcode = hp->rcode;      /* record most recent error */
2595 #ifdef DEBUG
2596                         if (res->options & RES_DEBUG)
2597                                 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
2598                                     ntohs(hp->ancount));
2599 #endif
2600                         continue;
2601                 }
2602
2603                 ancount += ntohs(hp->ancount);
2604
2605                 t->n = n;
2606         }
2607
2608         free(buf);
2609
2610         if (ancount == 0) {
2611                 switch (rcode) {
2612                 case NXDOMAIN:
2613                         RES_SET_H_ERRNO(res, HOST_NOT_FOUND);
2614                         break;
2615                 case SERVFAIL:
2616                         RES_SET_H_ERRNO(res, TRY_AGAIN);
2617                         break;
2618                 case NOERROR:
2619                         RES_SET_H_ERRNO(res, NO_DATA);
2620                         break;
2621                 case FORMERR:
2622                 case NOTIMP:
2623                 case REFUSED:
2624                 default:
2625                         RES_SET_H_ERRNO(res, NO_RECOVERY);
2626                         break;
2627                 }
2628                 return (-1);
2629         }
2630         return (ancount);
2631 }
2632
2633 /*
2634  * Formulate a normal query, send, and retrieve answer in supplied buffer.
2635  * Return the size of the response on success, -1 on error.
2636  * If enabled, implement search rules until answer or unrecoverable failure
2637  * is detected.  Error code, if any, is left in h_errno.
2638  */
2639 static int
2640 res_searchN(const char *name, struct res_target *target, res_state res)
2641 {
2642         const char *cp, * const *domain;
2643         HEADER *hp = (HEADER *)(void *)target->answer;  /*XXX*/
2644         u_int dots;
2645         int trailing_dot, ret, saved_herrno;
2646         int got_nodata = 0, got_servfail = 0, root_on_list = 0;
2647         int tried_as_is = 0;
2648         int searched = 0;
2649         char abuf[MAXDNAME];
2650
2651         errno = 0;
2652         RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */
2653         dots = 0;
2654         for (cp = name; *cp; cp++)
2655                 dots += (*cp == '.');
2656         trailing_dot = 0;
2657         if (cp > name && *--cp == '.')
2658                 trailing_dot++;
2659
2660         /*
2661          * if there aren't any dots, it could be a user-level alias
2662          */
2663         if (!dots &&
2664             (cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL)
2665                 return (res_queryN(cp, target, res));
2666
2667         /*
2668          * If there are enough dots in the name, let's just give it a
2669          * try 'as is'. The threshold can be set with the "ndots" option.
2670          * Also, query 'as is', if there is a trailing dot in the name.
2671          */
2672         saved_herrno = -1;
2673         if (dots >= res->ndots || trailing_dot) {
2674                 ret = res_querydomainN(name, NULL, target, res);
2675                 if (ret > 0 || trailing_dot)
2676                         return (ret);
2677                 if (errno == ECONNREFUSED) {
2678                         RES_SET_H_ERRNO(res, TRY_AGAIN);
2679                         return (-1);
2680                 }
2681                 switch (res->res_h_errno) {
2682                 case NO_DATA:
2683                 case HOST_NOT_FOUND:
2684                         break;
2685                 case TRY_AGAIN:
2686                         if (hp->rcode == SERVFAIL)
2687                                 break;
2688                         /* FALLTHROUGH */
2689                 default:
2690                         return (-1);
2691                 }
2692                 saved_herrno = res->res_h_errno;
2693                 tried_as_is++;
2694         }
2695
2696         /*
2697          * We do at least one level of search if
2698          *      - there is no dot and RES_DEFNAME is set, or
2699          *      - there is at least one dot, there is no trailing dot,
2700          *        and RES_DNSRCH is set.
2701          */
2702         if ((!dots && (res->options & RES_DEFNAMES)) ||
2703             (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
2704                 int done = 0;
2705
2706                 for (domain = (const char * const *)res->dnsrch;
2707                    *domain && !done;
2708                    domain++) {
2709                         searched = 1;
2710
2711                         if (domain[0][0] == '\0' ||
2712                             (domain[0][0] == '.' && domain[0][1] == '\0'))
2713                                 root_on_list++;
2714
2715                         if (root_on_list && tried_as_is)
2716                                 continue;
2717
2718                         ret = res_querydomainN(name, *domain, target, res);
2719                         if (ret > 0)
2720                                 return (ret);
2721
2722                         /*
2723                          * If no server present, give up.
2724                          * If name isn't found in this domain,
2725                          * keep trying higher domains in the search list
2726                          * (if that's enabled).
2727                          * On a NO_DATA error, keep trying, otherwise
2728                          * a wildcard entry of another type could keep us
2729                          * from finding this entry higher in the domain.
2730                          * If we get some other error (negative answer or
2731                          * server failure), then stop searching up,
2732                          * but try the input name below in case it's
2733                          * fully-qualified.
2734                          */
2735                         if (errno == ECONNREFUSED) {
2736                                 RES_SET_H_ERRNO(res, TRY_AGAIN);
2737                                 return (-1);
2738                         }
2739
2740                         switch (res->res_h_errno) {
2741                         case NO_DATA:
2742                                 got_nodata++;
2743                                 /* FALLTHROUGH */
2744                         case HOST_NOT_FOUND:
2745                                 /* keep trying */
2746                                 break;
2747                         case TRY_AGAIN:
2748                                 got_servfail++;
2749                                 if (hp->rcode == SERVFAIL) {
2750                                         /* try next search element, if any */
2751                                         break;
2752                                 }
2753                                 /* FALLTHROUGH */
2754                         default:
2755                                 /* anything else implies that we're done */
2756                                 done++;
2757                         }
2758                         /*
2759                          * if we got here for some reason other than DNSRCH,
2760                          * we only wanted one iteration of the loop, so stop.
2761                          */
2762                         if (!(res->options & RES_DNSRCH))
2763                                 done++;
2764                 }
2765         }
2766
2767         switch (res->res_h_errno) {
2768         case NO_DATA:
2769         case HOST_NOT_FOUND:
2770                 break;
2771         case TRY_AGAIN:
2772                 if (hp->rcode == SERVFAIL)
2773                         break;
2774                 /* FALLTHROUGH */
2775         default:
2776                 goto giveup;
2777         }
2778
2779         /*
2780          * If the query has not already been tried as is then try it
2781          * unless RES_NOTLDQUERY is set and there were no dots.
2782          */
2783         if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) &&
2784             !(tried_as_is || root_on_list)) {
2785                 ret = res_querydomainN(name, NULL, target, res);
2786                 if (ret > 0)
2787                         return (ret);
2788         }
2789
2790         /*
2791          * if we got here, we didn't satisfy the search.
2792          * if we did an initial full query, return that query's h_errno
2793          * (note that we wouldn't be here if that query had succeeded).
2794          * else if we ever got a nodata, send that back as the reason.
2795          * else send back meaningless h_errno, that being the one from
2796          * the last DNSRCH we did.
2797          */
2798 giveup:
2799         if (saved_herrno != -1)
2800                 RES_SET_H_ERRNO(res, saved_herrno);
2801         else if (got_nodata)
2802                 RES_SET_H_ERRNO(res, NO_DATA);
2803         else if (got_servfail)
2804                 RES_SET_H_ERRNO(res, TRY_AGAIN);
2805         return (-1);
2806 }
2807
2808 /*
2809  * Perform a call on res_query on the concatenation of name and domain,
2810  * removing a trailing dot from name if domain is NULL.
2811  */
2812 static int
2813 res_querydomainN(const char *name, const char *domain,
2814     struct res_target *target, res_state res)
2815 {
2816         char nbuf[MAXDNAME];
2817         const char *longname = nbuf;
2818         size_t n, d;
2819
2820 #ifdef DEBUG
2821         if (res->options & RES_DEBUG)
2822                 printf(";; res_querydomain(%s, %s)\n",
2823                         name, domain?domain:"<Nil>");
2824 #endif
2825         if (domain == NULL) {
2826                 /*
2827                  * Check for trailing '.';
2828                  * copy without '.' if present.
2829                  */
2830                 n = strlen(name);
2831                 if (n >= MAXDNAME) {
2832                         RES_SET_H_ERRNO(res, NO_RECOVERY);
2833                         return (-1);
2834                 }
2835                 if (n > 0 && name[--n] == '.') {
2836                         strncpy(nbuf, name, n);
2837                         nbuf[n] = '\0';
2838                 } else
2839                         longname = name;
2840         } else {
2841                 n = strlen(name);
2842                 d = strlen(domain);
2843                 if (n + d + 1 >= MAXDNAME) {
2844                         RES_SET_H_ERRNO(res, NO_RECOVERY);
2845                         return (-1);
2846                 }
2847                 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
2848         }
2849         return (res_queryN(longname, target, res));
2850 }