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