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