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