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