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