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