getaddrinfo.c revision 57107
1155324Simp/*
2155324Simp * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3155324Simp * All rights reserved.
4155324Simp *
5155324Simp * Redistribution and use in source and binary forms, with or without
6155324Simp * modification, are permitted provided that the following conditions
7155324Simp * are met:
8155324Simp * 1. Redistributions of source code must retain the above copyright
9155324Simp *    notice, this list of conditions and the following disclaimer.
10155324Simp * 2. Redistributions in binary form must reproduce the above copyright
11155324Simp *    notice, this list of conditions and the following disclaimer in the
12155324Simp *    documentation and/or other materials provided with the distribution.
13155324Simp * 3. Neither the name of the project nor the names of its contributors
14155324Simp *    may be used to endorse or promote products derived from this software
15155324Simp *    without specific prior written permission.
16155324Simp *
17155324Simp * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18155324Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19155324Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20155324Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21155324Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22155324Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23155324Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24155324Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25155324Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26155324Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27155324Simp * SUCH DAMAGE.
28155324Simp *
29155324Simp * $FreeBSD: head/lib/libc/net/getaddrinfo.c 57107 2000-02-10 02:59:50Z shin $
30155324Simp */
31155324Simp
32155324Simp/*
33155324Simp * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
34155324Simp *
35155324Simp * Issues to be discussed:
36155324Simp * - Thread safe-ness must be checked.
37155324Simp * - Return values.  There are nonstandard return values defined and used
38155324Simp *   in the source code.  This is because RFC2553 is silent about which error
39155324Simp *   code must be returned for which situation.
40155324Simp * Note:
41155324Simp * - We use getipnodebyname() just for thread-safeness.  There's no intent
42155324Simp *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
43155324Simp *   getipnodebyname().
44155324Simp * - The code filters out AFs that are not supported by the kernel,
45155324Simp *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
46155324Simp *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
47155324Simp *   in ai_flags?
48155324Simp */
49155324Simp
50155324Simp#include <sys/types.h>
51155324Simp#include <sys/param.h>
52155324Simp#include <sys/socket.h>
53155324Simp#include <net/if.h>
54155324Simp#include <netinet/in.h>
55155324Simp#include <arpa/inet.h>
56155324Simp#include <arpa/nameser.h>
57155324Simp#include <netdb.h>
58155324Simp#include <resolv.h>
59155324Simp#include <string.h>
60155324Simp#include <stdlib.h>
61155324Simp#include <stddef.h>
62155324Simp#include <ctype.h>
63155324Simp#include <unistd.h>
64155324Simp#include <stdio.h>
65155324Simp
66155324Simp#if defined(__KAME__) && defined(INET6)
67155324Simp# define FAITH
68155324Simp#endif
69155324Simp
70155324Simp#define	SUCCESS 0
71155324Simp#define	ANY 0
72155324Simp#define	YES 1
73155324Simp#define	NO  0
74155324Simp
75155324Simpstatic const char in_addrany[] = { 0, 0, 0, 0 };
76155324Simpstatic const char in6_addrany[] = {
77155324Simp	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
78155324Simp};
79155324Simpstatic const char in_loopback[] = { 127, 0, 0, 1 };
80155324Simpstatic const char in6_loopback[] = {
81155324Simp	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
82155324Simp};
83155324Simp
84155324Simpstatic const struct afd {
85155324Simp	int a_af;
86155324Simp	int a_addrlen;
87155324Simp	int a_socklen;
88155324Simp	int a_off;
89155324Simp	const char *a_addrany;
90155324Simp	const char *a_loopback;
91155324Simp	int a_scoped;
92155324Simp} afdl [] = {
93155324Simp#ifdef INET6
94155324Simp#define	N_INET6 0
95155324Simp	{PF_INET6, sizeof(struct in6_addr),
96155324Simp	 sizeof(struct sockaddr_in6),
97155324Simp	 offsetof(struct sockaddr_in6, sin6_addr),
98155324Simp	 in6_addrany, in6_loopback, 1},
99159556Scognet#define	N_INET 1
100155324Simp#else
101155324Simp#define	N_INET 0
102155324Simp#endif
103155324Simp	{PF_INET, sizeof(struct in_addr),
104155324Simp	 sizeof(struct sockaddr_in),
105155324Simp	 offsetof(struct sockaddr_in, sin_addr),
106155324Simp	 in_addrany, in_loopback, 0},
107155324Simp	{0, 0, 0, 0, NULL, NULL, 0},
108155324Simp};
109155324Simp
110155324Simpstruct explore {
111155324Simp	int e_af;
112155324Simp	int e_socktype;
113155324Simp	int e_protocol;
114155324Simp	const char *e_protostr;
115155324Simp	int e_wild;
116155324Simp#define	WILD_AF(ex)		((ex)->e_wild & 0x01)
117155324Simp#define	WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
118155324Simp#define	WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
119155324Simp};
120155324Simp
121155324Simpstatic const struct explore explore[] = {
122155324Simp#ifdef INET6
123155324Simp	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
124155324Simp	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
125155324Simp	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
126155324Simp#endif
127155324Simp	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
128155324Simp	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
129155324Simp	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
130155324Simp	{ -1, 0, 0, NULL, 0 },
131155324Simp};
132155324Simp
133155324Simp#ifdef INET6
134155324Simp#define	PTON_MAX	16
135155324Simp#else
136155324Simp#define	PTON_MAX	4
137155324Simp#endif
138155324Simp
139155324Simp
140155324Simpstatic int str_isnumber __P((const char *));
141155324Simpstatic int explore_fqdn __P((const struct addrinfo *, const char *,
142155324Simp	const char *, struct addrinfo **));
143155324Simpstatic int explore_null __P((const struct addrinfo *, const char *,
144155324Simp	const char *, struct addrinfo **));
145155324Simpstatic int explore_numeric __P((const struct addrinfo *, const char *,
146155324Simp	const char *, struct addrinfo **));
147156832Simpstatic int explore_numeric_scope __P((const struct addrinfo *, const char *,
148156832Simp	const char *, struct addrinfo **));
149156832Simpstatic int get_canonname __P((const struct addrinfo *,
150156832Simp	struct addrinfo *, const char *));
151156832Simpstatic struct addrinfo *get_ai __P((const struct addrinfo *,
152156832Simp	const struct afd *, const char *));
153156832Simpstatic int get_portmatch __P((const struct addrinfo *, const char *));
154156832Simpstatic int get_port __P((struct addrinfo *, const char *, int));
155156832Simpstatic const struct afd *find_afd __P((int));
156156832Simp
157156832Simpstatic char *ai_errlist[] = {
158156832Simp	"Success",
159160282Scognet	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
160156832Simp	"Temporary failure in name resolution",		/* EAI_AGAIN      */
161156832Simp	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
162156832Simp	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
163156832Simp	"ai_family not supported",			/* EAI_FAMILY     */
164156832Simp	"Memory allocation failure", 			/* EAI_MEMORY     */
165156832Simp	"No address associated with hostname", 		/* EAI_NODATA     */
166156832Simp	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
167156832Simp	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
168156832Simp	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
169156832Simp	"System error returned in errno", 		/* EAI_SYSTEM     */
170156832Simp	"Invalid value for hints",			/* EAI_BADHINTS	  */
171160282Scognet	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
172156832Simp	"Argument res is NULL",				/* EAI_RESNULL	  */
173156832Simp	"Unknown error", 				/* EAI_MAX        */
174156832Simp};
175156832Simp
176156832Simp/* XXX macros that make external reference is BAD. */
177156832Simp
178156832Simp#define	GET_AI(ai, afd, addr) \
179155324Simpdo { \
180155324Simp	/* external reference: pai, error, and label free */ \
181155324Simp	(ai) = get_ai(pai, (afd), (addr)); \
182155324Simp	if ((ai) == NULL) { \
183155324Simp		error = EAI_MEMORY; \
184155324Simp		goto free; \
185155324Simp	} \
186155324Simp} while (0)
187159814Simp
188159795Simp#define	GET_PORT(ai, serv) \
189159795Simpdo { \
190159795Simp	/* external reference: error and label free */ \
191159795Simp	error = get_port((ai), (serv), 0); \
192159795Simp	if (error != 0) \
193159795Simp		goto free; \
194159795Simp} while (0)
195159795Simp
196159795Simp#define	GET_CANONNAME(ai, str) \
197159795Simpdo { \
198159795Simp	/* external reference: pai, error and label free */ \
199159795Simp	error = get_canonname(pai, (ai), (str)); \
200159814Simp	if (error != 0) \
201159795Simp		goto free; \
202159795Simp} while (0)
203155324Simp
204155324Simp#define	ERR(err) \
205155324Simpdo { \
206155324Simp	/* external reference: error, and label bad */ \
207155324Simp	error = (err); \
208155324Simp	goto bad; \
209155324Simp} while (0)
210155324Simp
211155324Simp#define	MATCH_FAMILY(x, y, w) \
212155324Simp	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
213159795Simp#define	MATCH(x, y, w) \
214157024Scognet	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
215157024Scognet
216157024Scognetchar *
217157024Scognetgai_strerror(ecode)
218155324Simp	int ecode;
219155324Simp{
220155324Simp	if (ecode < 0 || ecode > EAI_MAX)
221155324Simp		ecode = EAI_MAX;
222155324Simp	return ai_errlist[ecode];
223155324Simp}
224155324Simp
225155324Simpvoid
226155324Simpfreeaddrinfo(ai)
227155324Simp	struct addrinfo *ai;
228155324Simp{
229155324Simp	struct addrinfo *next;
230155324Simp
231155324Simp	do {
232155324Simp		next = ai->ai_next;
233155324Simp		if (ai->ai_canonname)
234155324Simp			free(ai->ai_canonname);
235155324Simp		/* no need to free(ai->ai_addr) */
236155324Simp		free(ai);
237157024Scognet	} while ((ai = next) != NULL);
238157024Scognet}
239157024Scognet
240157024Scognetstatic int
241157024Scognetstr_isnumber(p)
242157024Scognet	const char *p;
243157024Scognet{
244157024Scognet	char *q = (char *)p;
245157024Scognet	while (*q) {
246157024Scognet		if (! isdigit(*q))
247157024Scognet			return NO;
248157024Scognet		q++;
249157024Scognet	}
250157024Scognet	return YES;
251157024Scognet}
252157024Scognet
253157024Scognetint
254155324Simpgetaddrinfo(hostname, servname, hints, res)
255155324Simp	const char *hostname, *servname;
256155324Simp	const struct addrinfo *hints;
257155324Simp	struct addrinfo **res;
258155324Simp{
259155324Simp	struct addrinfo sentinel;
260155324Simp	struct addrinfo *cur;
261155324Simp	int error = 0;
262155324Simp	struct addrinfo ai;
263157024Scognet	struct addrinfo ai0;
264155324Simp	struct addrinfo *pai;
265155324Simp	const struct afd *afd;
266155324Simp	const struct explore *ex;
267155324Simp
268155324Simp	sentinel.ai_next = NULL;
269155324Simp	cur = &sentinel;
270155324Simp	pai = &ai;
271155324Simp	pai->ai_flags = 0;
272155324Simp	pai->ai_family = PF_UNSPEC;
273155324Simp	pai->ai_socktype = ANY;
274155324Simp	pai->ai_protocol = ANY;
275155324Simp	pai->ai_addrlen = 0;
276155324Simp	pai->ai_canonname = NULL;
277155324Simp	pai->ai_addr = NULL;
278155324Simp	pai->ai_next = NULL;
279155324Simp
280155324Simp	if (hostname == NULL && servname == NULL)
281155324Simp		return EAI_NONAME;
282155324Simp	if (res == NULL)
283155324Simp		return EAI_RESNULL; /* xxx */
284155324Simp	if (hints) {
285155324Simp		/* error check for hints */
286155324Simp		if (hints->ai_addrlen || hints->ai_canonname ||
287155324Simp		    hints->ai_addr || hints->ai_next)
288155324Simp			ERR(EAI_BADHINTS); /* xxx */
289155324Simp		if (hints->ai_flags & ~AI_MASK)
290155324Simp			ERR(EAI_BADFLAGS);
291155324Simp		switch (hints->ai_family) {
292155324Simp		case PF_UNSPEC:
293155324Simp		case PF_INET:
294155324Simp#ifdef INET6
295155324Simp		case PF_INET6:
296155324Simp#endif
297155324Simp			break;
298155324Simp		default:
299155324Simp			ERR(EAI_FAMILY);
300155324Simp		}
301155324Simp		memcpy(pai, hints, sizeof(*pai));
302155324Simp
303155324Simp		/*
304155324Simp		 * if both socktype/protocol are specified, check if they
305155324Simp		 * are meaningful combination.
306155324Simp		 */
307155324Simp		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
308155324Simp			int matched = 0;
309155324Simp
310155324Simp			for (ex = explore; ex->e_af >= 0; ex++) {
311155324Simp				if (pai->ai_family != ex->e_af)
312155324Simp					continue;
313155324Simp				if (ex->e_socktype == ANY)
314155324Simp					continue;
315155324Simp				if (ex->e_protocol == ANY)
316155324Simp					continue;
317155324Simp				if (pai->ai_socktype == ex->e_socktype
318155324Simp				 && pai->ai_protocol == ex->e_protocol)
319157024Scognet					matched = 1;
320155324Simp				else
321157024Scognet					continue;
322155324Simp				if (matched == 0)
323155324Simp					ERR(EAI_BADHINTS);
324155324Simp			}
325155324Simp		}
326155324Simp	}
327155324Simp
328155324Simp	/* backup original pai contents */
329155324Simp	ai0 = *pai;
330155324Simp
331155324Simp	/*
332155324Simp	 * special cases check for inet and inet6 sockets.
333155324Simp	 * (1) servname is disallowed for raw sockets.
334155324Simp	 * (2) numeric servname is disallowed if socktype/protocol is left
335155324Simp	 *     unspecified.
336155324Simp	 */
337155324Simp	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
338155324Simp#ifdef INET6
339155324Simp	    || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
340155324Simp#endif
341155324Simp	    ) {
342155324Simp		*pai = ai0;
343155324Simp
344155324Simp		if (pai->ai_family == PF_UNSPEC)
345155324Simp#ifdef INET6
346155324Simp			pai->ai_family = PF_INET6;
347155324Simp#else
348155324Simp			pai->ai_family = PF_INET;
349155324Simp#endif
350155324Simp		error = get_portmatch(pai, servname);
351155324Simp		if (error)
352155324Simp			ERR(error);
353155324Simp	}
354155324Simp
355155324Simp	/* NULL hostname, or numeric hostname */
356155324Simp	for (ex = explore; ex->e_af >= 0; ex++) {
357155324Simp		*pai = ai0;
358155324Simp
359155324Simp		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
360155324Simp			continue;
361157029Scognet		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
362159795Simp			continue;
363159814Simp		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
364159814Simp			continue;
365155324Simp
366155324Simp		if (pai->ai_family == PF_UNSPEC)
367155324Simp			pai->ai_family = ex->e_af;
368155324Simp		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
369155324Simp			pai->ai_socktype = ex->e_socktype;
370155324Simp		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
371155324Simp			pai->ai_protocol = ex->e_protocol;
372155324Simp
373155324Simp		if (hostname == NULL)
374155324Simp			error = explore_null(pai, hostname, servname, &cur->ai_next);
375155324Simp		else
376155324Simp			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
377155324Simp
378155324Simp		if (error)
379155324Simp			goto free;
380155324Simp
381155324Simp		while (cur && cur->ai_next)
382155324Simp			cur = cur->ai_next;
383155324Simp	}
384155324Simp
385155324Simp	/*
386155324Simp	 * XXX
387155324Simp	 * If numreic representation of AF1 can be interpreted as FQDN
388155324Simp	 * representation of AF2, we need to think again about the code below.
389155324Simp	 */
390155324Simp	if (sentinel.ai_next)
391155324Simp		goto good;
392155324Simp
393155324Simp	if (pai->ai_flags & AI_NUMERICHOST)
394155324Simp		ERR(EAI_NONAME);
395155324Simp	if (hostname == NULL)
396155324Simp		ERR(EAI_NONAME);
397155324Simp
398155324Simp	/*
399155324Simp	 * hostname as alphabetical name.
400155324Simp	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
401155324Simp	 * outer loop by AFs.
402155324Simp	 */
403155324Simp	for (afd = afdl; afd->a_af; afd++) {
404155324Simp		*pai = ai0;
405155324Simp
406155324Simp		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
407155324Simp			continue;
408155324Simp
409155324Simp		for (ex = explore; ex->e_af >= 0; ex++) {
410155324Simp			*pai = ai0;
411155324Simp
412155324Simp			if (pai->ai_family == PF_UNSPEC)
413155324Simp				pai->ai_family = afd->a_af;
414155324Simp
415155324Simp			if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
416155324Simp					  WILD_AF(ex)))
417155324Simp				continue;
418155324Simp			if (!MATCH(pai->ai_socktype, ex->e_socktype,
419155324Simp					WILD_SOCKTYPE(ex))) {
420155324Simp				continue;
421155324Simp			}
422155324Simp			if (!MATCH(pai->ai_protocol, ex->e_protocol,
423155324Simp					WILD_PROTOCOL(ex))) {
424155324Simp				continue;
425155324Simp			}
426155324Simp
427155324Simp			if (pai->ai_family == PF_UNSPEC)
428155324Simp				pai->ai_family = ex->e_af;
429155324Simp			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
430155324Simp				pai->ai_socktype = ex->e_socktype;
431155324Simp			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
432155324Simp				pai->ai_protocol = ex->e_protocol;
433159814Simp
434155324Simp			error = explore_fqdn(pai, hostname, servname,
435155324Simp				&cur->ai_next);
436155324Simp
437155324Simp			while (cur && cur->ai_next)
438155324Simp				cur = cur->ai_next;
439		}
440	}
441
442	/* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */
443	if (sentinel.ai_next) {
444 good:
445		*res = sentinel.ai_next;
446		return SUCCESS;
447	}
448	/* else, failed */
449 free:
450 bad:
451	if (error == 0)
452		error = EAI_FAIL;
453	if (sentinel.ai_next)
454		freeaddrinfo(sentinel.ai_next);
455	*res = NULL;
456	return error;
457}
458
459/*
460 * FQDN hostname, DNS lookup
461 */
462static int
463explore_fqdn(pai, hostname, servname, res)
464	const struct addrinfo *pai;
465	const char *hostname;
466	const char *servname;
467	struct addrinfo **res;
468{
469	struct hostent *hp;
470	int h_error;
471	int af;
472	char *ap;
473	struct addrinfo sentinel, *cur;
474	int i;
475	const struct afd *afd;
476	int error;
477
478	*res = NULL;
479	sentinel.ai_next = NULL;
480	cur = &sentinel;
481
482	/*
483	 * if the servname does not match socktype/protocol, ignore it.
484	 */
485	if (get_portmatch(pai, servname) != 0)
486		return 0;
487
488	afd = find_afd(pai->ai_family);
489	if (afd == NULL)
490		return 0;
491
492	hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG,
493			     &h_error);
494	if (hp == NULL) {
495		switch (h_error) {
496		case HOST_NOT_FOUND:
497		case NO_DATA:
498			error = EAI_NODATA;
499			break;
500		case TRY_AGAIN:
501			error = EAI_AGAIN;
502			break;
503		case NO_RECOVERY:
504		case NETDB_INTERNAL:
505		default:
506			error = EAI_FAIL;
507			break;
508		}
509	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
510			|| (hp->h_addr_list[0] == NULL)) {
511		freehostent(hp);
512		hp = NULL;
513		error = EAI_FAIL;
514	}
515
516	if (hp == NULL)
517		goto free;
518
519	for (i = 0; hp->h_addr_list[i] != NULL; i++) {
520		af = hp->h_addrtype;
521		ap = hp->h_addr_list[i];
522
523		if (af != pai->ai_family)
524			continue;
525
526		GET_AI(cur->ai_next, afd, ap);
527		GET_PORT(cur->ai_next, servname);
528		if ((pai->ai_flags & AI_CANONNAME) != 0) {
529			/*
530			 * RFC2553 says that ai_canonname will be set only for
531			 * the first element.  we do it for all the elements,
532			 * just for convenience.
533			 */
534			GET_CANONNAME(cur->ai_next, hp->h_name);
535		}
536
537		while (cur && cur->ai_next)
538			cur = cur->ai_next;
539	}
540
541	*res = sentinel.ai_next;
542	return 0;
543
544free:
545	if (hp)
546		freehostent(hp);
547	if (sentinel.ai_next)
548		freeaddrinfo(sentinel.ai_next);
549	return error;
550}
551
552/*
553 * hostname == NULL.
554 * passive socket -> anyaddr (0.0.0.0 or ::)
555 * non-passive socket -> localhost (127.0.0.1 or ::1)
556 */
557static int
558explore_null(pai, hostname, servname, res)
559	const struct addrinfo *pai;
560	const char *hostname;
561	const char *servname;
562	struct addrinfo **res;
563{
564	int s;
565	const struct afd *afd;
566	struct addrinfo *cur;
567	struct addrinfo sentinel;
568	int error;
569
570	*res = NULL;
571	sentinel.ai_next = NULL;
572	cur = &sentinel;
573
574	/*
575	 * filter out AFs that are not supported by the kernel
576	 * XXX errno?
577	 */
578	s = socket(pai->ai_family, SOCK_DGRAM, 0);
579	if (s < 0)
580		return 0;
581	_close(s);
582	afd = find_afd(pai->ai_family);
583	if (afd == NULL)
584		return 0;
585
586	GET_AI(cur->ai_next, afd,
587	       (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback
588	       );
589	/* xxx meaningless?
590	 * GET_CANONNAME(cur->ai_next, "anyaddr");
591	 * or
592	 * GET_CANONNAME(cur->ai_next, "localhost");
593	 */
594	/* if the servname does not match socktype/protocol, ignored */
595	GET_PORT(cur->ai_next, servname);
596
597	*res = sentinel.ai_next;
598	return 0;
599
600free:
601	if (sentinel.ai_next)
602		freeaddrinfo(sentinel.ai_next);
603	return error;
604}
605
606/*
607 * numeric hostname
608 */
609static int
610explore_numeric(pai, hostname, servname, res)
611	const struct addrinfo *pai;
612	const char *hostname;
613	const char *servname;
614	struct addrinfo **res;
615{
616	const struct afd *afd;
617	struct addrinfo *cur;
618	struct addrinfo sentinel;
619	int error;
620	char pton[PTON_MAX];
621	int flags;
622
623	*res = NULL;
624	sentinel.ai_next = NULL;
625	cur = &sentinel;
626
627	/*
628	 * if the servname does not match socktype/protocol, ignore it.
629	 */
630	if (get_portmatch(pai, servname) != 0)
631		return 0;
632
633	afd = find_afd(pai->ai_family);
634	if (afd == NULL)
635		return 0;
636	flags = pai->ai_flags;
637
638	if ((afd->a_af == AF_INET
639	     ? inet_aton(hostname, (struct in_addr *)pton)
640	     : inet_pton(afd->a_af, hostname, pton)) == 1) {
641		if (pai->ai_family == afd->a_af ||
642		    pai->ai_family == PF_UNSPEC /*?*/) {
643			GET_AI(cur->ai_next, afd, pton);
644			GET_PORT(cur->ai_next, servname);
645			while (cur && cur->ai_next)
646				cur = cur->ai_next;
647		} else
648			ERR(EAI_FAMILY);	/*xxx*/
649	}
650
651	*res = sentinel.ai_next;
652	return 0;
653
654free:
655bad:
656	if (sentinel.ai_next)
657		freeaddrinfo(sentinel.ai_next);
658	return error;
659}
660
661/*
662 * numeric hostname with scope
663 */
664static int
665explore_numeric_scope(pai, hostname, servname, res)
666	const struct addrinfo *pai;
667	const char *hostname;
668	const char *servname;
669	struct addrinfo **res;
670{
671#ifndef SCOPE_DELIMITER
672	return explore_numeric(pai, hostname, servname, res);
673#else
674	const struct afd *afd;
675	struct addrinfo *cur;
676	int error;
677	char *cp, *hostname2 = NULL;
678	int scope;
679#ifdef INET6
680	struct sockaddr_in6 *sin6;
681#endif
682
683	/*
684	 * if the servname does not match socktype/protocol, ignore it.
685	 */
686	if (get_portmatch(pai, servname) != 0)
687		return 0;
688
689	afd = find_afd(pai->ai_family);
690	if (afd == NULL)
691		return 0;
692	if (!afd->a_scoped)
693		return explore_numeric(pai, hostname, servname, res);
694
695	cp = strchr(hostname, SCOPE_DELIMITER);
696	if (cp == NULL)
697		return explore_numeric(pai, hostname, servname, res);
698
699	/*
700	 * Handle special case of <scoped_address><delimiter><scope id>
701	 */
702	hostname2 = strdup(hostname);
703	if (hostname2 == NULL)
704		return EAI_MEMORY;
705	/* terminate at the delimiter */
706	hostname2[cp - hostname] = '\0';
707
708	cp++;
709	switch (pai->ai_family) {
710#ifdef INET6
711	case AF_INET6:
712		scope = if_nametoindex(hostname2);
713		if (scope == 0) {
714			error = EAI_SYSTEM;
715			goto free;
716		}
717		break;
718#endif
719	}
720
721	error = explore_numeric(pai, cp, servname, res);
722	if (error == 0) {
723		for (cur = *res; cur; cur = cur->ai_next) {
724#ifdef INET6
725			if (cur->ai_family != AF_INET6)
726				continue;
727			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
728			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
729			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
730				sin6->sin6_scope_id = scope;
731#endif
732		}
733	}
734
735#ifdef INET6
736free:
737#endif
738	free(hostname2);
739
740	return error;
741#endif
742}
743
744static int
745get_canonname(pai, ai, str)
746	const struct addrinfo *pai;
747	struct addrinfo *ai;
748	const char *str;
749{
750	if ((pai->ai_flags & AI_CANONNAME) != 0) {
751		ai->ai_canonname = (char *)malloc(strlen(str) + 1);
752		if (ai->ai_canonname == NULL)
753			return EAI_MEMORY;
754		strcpy(ai->ai_canonname, str);
755	}
756	return 0;
757}
758
759static struct addrinfo *
760get_ai(pai, afd, addr)
761	const struct addrinfo *pai;
762	const struct afd *afd;
763	const char *addr;
764{
765	char *p;
766	struct addrinfo *ai;
767#ifdef FAITH
768	struct in6_addr faith_prefix;
769	char *fp_str;
770	int translate = 0;
771#endif
772
773#ifdef FAITH
774	/*
775	 * Transfrom an IPv4 addr into a special IPv6 addr format for
776	 * IPv6->IPv4 translation gateway. (only TCP is supported now)
777	 *
778	 * +-----------------------------------+------------+
779	 * | faith prefix part (12 bytes)      | embedded   |
780	 * |                                   | IPv4 addr part (4 bytes)
781	 * +-----------------------------------+------------+
782	 *
783	 * faith prefix part is specified as ascii IPv6 addr format
784	 * in environmental variable GAI.
785	 * For FAITH to work correctly, routing to faith prefix must be
786	 * setup toward a machine where a FAITH daemon operates.
787	 * Also, the machine must enable some mechanizm
788	 * (e.g. faith interface hack) to divert those packet with
789	 * faith prefixed destination addr to user-land FAITH daemon.
790	 */
791	fp_str = getenv("GAI");
792	if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
793	    afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
794		u_int32_t v4a;
795		u_int8_t v4a_top;
796
797		memcpy(&v4a, addr, sizeof v4a);
798		v4a_top = v4a >> IN_CLASSA_NSHIFT;
799		if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
800		    v4a_top != 0 && v4a != IN_LOOPBACKNET) {
801			afd = &afdl[N_INET6];
802			memcpy(&faith_prefix.s6_addr[12], addr,
803			       sizeof(struct in_addr));
804			translate = 1;
805		}
806	}
807#endif
808
809	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
810		+ (afd->a_socklen));
811	if (ai == NULL)
812		return NULL;
813
814	memcpy(ai, pai, sizeof(struct addrinfo));
815	ai->ai_addr = (struct sockaddr *)(ai + 1);
816	memset(ai->ai_addr, 0, afd->a_socklen);
817	ai->ai_addr->sa_len = afd->a_socklen;
818	ai->ai_addrlen = afd->a_socklen;
819	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
820	p = (char *)(ai->ai_addr);
821#ifdef FAITH
822	if (translate == 1)
823		memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen);
824	else
825#endif
826	memcpy(p + afd->a_off, addr, afd->a_addrlen);
827
828	return ai;
829}
830
831static int
832get_portmatch(ai, servname)
833	const struct addrinfo *ai;
834	const char *servname;
835{
836	/* get_port does not touch first argument. when matchonly == 1. */
837	return get_port((struct addrinfo *)ai, servname, 1);
838}
839
840static int
841get_port(ai, servname, matchonly)
842	struct addrinfo *ai;
843	const char *servname;
844	int matchonly;
845{
846	const char *proto;
847	struct servent *sp;
848	int port;
849	int allownumeric;
850
851	if (servname == NULL)
852		return 0;
853	if (ai->ai_family != AF_INET
854#ifdef INET6
855	    && ai->ai_family != AF_INET6
856#endif
857	    )
858		return 0;
859
860	switch (ai->ai_socktype) {
861	case SOCK_RAW:
862		return EAI_SERVICE;
863	case SOCK_DGRAM:
864	case SOCK_STREAM:
865		allownumeric = 1;
866		break;
867	case ANY:
868		allownumeric = 0;
869		break;
870	default:
871		return EAI_SOCKTYPE;
872	}
873
874	if (str_isnumber(servname)) {
875		if (!allownumeric)
876			return EAI_SERVICE;
877		port = htons(atoi(servname));
878		if (port < 0 || port > 65535)
879			return EAI_SERVICE;
880	} else {
881		switch (ai->ai_socktype) {
882		case SOCK_DGRAM:
883			proto = "udp";
884			break;
885		case SOCK_STREAM:
886			proto = "tcp";
887			break;
888		default:
889			proto = NULL;
890			break;
891		}
892
893		if ((sp = getservbyname(servname, proto)) == NULL)
894			return EAI_SERVICE;
895		port = sp->s_port;
896	}
897
898	if (!matchonly) {
899		switch (ai->ai_family) {
900		case AF_INET:
901			((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
902			break;
903#ifdef INET6
904		case AF_INET6:
905			((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
906			break;
907#endif
908		}
909	}
910
911	return 0;
912}
913
914static const struct afd *
915find_afd(af)
916	int af;
917{
918	const struct afd *afd;
919
920	if (af == PF_UNSPEC)
921		return NULL;
922	for (afd = afdl; afd->a_af; afd++) {
923		if (afd->a_af == af)
924			return afd;
925	}
926	return NULL;
927}
928