1/*
2 * Copyright (C) 2009, 2012-2014  Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* $Id: getaddrinfo.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
18
19/*! \file */
20
21/**
22 *    getaddrinfo() is used to get a list of IP addresses and port
23 *    numbers for host hostname and service servname as defined in RFC3493.
24 *    hostname and servname are pointers to null-terminated strings
25 *    or NULL. hostname is either a host name or a numeric host address
26 *    string: a dotted decimal IPv4 address or an IPv6 address. servname is
27 *    either a decimal port number or a service name as listed in
28 *    /etc/services.
29 *
30 *    If the operating system does not provide a struct addrinfo, the
31 *    following structure is used:
32 *
33 * \code
34 * struct  addrinfo {
35 *         int             ai_flags;       // AI_PASSIVE, AI_CANONNAME
36 *         int             ai_family;      // PF_xxx
37 *         int             ai_socktype;    // SOCK_xxx
38 *         int             ai_protocol;    // 0 or IPPROTO_xxx for IPv4 and IPv6
39 *         size_t          ai_addrlen;     // length of ai_addr
40 *         char            *ai_canonname;  // canonical name for hostname
41 *         struct sockaddr *ai_addr;       // binary address
42 *         struct addrinfo *ai_next;       // next structure in linked list
43 * };
44 * \endcode
45 *
46 *
47 *    hints is an optional pointer to a struct addrinfo. This structure can
48 *    be used to provide hints concerning the type of socket that the caller
49 *    supports or wishes to use. The caller can supply the following
50 *    structure elements in *hints:
51 *
52 * <ul>
53 *    <li>ai_family:
54 *           The protocol family that should be used. When ai_family is set
55 *           to PF_UNSPEC, it means the caller will accept any protocol
56 *           family supported by the operating system.</li>
57 *
58 *    <li>ai_socktype:
59 *           denotes the type of socket -- SOCK_STREAM, SOCK_DGRAM or
60 *           SOCK_RAW -- that is wanted. When ai_socktype is zero the caller
61 *           will accept any socket type.</li>
62 *
63 *    <li>ai_protocol:
64 *           indicates which transport protocol is wanted: IPPROTO_UDP or
65 *           IPPROTO_TCP. If ai_protocol is zero the caller will accept any
66 *           protocol.</li>
67 *
68 *    <li>ai_flags:
69 *           Flag bits. If the AI_CANONNAME bit is set, a successful call to
70 *           getaddrinfo() will return a null-terminated string
71 *           containing the canonical name of the specified hostname in
72 *           ai_canonname of the first addrinfo structure returned. Setting
73 *           the AI_PASSIVE bit indicates that the returned socket address
74 *           structure is intended for used in a call to bind(2). In this
75 *           case, if the hostname argument is a NULL pointer, then the IP
76 *           address portion of the socket address structure will be set to
77 *           INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6
78 *           address.<br /><br />
79 *
80 *           When ai_flags does not set the AI_PASSIVE bit, the returned
81 *           socket address structure will be ready for use in a call to
82 *           connect(2) for a connection-oriented protocol or connect(2),
83 *           sendto(2), or sendmsg(2) if a connectionless protocol was
84 *           chosen. The IP address portion of the socket address structure
85 *           will be set to the loopback address if hostname is a NULL
86 *           pointer and AI_PASSIVE is not set in ai_flags.<br /><br />
87 *
88 *           If ai_flags is set to AI_NUMERICHOST it indicates that hostname
89 *           should be treated as a numeric string defining an IPv4 or IPv6
90 *           address and no name resolution should be attempted.
91 * </li></ul>
92 *
93 *    All other elements of the struct addrinfo passed via hints must be
94 *    zero.
95 *
96 *    A hints of NULL is treated as if the caller provided a struct addrinfo
97 *    initialized to zero with ai_familyset to PF_UNSPEC.
98 *
99 *    After a successful call to getaddrinfo(), *res is a pointer to a
100 *    linked list of one or more addrinfo structures. Each struct addrinfo
101 *    in this list cn be processed by following the ai_next pointer, until a
102 *    NULL pointer is encountered. The three members ai_family, ai_socktype,
103 *    and ai_protocol in each returned addrinfo structure contain the
104 *    corresponding arguments for a call to socket(2). For each addrinfo
105 *    structure in the list, the ai_addr member points to a filled-in socket
106 *    address structure of length ai_addrlen.
107 *
108 *    All of the information returned by getaddrinfo() is dynamically
109 *    allocated: the addrinfo structures, and the socket address structures
110 *    and canonical host name strings pointed to by the addrinfostructures.
111 *    Memory allocated for the dynamically allocated structures created by a
112 *    successful call to getaddrinfo() is released by freeaddrinfo().
113 *    ai is a pointer to a struct addrinfo created by a call to getaddrinfo().
114 *
115 * \section irsreturn RETURN VALUES
116 *
117 *    getaddrinfo() returns zero on success or one of the error codes
118 *    listed in gai_strerror() if an error occurs. If both hostname and
119 *    servname are NULL getaddrinfo() returns #EAI_NONAME.
120 *
121 * \section irssee SEE ALSO
122 *
123 *    getaddrinfo(), freeaddrinfo(),
124 *    gai_strerror(), RFC3493, getservbyname(3), connect(2),
125 *    sendto(2), sendmsg(2), socket(2).
126 */
127
128#include <config.h>
129
130#include <stdlib.h>
131#include <string.h>
132#include <errno.h>
133
134#include <isc/app.h>
135#include <isc/buffer.h>
136#include <isc/lib.h>
137#include <isc/mem.h>
138#include <isc/sockaddr.h>
139#include <isc/string.h>
140#include <isc/util.h>
141
142#include <dns/client.h>
143#include <dns/fixedname.h>
144#include <dns/name.h>
145#include <dns/rdata.h>
146#include <dns/rdataset.h>
147#include <dns/rdatastruct.h>
148#include <dns/rdatatype.h>
149#include <dns/result.h>
150
151#include <irs/context.h>
152#include <irs/netdb.h>
153#include <irs/resconf.h>
154
155#define SA(addr)	((struct sockaddr *)(addr))
156#define SIN(addr)	((struct sockaddr_in *)(addr))
157#define SIN6(addr)	((struct sockaddr_in6 *)(addr))
158#define SLOCAL(addr)	((struct sockaddr_un *)(addr))
159
160/*! \struct addrinfo
161 */
162static struct addrinfo
163	*ai_concat(struct addrinfo *ai1, struct addrinfo *ai2),
164	*ai_reverse(struct addrinfo *oai),
165	*ai_clone(struct addrinfo *oai, int family),
166	*ai_alloc(int family, int addrlen);
167#ifdef AF_LOCAL
168static int get_local(const char *name, int socktype, struct addrinfo **res);
169#endif
170
171static int
172resolve_name(int family, const char *hostname, int flags,
173	     struct addrinfo **aip, int socktype, int port);
174
175static int add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
176		    int socktype, int port);
177static int add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
178		    int socktype, int port);
179static void set_order(int, int (**)(const char *, int, struct addrinfo **,
180				    int, int));
181
182#define FOUND_IPV4	0x1
183#define FOUND_IPV6	0x2
184#define FOUND_MAX	2
185
186#define ISC_AI_MASK (AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST)
187/*%
188 * Get a list of IP addresses and port numbers for host hostname and
189 * service servname.
190 */
191int
192getaddrinfo(const char *hostname, const char *servname,
193	    const struct addrinfo *hints, struct addrinfo **res)
194{
195	struct servent *sp;
196	const char *proto;
197	int family, socktype, flags, protocol;
198	struct addrinfo *ai, *ai_list;
199	int err = 0;
200	int port, i;
201	int (*net_order[FOUND_MAX+1])(const char *, int, struct addrinfo **,
202				      int, int);
203
204	if (hostname == NULL && servname == NULL)
205		return (EAI_NONAME);
206
207	proto = NULL;
208	if (hints != NULL) {
209		if ((hints->ai_flags & ~(ISC_AI_MASK)) != 0)
210			return (EAI_BADFLAGS);
211		if (hints->ai_addrlen || hints->ai_canonname ||
212		    hints->ai_addr || hints->ai_next) {
213			errno = EINVAL;
214			return (EAI_SYSTEM);
215		}
216		family = hints->ai_family;
217		socktype = hints->ai_socktype;
218		protocol = hints->ai_protocol;
219		flags = hints->ai_flags;
220		switch (family) {
221		case AF_UNSPEC:
222			switch (hints->ai_socktype) {
223			case SOCK_STREAM:
224				proto = "tcp";
225				break;
226			case SOCK_DGRAM:
227				proto = "udp";
228				break;
229			}
230			break;
231		case AF_INET:
232		case AF_INET6:
233			switch (hints->ai_socktype) {
234			case 0:
235				break;
236			case SOCK_STREAM:
237				proto = "tcp";
238				break;
239			case SOCK_DGRAM:
240				proto = "udp";
241				break;
242			case SOCK_RAW:
243				break;
244			default:
245				return (EAI_SOCKTYPE);
246			}
247			break;
248#ifdef	AF_LOCAL
249		case AF_LOCAL:
250			switch (hints->ai_socktype) {
251			case 0:
252				break;
253			case SOCK_STREAM:
254				break;
255			case SOCK_DGRAM:
256				break;
257			default:
258				return (EAI_SOCKTYPE);
259			}
260			break;
261#endif
262		default:
263			return (EAI_FAMILY);
264		}
265	} else {
266		protocol = 0;
267		family = 0;
268		socktype = 0;
269		flags = 0;
270	}
271
272#ifdef	AF_LOCAL
273	/*!
274	 * First, deal with AF_LOCAL.  If the family was not set,
275	 * then assume AF_LOCAL if the first character of the
276	 * hostname/servname is '/'.
277	 */
278
279	if (hostname != NULL &&
280	    (family == AF_LOCAL || (family == 0 && *hostname == '/')))
281		return (get_local(hostname, socktype, res));
282
283	if (servname != NULL &&
284	    (family == AF_LOCAL || (family == 0 && *servname == '/')))
285		return (get_local(servname, socktype, res));
286#endif
287
288	/*
289	 * Ok, only AF_INET and AF_INET6 left.
290	 */
291	ai_list = NULL;
292
293	/*
294	 * First, look up the service name (port) if it was
295	 * requested.  If the socket type wasn't specified, then
296	 * try and figure it out.
297	 */
298	if (servname != NULL) {
299		char *e;
300
301		port = strtol(servname, &e, 10);
302		if (*e == '\0') {
303			if (socktype == 0)
304				return (EAI_SOCKTYPE);
305			if (port < 0 || port > 65535)
306				return (EAI_SERVICE);
307			port = htons((unsigned short) port);
308		} else {
309			sp = getservbyname(servname, proto);
310			if (sp == NULL)
311				return (EAI_SERVICE);
312			port = sp->s_port;
313			if (socktype == 0) {
314				if (strcmp(sp->s_proto, "tcp") == 0)
315					socktype = SOCK_STREAM;
316				else if (strcmp(sp->s_proto, "udp") == 0)
317					socktype = SOCK_DGRAM;
318			}
319		}
320	} else
321		port = 0;
322
323	/*
324	 * Next, deal with just a service name, and no hostname.
325	 * (we verified that one of them was non-null up above).
326	 */
327	if (hostname == NULL && (flags & AI_PASSIVE) != 0) {
328		if (family == AF_INET || family == 0) {
329			ai = ai_alloc(AF_INET, sizeof(struct sockaddr_in));
330			if (ai == NULL)
331				return (EAI_MEMORY);
332			ai->ai_socktype = socktype;
333			ai->ai_protocol = protocol;
334			SIN(ai->ai_addr)->sin_port = port;
335			ai->ai_next = ai_list;
336			ai_list = ai;
337		}
338
339		if (family == AF_INET6 || family == 0) {
340			ai = ai_alloc(AF_INET6, sizeof(struct sockaddr_in6));
341			if (ai == NULL) {
342				freeaddrinfo(ai_list);
343				return (EAI_MEMORY);
344			}
345			ai->ai_socktype = socktype;
346			ai->ai_protocol = protocol;
347			SIN6(ai->ai_addr)->sin6_port = port;
348			ai->ai_next = ai_list;
349			ai_list = ai;
350		}
351
352		*res = ai_list;
353		return (0);
354	}
355
356	/*
357	 * If the family isn't specified or AI_NUMERICHOST specified, check
358	 * first to see if it is a numeric address.
359	 * Though the gethostbyname2() routine will recognize numeric addresses,
360	 * it will only recognize the format that it is being called for.  Thus,
361	 * a numeric AF_INET address will be treated by the AF_INET6 call as
362	 * a domain name, and vice versa.  Checking for both numerics here
363	 * avoids that.
364	 */
365	if (hostname != NULL &&
366	    (family == 0 || (flags & AI_NUMERICHOST) != 0)) {
367		char abuf[sizeof(struct in6_addr)];
368		char nbuf[NI_MAXHOST];
369		int addrsize, addroff;
370#ifdef IRS_HAVE_SIN6_SCOPE_ID
371		char *p, *ep;
372		char ntmp[NI_MAXHOST];
373		isc_uint32_t scopeid;
374#endif
375
376#ifdef IRS_HAVE_SIN6_SCOPE_ID
377		/*
378		 * Scope identifier portion.
379		 */
380		ntmp[0] = '\0';
381		if (strchr(hostname, '%') != NULL) {
382			strncpy(ntmp, hostname, sizeof(ntmp) - 1);
383			ntmp[sizeof(ntmp) - 1] = '\0';
384			p = strchr(ntmp, '%');
385			ep = NULL;
386
387			/*
388			 * Vendors may want to support non-numeric
389			 * scopeid around here.
390			 */
391
392			if (p != NULL)
393				scopeid = (isc_uint32_t)strtoul(p + 1,
394								&ep, 10);
395			if (p != NULL && ep != NULL && ep[0] == '\0')
396				*p = '\0';
397			else {
398				ntmp[0] = '\0';
399				scopeid = 0;
400			}
401		} else
402			scopeid = 0;
403#endif
404
405		if (inet_pton(AF_INET, hostname, (struct in_addr *)abuf)
406		    == 1) {
407			if (family == AF_INET6) {
408				/*
409				 * Convert to a V4 mapped address.
410				 */
411				struct in6_addr *a6 = (struct in6_addr *)abuf;
412				memmove(&a6->s6_addr[12], &a6->s6_addr[0], 4);
413				memset(&a6->s6_addr[10], 0xff, 2);
414				memset(&a6->s6_addr[0], 0, 10);
415				goto inet6_addr;
416			}
417			addrsize = sizeof(struct in_addr);
418			addroff = (char *)(&SIN(0)->sin_addr) - (char *)0;
419			family = AF_INET;
420			goto common;
421#ifdef IRS_HAVE_SIN6_SCOPE_ID
422		} else if (ntmp[0] != '\0' &&
423			   inet_pton(AF_INET6, ntmp, abuf) == 1) {
424			if (family && family != AF_INET6)
425				return (EAI_NONAME);
426			addrsize = sizeof(struct in6_addr);
427			addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
428			family = AF_INET6;
429			goto common;
430#endif
431		} else if (inet_pton(AF_INET6, hostname, abuf) == 1) {
432			if (family != 0 && family != AF_INET6)
433				return (EAI_NONAME);
434		inet6_addr:
435			addrsize = sizeof(struct in6_addr);
436			addroff = (char *)(&SIN6(0)->sin6_addr) - (char *)0;
437			family = AF_INET6;
438
439		common:
440			ai = ai_alloc(family,
441				      ((family == AF_INET6) ?
442				       sizeof(struct sockaddr_in6) :
443				       sizeof(struct sockaddr_in)));
444			if (ai == NULL)
445				return (EAI_MEMORY);
446			ai_list = ai;
447			ai->ai_socktype = socktype;
448			SIN(ai->ai_addr)->sin_port = port;
449			memmove((char *)ai->ai_addr + addroff, abuf, addrsize);
450			if ((flags & AI_CANONNAME) != 0) {
451#ifdef IRS_HAVE_SIN6_SCOPE_ID
452				if (ai->ai_family == AF_INET6)
453					SIN6(ai->ai_addr)->sin6_scope_id =
454						scopeid;
455#endif
456				if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
457						nbuf, sizeof(nbuf), NULL, 0,
458						NI_NUMERICHOST) == 0) {
459					ai->ai_canonname = strdup(nbuf);
460					if (ai->ai_canonname == NULL) {
461						freeaddrinfo(ai);
462						return (EAI_MEMORY);
463					}
464				} else {
465					/* XXX raise error? */
466					ai->ai_canonname = NULL;
467				}
468			}
469			goto done;
470		} else if ((flags & AI_NUMERICHOST) != 0) {
471			return (EAI_NONAME);
472		}
473	}
474
475	if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
476		set_order(family, net_order);
477		for (i = 0; i < FOUND_MAX; i++) {
478			if (net_order[i] == NULL)
479				break;
480			err = (net_order[i])(hostname, flags, &ai_list,
481					     socktype, port);
482			if (err != 0) {
483				if (ai_list != NULL) {
484					freeaddrinfo(ai_list);
485					ai_list = NULL;
486				}
487				break;
488			}
489		}
490	} else
491		err = resolve_name(family, hostname, flags, &ai_list,
492				   socktype, port);
493
494	if (ai_list == NULL) {
495		if (err == 0)
496			err = EAI_NONAME;
497		return (err);
498	}
499
500done:
501	ai_list = ai_reverse(ai_list);
502
503	*res = ai_list;
504	return (0);
505}
506
507typedef struct gai_restrans {
508	dns_clientrestrans_t	*xid;
509	isc_boolean_t		is_inprogress;
510	int			error;
511	struct addrinfo		ai_sentinel;
512	struct gai_resstate	*resstate;
513} gai_restrans_t;
514
515typedef struct gai_resstate {
516	isc_mem_t			*mctx;
517	struct gai_statehead		*head;
518	dns_fixedname_t			fixedname;
519	dns_name_t			*qname;
520	gai_restrans_t			*trans4;
521	gai_restrans_t			*trans6;
522	ISC_LINK(struct gai_resstate)	link;
523} gai_resstate_t;
524
525typedef struct gai_statehead {
526	int				ai_family;
527	int				ai_flags;
528	int				ai_socktype;
529	int				ai_port;
530	isc_appctx_t			*actx;
531	dns_client_t			*dnsclient;
532	ISC_LIST(struct gai_resstate)	resstates;
533	unsigned int			activestates;
534} gai_statehead_t;
535
536static isc_result_t
537make_resstate(isc_mem_t *mctx, gai_statehead_t *head, const char *hostname,
538	      const char *domain, gai_resstate_t **statep)
539{
540	isc_result_t result;
541	gai_resstate_t *state;
542	dns_fixedname_t fixeddomain;
543	dns_name_t *qdomain;
544	size_t namelen;
545	isc_buffer_t b;
546	isc_boolean_t need_v4 = ISC_FALSE;
547	isc_boolean_t need_v6 = ISC_FALSE;
548
549	state = isc_mem_get(mctx, sizeof(*state));
550	if (state == NULL)
551		return (ISC_R_NOMEMORY);
552
553	/* Construct base domain name */
554	namelen = strlen(domain);
555	isc_buffer_constinit(&b, domain, namelen);
556	isc_buffer_add(&b, namelen);
557	dns_fixedname_init(&fixeddomain);
558	qdomain = dns_fixedname_name(&fixeddomain);
559	result = dns_name_fromtext(qdomain, &b, dns_rootname, 0, NULL);
560	if (result != ISC_R_SUCCESS) {
561		isc_mem_put(mctx, state, sizeof(*state));
562		return (result);
563	}
564
565	/* Construct query name */
566	namelen = strlen(hostname);
567	isc_buffer_constinit(&b, hostname, namelen);
568	isc_buffer_add(&b, namelen);
569	dns_fixedname_init(&state->fixedname);
570	state->qname = dns_fixedname_name(&state->fixedname);
571	result = dns_name_fromtext(state->qname, &b, qdomain, 0, NULL);
572	if (result != ISC_R_SUCCESS) {
573		isc_mem_put(mctx, state, sizeof(*state));
574		return (result);
575	}
576
577	if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET)
578		need_v4 = ISC_TRUE;
579	if (head->ai_family == AF_UNSPEC || head->ai_family == AF_INET6)
580		need_v6 = ISC_TRUE;
581
582	state->trans6 = NULL;
583	state->trans4 = NULL;
584	if (need_v4) {
585		state->trans4 = isc_mem_get(mctx, sizeof(gai_restrans_t));
586		if (state->trans4 == NULL) {
587			isc_mem_put(mctx, state, sizeof(*state));
588			return (ISC_R_NOMEMORY);
589		}
590		state->trans4->error = 0;
591		state->trans4->xid = NULL;
592		state->trans4->resstate = state;
593		state->trans4->is_inprogress = ISC_TRUE;
594		state->trans4->ai_sentinel.ai_next = NULL;
595	}
596	if (need_v6) {
597		state->trans6 = isc_mem_get(mctx, sizeof(gai_restrans_t));
598		if (state->trans6 == NULL) {
599			if (state->trans4 != NULL)
600				isc_mem_put(mctx, state->trans4,
601					    sizeof(*state->trans4));
602			isc_mem_put(mctx, state, sizeof(*state));
603			return (ISC_R_NOMEMORY);
604		}
605		state->trans6->error = 0;
606		state->trans6->xid = NULL;
607		state->trans6->resstate = state;
608		state->trans6->is_inprogress = ISC_TRUE;
609		state->trans6->ai_sentinel.ai_next = NULL;
610	}
611
612	state->mctx = mctx;
613	state->head = head;
614	ISC_LINK_INIT(state, link);
615
616	*statep = state;
617
618	return (ISC_R_SUCCESS);
619}
620
621static isc_result_t
622make_resstates(isc_mem_t *mctx, const char *hostname, gai_statehead_t *head,
623	       irs_resconf_t *resconf)
624{
625	isc_result_t result;
626	irs_resconf_searchlist_t *searchlist;
627	irs_resconf_search_t *searchent;
628	gai_resstate_t *resstate, *resstate0;
629
630	resstate0 = NULL;
631	result = make_resstate(mctx, head, hostname, ".", &resstate0);
632	if (result != ISC_R_SUCCESS)
633		return (result);
634
635	searchlist = irs_resconf_getsearchlist(resconf);
636	for (searchent = ISC_LIST_HEAD(*searchlist); searchent != NULL;
637	     searchent = ISC_LIST_NEXT(searchent, link)) {
638		resstate = NULL;
639		result = make_resstate(mctx, head, hostname,
640				       (const char *)searchent->domain,
641				       &resstate);
642		if (result != ISC_R_SUCCESS)
643			break;
644
645		ISC_LIST_APPEND(head->resstates, resstate, link);
646		head->activestates++;
647	}
648
649	/*
650	 * Insert the original hostname either at the head or the tail of the
651	 * state list, depending on the number of labels contained in the
652	 * original name and the 'ndots' configuration parameter.
653	 */
654	if (dns_name_countlabels(resstate0->qname) >
655	    irs_resconf_getndots(resconf) + 1) {
656		ISC_LIST_PREPEND(head->resstates, resstate0, link);
657	} else
658		ISC_LIST_APPEND(head->resstates, resstate0, link);
659	head->activestates++;
660
661	if (result != ISC_R_SUCCESS) {
662		while ((resstate = ISC_LIST_HEAD(head->resstates)) != NULL) {
663			ISC_LIST_UNLINK(head->resstates, resstate, link);
664			if (resstate->trans4 != NULL) {
665				isc_mem_put(mctx, resstate->trans4,
666					    sizeof(*resstate->trans4));
667			}
668			if (resstate->trans6 != NULL) {
669				isc_mem_put(mctx, resstate->trans6,
670					    sizeof(*resstate->trans6));
671			}
672
673			isc_mem_put(mctx, resstate, sizeof(*resstate));
674		}
675	}
676
677	return (result);
678}
679
680static void
681process_answer(isc_task_t *task, isc_event_t *event) {
682	int error = 0, family;
683	gai_restrans_t *trans = event->ev_arg;
684	gai_resstate_t *resstate;
685	dns_clientresevent_t *rev = (dns_clientresevent_t *)event;
686	dns_rdatatype_t qtype;
687	dns_name_t *name;
688
689	REQUIRE(trans != NULL);
690	resstate = trans->resstate;
691	REQUIRE(resstate != NULL);
692	REQUIRE(task != NULL);
693
694	if (trans == resstate->trans4) {
695		family = AF_INET;
696		qtype = dns_rdatatype_a;
697	} else {
698		INSIST(trans == resstate->trans6);
699		family = AF_INET6;
700		qtype = dns_rdatatype_aaaa;
701	}
702
703	INSIST(trans->is_inprogress);
704	trans->is_inprogress = ISC_FALSE;
705
706	switch (rev->result) {
707	case ISC_R_SUCCESS:
708	case DNS_R_NCACHENXDOMAIN: /* treat this as a fatal error? */
709	case DNS_R_NCACHENXRRSET:
710		break;
711	default:
712		switch (rev->vresult) {
713		case DNS_R_SIGINVALID:
714		case DNS_R_SIGEXPIRED:
715		case DNS_R_SIGFUTURE:
716		case DNS_R_KEYUNAUTHORIZED:
717		case DNS_R_MUSTBESECURE:
718		case DNS_R_COVERINGNSEC:
719		case DNS_R_NOTAUTHORITATIVE:
720		case DNS_R_NOVALIDKEY:
721		case DNS_R_NOVALIDDS:
722		case DNS_R_NOVALIDSIG:
723			error = EAI_INSECUREDATA;
724			break;
725		default:
726			error = EAI_FAIL;
727		}
728		goto done;
729	}
730
731	/* Parse the response and construct the addrinfo chain */
732	for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL;
733	     name = ISC_LIST_NEXT(name, link)) {
734		isc_result_t result;
735		dns_rdataset_t *rdataset;
736		isc_buffer_t b;
737		isc_region_t r;
738		char t[1024];
739
740		for (rdataset = ISC_LIST_HEAD(name->list);
741		     rdataset != NULL;
742		     rdataset = ISC_LIST_NEXT(rdataset, link)) {
743			if (!dns_rdataset_isassociated(rdataset))
744				continue;
745			if (rdataset->type != qtype)
746				continue;
747
748			if ((resstate->head->ai_flags & AI_CANONNAME) != 0) {
749				isc_buffer_init(&b, t, sizeof(t));
750				result = dns_name_totext(name, ISC_TRUE, &b);
751				if (result != ISC_R_SUCCESS) {
752					error = EAI_FAIL;
753					goto done;
754				}
755				isc_buffer_putuint8(&b, '\0');
756				isc_buffer_usedregion(&b, &r);
757			}
758
759			for (result = dns_rdataset_first(rdataset);
760			     result == ISC_R_SUCCESS;
761			     result = dns_rdataset_next(rdataset)) {
762				struct addrinfo *ai;
763				dns_rdata_t rdata;
764				dns_rdata_in_a_t rdata_a;
765				dns_rdata_in_aaaa_t rdata_aaaa;
766
767				ai = ai_alloc(family,
768					      ((family == AF_INET6) ?
769					       sizeof(struct sockaddr_in6) :
770					       sizeof(struct sockaddr_in)));
771				if (ai == NULL) {
772					error = EAI_MEMORY;
773					goto done;
774				}
775				ai->ai_socktype = resstate->head->ai_socktype;
776				ai->ai_next = trans->ai_sentinel.ai_next;
777				trans->ai_sentinel.ai_next = ai;
778
779				/*
780				 * Set AF-specific parameters
781				 * (IPv4/v6 address/port)
782				 */
783				dns_rdata_init(&rdata);
784				switch (family) {
785				case AF_INET:
786					dns_rdataset_current(rdataset, &rdata);
787					result = dns_rdata_tostruct(&rdata, &rdata_a,
788								    NULL);
789					RUNTIME_CHECK(result == ISC_R_SUCCESS);
790					SIN(ai->ai_addr)->sin_port =
791						resstate->head->ai_port;
792					memmove(&SIN(ai->ai_addr)->sin_addr,
793						&rdata_a.in_addr, 4);
794					dns_rdata_freestruct(&rdata_a);
795					break;
796				case AF_INET6:
797					dns_rdataset_current(rdataset, &rdata);
798					result = dns_rdata_tostruct(&rdata, &rdata_aaaa,
799								    NULL);
800					RUNTIME_CHECK(result == ISC_R_SUCCESS);
801					SIN6(ai->ai_addr)->sin6_port =
802						resstate->head->ai_port;
803					memmove(&SIN6(ai->ai_addr)->sin6_addr,
804						&rdata_aaaa.in6_addr, 16);
805					dns_rdata_freestruct(&rdata_aaaa);
806					break;
807				}
808
809				if ((resstate->head->ai_flags & AI_CANONNAME)
810				    != 0) {
811					ai->ai_canonname =
812						strdup((const char *)r.base);
813					if (ai->ai_canonname == NULL) {
814						error = EAI_MEMORY;
815						goto done;
816					}
817				}
818			}
819		}
820	}
821
822 done:
823	dns_client_freeresanswer(resstate->head->dnsclient, &rev->answerlist);
824	dns_client_destroyrestrans(&trans->xid);
825
826	isc_event_free(&event);
827
828	/* Make sure that error == 0 iff we have a non-empty list */
829	if (error == 0) {
830		if (trans->ai_sentinel.ai_next == NULL)
831			error = EAI_NONAME;
832	} else {
833		if (trans->ai_sentinel.ai_next != NULL) {
834			freeaddrinfo(trans->ai_sentinel.ai_next);
835			trans->ai_sentinel.ai_next = NULL;
836		}
837	}
838	trans->error = error;
839
840	/* Check whether we are done */
841	if ((resstate->trans4 == NULL || !resstate->trans4->is_inprogress) &&
842	    (resstate->trans6 == NULL || !resstate->trans6->is_inprogress)) {
843		/*
844		 * We're done for this state.  If there is no other outstanding
845		 * state, we can exit.
846		 */
847		resstate->head->activestates--;
848		if (resstate->head->activestates == 0) {
849			isc_app_ctxsuspend(resstate->head->actx);
850			return;
851		}
852
853		/*
854		 * There are outstanding states, but if we are at the head
855		 * of the state list (i.e., at the highest search priority)
856		 * and have any answer, we can stop now by canceling the
857		 * others.
858		 */
859		if (resstate == ISC_LIST_HEAD(resstate->head->resstates)) {
860			if ((resstate->trans4 != NULL &&
861			     resstate->trans4->ai_sentinel.ai_next != NULL) ||
862			    (resstate->trans6 != NULL &&
863			     resstate->trans6->ai_sentinel.ai_next != NULL)) {
864				gai_resstate_t *rest;
865
866				for (rest = ISC_LIST_NEXT(resstate, link);
867				     rest != NULL;
868				     rest = ISC_LIST_NEXT(rest, link)) {
869					if (rest->trans4 != NULL &&
870					    rest->trans4->xid != NULL)
871						dns_client_cancelresolve(
872							rest->trans4->xid);
873					if (rest->trans6 != NULL &&
874					    rest->trans6->xid != NULL)
875						dns_client_cancelresolve(
876							rest->trans6->xid);
877				}
878			} else {
879				/*
880				 * This search fails, so we move to the tail
881				 * of the list so that the next entry will
882				 * have the highest priority.
883				 */
884				ISC_LIST_UNLINK(resstate->head->resstates,
885						resstate, link);
886				ISC_LIST_APPEND(resstate->head->resstates,
887						resstate, link);
888			}
889		}
890	}
891}
892
893static int
894resolve_name(int family, const char *hostname, int flags,
895	     struct addrinfo **aip, int socktype, int port)
896{
897	isc_result_t result;
898	irs_context_t *irsctx;
899	irs_resconf_t *conf;
900	isc_mem_t *mctx;
901	isc_appctx_t *actx;
902	isc_task_t *task;
903	int terror = 0;
904	int error = 0;
905	dns_client_t *client;
906	gai_resstate_t *resstate;
907	gai_statehead_t head;
908	isc_boolean_t all_fail = ISC_TRUE;
909
910	/* get IRS context and the associated parameters */
911	irsctx = NULL;
912	result = irs_context_get(&irsctx);
913	if (result != ISC_R_SUCCESS)
914		return (EAI_FAIL);
915	actx = irs_context_getappctx(irsctx);
916
917	mctx = irs_context_getmctx(irsctx);
918	task = irs_context_gettask(irsctx);
919	conf = irs_context_getresconf(irsctx);
920	client = irs_context_getdnsclient(irsctx);
921
922	/* construct resolution states */
923	head.activestates = 0;
924	head.ai_family = family;
925	head.ai_socktype = socktype;
926	head.ai_flags = flags;
927	head.ai_port = port;
928	head.actx = actx;
929	head.dnsclient = client;
930	ISC_LIST_INIT(head.resstates);
931	result = make_resstates(mctx, hostname, &head, conf);
932	if (result != ISC_R_SUCCESS)
933		return (EAI_FAIL);
934
935	for (resstate = ISC_LIST_HEAD(head.resstates);
936	     resstate != NULL; resstate = ISC_LIST_NEXT(resstate, link)) {
937		if (resstate->trans4 != NULL) {
938			result = dns_client_startresolve(client,
939							 resstate->qname,
940							 dns_rdataclass_in,
941							 dns_rdatatype_a,
942							 0, task,
943							 process_answer,
944							 resstate->trans4,
945							 &resstate->trans4->xid);
946			if (result == ISC_R_SUCCESS) {
947				resstate->trans4->is_inprogress = ISC_TRUE;
948				all_fail = ISC_FALSE;
949			} else
950				resstate->trans4->is_inprogress = ISC_FALSE;
951		}
952		if (resstate->trans6 != NULL) {
953			result = dns_client_startresolve(client,
954							 resstate->qname,
955							 dns_rdataclass_in,
956							 dns_rdatatype_aaaa,
957							 0, task,
958							 process_answer,
959							 resstate->trans6,
960							 &resstate->trans6->xid);
961			if (result == ISC_R_SUCCESS) {
962				resstate->trans6->is_inprogress = ISC_TRUE;
963				all_fail = ISC_FALSE;
964			} else
965				resstate->trans6->is_inprogress= ISC_FALSE;
966		}
967	}
968	if (!all_fail) {
969		/* Start all the events */
970		isc_app_ctxrun(actx);
971	} else
972		error = EAI_FAIL;
973
974	/* Cleanup */
975	while ((resstate = ISC_LIST_HEAD(head.resstates)) != NULL) {
976		int terror4 = 0, terror6 = 0;
977
978		ISC_LIST_UNLINK(head.resstates, resstate, link);
979
980		if (*aip == NULL) {
981			struct addrinfo *sentinel4 = NULL;
982			struct addrinfo *sentinel6 = NULL;
983
984			if (resstate->trans4 != NULL) {
985				sentinel4 =
986					resstate->trans4->ai_sentinel.ai_next;
987				resstate->trans4->ai_sentinel.ai_next = NULL;
988			}
989			if (resstate->trans6 != NULL) {
990				sentinel6 =
991					resstate->trans6->ai_sentinel.ai_next;
992				resstate->trans6->ai_sentinel.ai_next = NULL;
993			}
994			*aip = ai_concat(sentinel4, sentinel6);
995		}
996
997		if (resstate->trans4 != NULL) {
998			INSIST(resstate->trans4->xid == NULL);
999			terror4 = resstate->trans4->error;
1000			isc_mem_put(mctx, resstate->trans4,
1001				    sizeof(*resstate->trans4));
1002		}
1003		if (resstate->trans6 != NULL) {
1004			INSIST(resstate->trans6->xid == NULL);
1005			terror6 = resstate->trans6->error;
1006			isc_mem_put(mctx, resstate->trans6,
1007				    sizeof(*resstate->trans6));
1008		}
1009
1010		/*
1011		 * If the entire lookup fails, we need to choose an appropriate
1012		 * error code from individual codes.  We'll try to provide as
1013		 * specific a code as possible.  In general, we are going to
1014		 * find an error code other than EAI_NONAME (which is too
1015		 * generic and may actually not be problematic in some cases).
1016		 * EAI_NONAME will be set below if no better code is found.
1017		 */
1018		if (terror == 0 || terror == EAI_NONAME) {
1019			if (terror4 != 0 && terror4 != EAI_NONAME)
1020				terror = terror4;
1021			else if (terror6 != 0 && terror6 != EAI_NONAME)
1022				terror = terror6;
1023		}
1024
1025		isc_mem_put(mctx, resstate, sizeof(*resstate));
1026	}
1027
1028	if (*aip == NULL) {
1029		error = terror;
1030		if (error == 0)
1031			error = EAI_NONAME;
1032	}
1033
1034#if 1	/*  XXX: enabled for finding leaks.  should be cleaned up later. */
1035	isc_app_ctxfinish(actx);
1036	irs_context_destroy(&irsctx);
1037#endif
1038
1039	return (error);
1040}
1041
1042static char *
1043irs_strsep(char **stringp, const char *delim) {
1044	char *string = *stringp;
1045	char *s;
1046	const char *d;
1047	char sc, dc;
1048
1049	if (string == NULL)
1050		return (NULL);
1051
1052	for (s = string; *s != '\0'; s++) {
1053		sc = *s;
1054		for (d = delim; (dc = *d) != '\0'; d++)
1055			if (sc == dc) {
1056				*s++ = '\0';
1057				*stringp = s;
1058				return (string);
1059			}
1060	}
1061	*stringp = NULL;
1062	return (string);
1063}
1064
1065static void
1066set_order(int family, int (**net_order)(const char *, int, struct addrinfo **,
1067					int, int))
1068{
1069	char *order, *tok;
1070	int found;
1071
1072	if (family) {
1073		switch (family) {
1074		case AF_INET:
1075			*net_order++ = add_ipv4;
1076			break;
1077		case AF_INET6:
1078			*net_order++ = add_ipv6;
1079			break;
1080		}
1081	} else {
1082		order = getenv("NET_ORDER");
1083		found = 0;
1084		while (order != NULL) {
1085			/*
1086			 * We ignore any unknown names.
1087			 */
1088			tok = irs_strsep(&order, ":");
1089			if (strcasecmp(tok, "inet6") == 0) {
1090				if ((found & FOUND_IPV6) == 0)
1091					*net_order++ = add_ipv6;
1092				found |= FOUND_IPV6;
1093			} else if (strcasecmp(tok, "inet") == 0 ||
1094			    strcasecmp(tok, "inet4") == 0) {
1095				if ((found & FOUND_IPV4) == 0)
1096					*net_order++ = add_ipv4;
1097				found |= FOUND_IPV4;
1098			}
1099		}
1100
1101		/*
1102		 * Add in anything that we didn't find.
1103		 */
1104		if ((found & FOUND_IPV4) == 0)
1105			*net_order++ = add_ipv4;
1106		if ((found & FOUND_IPV6) == 0)
1107			*net_order++ = add_ipv6;
1108	}
1109	*net_order = NULL;
1110	return;
1111}
1112
1113static char v4_loop[4] = { 127, 0, 0, 1 };
1114
1115static int
1116add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
1117	 int socktype, int port)
1118{
1119	struct addrinfo *ai;
1120
1121	UNUSED(hostname);
1122	UNUSED(flags);
1123
1124	ai = ai_clone(*aip, AF_INET); /* don't use ai_clone() */
1125	if (ai == NULL) {
1126		freeaddrinfo(*aip);
1127		return (EAI_MEMORY);
1128	}
1129
1130	*aip = ai;
1131	ai->ai_socktype = socktype;
1132	SIN(ai->ai_addr)->sin_port = port;
1133	memmove(&SIN(ai->ai_addr)->sin_addr, v4_loop, 4);
1134
1135	return (0);
1136}
1137
1138static char v6_loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
1139
1140static int
1141add_ipv6(const char *hostname, int flags, struct addrinfo **aip,
1142	 int socktype, int port)
1143{
1144	struct addrinfo *ai;
1145
1146	UNUSED(hostname);
1147	UNUSED(flags);
1148
1149	ai = ai_clone(*aip, AF_INET6); /* don't use ai_clone() */
1150	if (ai == NULL)
1151		return (EAI_MEMORY);
1152
1153	*aip = ai;
1154	ai->ai_socktype = socktype;
1155	SIN6(ai->ai_addr)->sin6_port = port;
1156	memmove(&SIN6(ai->ai_addr)->sin6_addr, v6_loop, 16);
1157
1158	return (0);
1159}
1160
1161/*% Free address info. */
1162void
1163freeaddrinfo(struct addrinfo *ai) {
1164	struct addrinfo *ai_next;
1165
1166	while (ai != NULL) {
1167		ai_next = ai->ai_next;
1168		if (ai->ai_addr != NULL)
1169			free(ai->ai_addr);
1170		if (ai->ai_canonname)
1171			free(ai->ai_canonname);
1172		free(ai);
1173		ai = ai_next;
1174	}
1175}
1176
1177#ifdef AF_LOCAL
1178static int
1179get_local(const char *name, int socktype, struct addrinfo **res) {
1180	struct addrinfo *ai;
1181	struct sockaddr_un *slocal;
1182
1183	if (socktype == 0)
1184		return (EAI_SOCKTYPE);
1185
1186	ai = ai_alloc(AF_LOCAL, sizeof(*slocal));
1187	if (ai == NULL)
1188		return (EAI_MEMORY);
1189
1190	slocal = SLOCAL(ai->ai_addr);
1191	strlcpy(slocal->sun_path, name, sizeof(slocal->sun_path));
1192
1193	ai->ai_socktype = socktype;
1194	/*
1195	 * ai->ai_flags, ai->ai_protocol, ai->ai_canonname,
1196	 * and ai->ai_next were initialized to zero.
1197	 */
1198
1199	*res = ai;
1200	return (0);
1201}
1202#endif
1203
1204/*!
1205 * Allocate an addrinfo structure, and a sockaddr structure
1206 * of the specificed length.  We initialize:
1207 *	ai_addrlen
1208 *	ai_family
1209 *	ai_addr
1210 *	ai_addr->sa_family
1211 *	ai_addr->sa_len	(IRS_PLATFORM_HAVESALEN)
1212 * and everything else is initialized to zero.
1213 */
1214static struct addrinfo *
1215ai_alloc(int family, int addrlen) {
1216	struct addrinfo *ai;
1217
1218	ai = (struct addrinfo *)calloc(1, sizeof(*ai));
1219	if (ai == NULL)
1220		return (NULL);
1221
1222	ai->ai_addr = SA(calloc(1, addrlen));
1223	if (ai->ai_addr == NULL) {
1224		free(ai);
1225		return (NULL);
1226	}
1227	ai->ai_addrlen = addrlen;
1228	ai->ai_family = family;
1229	ai->ai_addr->sa_family = family;
1230#ifdef IRS_PLATFORM_HAVESALEN
1231	ai->ai_addr->sa_len = addrlen;
1232#endif
1233	return (ai);
1234}
1235
1236static struct addrinfo *
1237ai_clone(struct addrinfo *oai, int family) {
1238	struct addrinfo *ai;
1239
1240	ai = ai_alloc(family, ((family == AF_INET6) ?
1241	    sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)));
1242
1243	if (ai == NULL) {
1244		if (oai != NULL)
1245			freeaddrinfo(oai);
1246		return (NULL);
1247	}
1248	if (oai == NULL)
1249		return (ai);
1250
1251	ai->ai_flags = oai->ai_flags;
1252	ai->ai_socktype = oai->ai_socktype;
1253	ai->ai_protocol = oai->ai_protocol;
1254	ai->ai_canonname = NULL;
1255	ai->ai_next = oai;
1256	return (ai);
1257}
1258
1259static struct addrinfo *
1260ai_reverse(struct addrinfo *oai) {
1261	struct addrinfo *nai, *tai;
1262
1263	nai = NULL;
1264
1265	while (oai != NULL) {
1266		/*
1267		 * Grab one off the old list.
1268		 */
1269		tai = oai;
1270		oai = oai->ai_next;
1271		/*
1272		 * Put it on the front of the new list.
1273		 */
1274		tai->ai_next = nai;
1275		nai = tai;
1276	}
1277	return (nai);
1278}
1279
1280
1281static struct addrinfo *
1282ai_concat(struct addrinfo *ai1, struct addrinfo *ai2) {
1283	struct addrinfo *ai_tmp;
1284
1285	if (ai1 == NULL)
1286		return (ai2);
1287	else if (ai2 == NULL)
1288		return (ai1);
1289
1290	for (ai_tmp = ai1; ai_tmp != NULL && ai_tmp->ai_next != NULL;
1291	     ai_tmp = ai_tmp->ai_next)
1292		;
1293
1294	ai_tmp->ai_next = ai2;
1295
1296	return (ai1);
1297}
1298