getaddrinfo.c revision 57107
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/lib/libc/net/getaddrinfo.c 57107 2000-02-10 02:59:50Z shin $
30 */
31
32/*
33 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
34 *
35 * Issues to be discussed:
36 * - Thread safe-ness must be checked.
37 * - Return values.  There are nonstandard return values defined and used
38 *   in the source code.  This is because RFC2553 is silent about which error
39 *   code must be returned for which situation.
40 * Note:
41 * - We use getipnodebyname() just for thread-safeness.  There's no intent
42 *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
43 *   getipnodebyname().
44 * - The code filters out AFs that are not supported by the kernel,
45 *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
46 *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
47 *   in ai_flags?
48 */
49
50#include <sys/types.h>
51#include <sys/param.h>
52#include <sys/socket.h>
53#include <net/if.h>
54#include <netinet/in.h>
55#include <arpa/inet.h>
56#include <arpa/nameser.h>
57#include <netdb.h>
58#include <resolv.h>
59#include <string.h>
60#include <stdlib.h>
61#include <stddef.h>
62#include <ctype.h>
63#include <unistd.h>
64#include <stdio.h>
65
66#if defined(__KAME__) && defined(INET6)
67# define FAITH
68#endif
69
70#define	SUCCESS 0
71#define	ANY 0
72#define	YES 1
73#define	NO  0
74
75static const char in_addrany[] = { 0, 0, 0, 0 };
76static const char in6_addrany[] = {
77	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
78};
79static const char in_loopback[] = { 127, 0, 0, 1 };
80static const char in6_loopback[] = {
81	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
82};
83
84static const struct afd {
85	int a_af;
86	int a_addrlen;
87	int a_socklen;
88	int a_off;
89	const char *a_addrany;
90	const char *a_loopback;
91	int a_scoped;
92} afdl [] = {
93#ifdef INET6
94#define	N_INET6 0
95	{PF_INET6, sizeof(struct in6_addr),
96	 sizeof(struct sockaddr_in6),
97	 offsetof(struct sockaddr_in6, sin6_addr),
98	 in6_addrany, in6_loopback, 1},
99#define	N_INET 1
100#else
101#define	N_INET 0
102#endif
103	{PF_INET, sizeof(struct in_addr),
104	 sizeof(struct sockaddr_in),
105	 offsetof(struct sockaddr_in, sin_addr),
106	 in_addrany, in_loopback, 0},
107	{0, 0, 0, 0, NULL, NULL, 0},
108};
109
110struct explore {
111	int e_af;
112	int e_socktype;
113	int e_protocol;
114	const char *e_protostr;
115	int e_wild;
116#define	WILD_AF(ex)		((ex)->e_wild & 0x01)
117#define	WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
118#define	WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
119};
120
121static const struct explore explore[] = {
122#ifdef INET6
123	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
124	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
125	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
126#endif
127	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
128	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
129	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
130	{ -1, 0, 0, NULL, 0 },
131};
132
133#ifdef INET6
134#define	PTON_MAX	16
135#else
136#define	PTON_MAX	4
137#endif
138
139
140static int str_isnumber __P((const char *));
141static int explore_fqdn __P((const struct addrinfo *, const char *,
142	const char *, struct addrinfo **));
143static int explore_null __P((const struct addrinfo *, const char *,
144	const char *, struct addrinfo **));
145static int explore_numeric __P((const struct addrinfo *, const char *,
146	const char *, struct addrinfo **));
147static int explore_numeric_scope __P((const struct addrinfo *, const char *,
148	const char *, struct addrinfo **));
149static int get_canonname __P((const struct addrinfo *,
150	struct addrinfo *, const char *));
151static struct addrinfo *get_ai __P((const struct addrinfo *,
152	const struct afd *, const char *));
153static int get_portmatch __P((const struct addrinfo *, const char *));
154static int get_port __P((struct addrinfo *, const char *, int));
155static const struct afd *find_afd __P((int));
156
157static char *ai_errlist[] = {
158	"Success",
159	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
160	"Temporary failure in name resolution",		/* EAI_AGAIN      */
161	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
162	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
163	"ai_family not supported",			/* EAI_FAMILY     */
164	"Memory allocation failure", 			/* EAI_MEMORY     */
165	"No address associated with hostname", 		/* EAI_NODATA     */
166	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
167	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
168	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
169	"System error returned in errno", 		/* EAI_SYSTEM     */
170	"Invalid value for hints",			/* EAI_BADHINTS	  */
171	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
172	"Argument res is NULL",				/* EAI_RESNULL	  */
173	"Unknown error", 				/* EAI_MAX        */
174};
175
176/* XXX macros that make external reference is BAD. */
177
178#define	GET_AI(ai, afd, addr) \
179do { \
180	/* external reference: pai, error, and label free */ \
181	(ai) = get_ai(pai, (afd), (addr)); \
182	if ((ai) == NULL) { \
183		error = EAI_MEMORY; \
184		goto free; \
185	} \
186} while (0)
187
188#define	GET_PORT(ai, serv) \
189do { \
190	/* external reference: error and label free */ \
191	error = get_port((ai), (serv), 0); \
192	if (error != 0) \
193		goto free; \
194} while (0)
195
196#define	GET_CANONNAME(ai, str) \
197do { \
198	/* external reference: pai, error and label free */ \
199	error = get_canonname(pai, (ai), (str)); \
200	if (error != 0) \
201		goto free; \
202} while (0)
203
204#define	ERR(err) \
205do { \
206	/* external reference: error, and label bad */ \
207	error = (err); \
208	goto bad; \
209} while (0)
210
211#define	MATCH_FAMILY(x, y, w) \
212	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
213#define	MATCH(x, y, w) \
214	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
215
216char *
217gai_strerror(ecode)
218	int ecode;
219{
220	if (ecode < 0 || ecode > EAI_MAX)
221		ecode = EAI_MAX;
222	return ai_errlist[ecode];
223}
224
225void
226freeaddrinfo(ai)
227	struct addrinfo *ai;
228{
229	struct addrinfo *next;
230
231	do {
232		next = ai->ai_next;
233		if (ai->ai_canonname)
234			free(ai->ai_canonname);
235		/* no need to free(ai->ai_addr) */
236		free(ai);
237	} while ((ai = next) != NULL);
238}
239
240static int
241str_isnumber(p)
242	const char *p;
243{
244	char *q = (char *)p;
245	while (*q) {
246		if (! isdigit(*q))
247			return NO;
248		q++;
249	}
250	return YES;
251}
252
253int
254getaddrinfo(hostname, servname, hints, res)
255	const char *hostname, *servname;
256	const struct addrinfo *hints;
257	struct addrinfo **res;
258{
259	struct addrinfo sentinel;
260	struct addrinfo *cur;
261	int error = 0;
262	struct addrinfo ai;
263	struct addrinfo ai0;
264	struct addrinfo *pai;
265	const struct afd *afd;
266	const struct explore *ex;
267
268	sentinel.ai_next = NULL;
269	cur = &sentinel;
270	pai = &ai;
271	pai->ai_flags = 0;
272	pai->ai_family = PF_UNSPEC;
273	pai->ai_socktype = ANY;
274	pai->ai_protocol = ANY;
275	pai->ai_addrlen = 0;
276	pai->ai_canonname = NULL;
277	pai->ai_addr = NULL;
278	pai->ai_next = NULL;
279
280	if (hostname == NULL && servname == NULL)
281		return EAI_NONAME;
282	if (res == NULL)
283		return EAI_RESNULL; /* xxx */
284	if (hints) {
285		/* error check for hints */
286		if (hints->ai_addrlen || hints->ai_canonname ||
287		    hints->ai_addr || hints->ai_next)
288			ERR(EAI_BADHINTS); /* xxx */
289		if (hints->ai_flags & ~AI_MASK)
290			ERR(EAI_BADFLAGS);
291		switch (hints->ai_family) {
292		case PF_UNSPEC:
293		case PF_INET:
294#ifdef INET6
295		case PF_INET6:
296#endif
297			break;
298		default:
299			ERR(EAI_FAMILY);
300		}
301		memcpy(pai, hints, sizeof(*pai));
302
303		/*
304		 * if both socktype/protocol are specified, check if they
305		 * are meaningful combination.
306		 */
307		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
308			int matched = 0;
309
310			for (ex = explore; ex->e_af >= 0; ex++) {
311				if (pai->ai_family != ex->e_af)
312					continue;
313				if (ex->e_socktype == ANY)
314					continue;
315				if (ex->e_protocol == ANY)
316					continue;
317				if (pai->ai_socktype == ex->e_socktype
318				 && pai->ai_protocol == ex->e_protocol)
319					matched = 1;
320				else
321					continue;
322				if (matched == 0)
323					ERR(EAI_BADHINTS);
324			}
325		}
326	}
327
328	/* backup original pai contents */
329	ai0 = *pai;
330
331	/*
332	 * special cases check for inet and inet6 sockets.
333	 * (1) servname is disallowed for raw sockets.
334	 * (2) numeric servname is disallowed if socktype/protocol is left
335	 *     unspecified.
336	 */
337	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
338#ifdef INET6
339	    || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
340#endif
341	    ) {
342		*pai = ai0;
343
344		if (pai->ai_family == PF_UNSPEC)
345#ifdef INET6
346			pai->ai_family = PF_INET6;
347#else
348			pai->ai_family = PF_INET;
349#endif
350		error = get_portmatch(pai, servname);
351		if (error)
352			ERR(error);
353	}
354
355	/* NULL hostname, or numeric hostname */
356	for (ex = explore; ex->e_af >= 0; ex++) {
357		*pai = ai0;
358
359		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
360			continue;
361		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
362			continue;
363		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
364			continue;
365
366		if (pai->ai_family == PF_UNSPEC)
367			pai->ai_family = ex->e_af;
368		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
369			pai->ai_socktype = ex->e_socktype;
370		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
371			pai->ai_protocol = ex->e_protocol;
372
373		if (hostname == NULL)
374			error = explore_null(pai, hostname, servname, &cur->ai_next);
375		else
376			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
377
378		if (error)
379			goto free;
380
381		while (cur && cur->ai_next)
382			cur = cur->ai_next;
383	}
384
385	/*
386	 * XXX
387	 * If numreic representation of AF1 can be interpreted as FQDN
388	 * representation of AF2, we need to think again about the code below.
389	 */
390	if (sentinel.ai_next)
391		goto good;
392
393	if (pai->ai_flags & AI_NUMERICHOST)
394		ERR(EAI_NONAME);
395	if (hostname == NULL)
396		ERR(EAI_NONAME);
397
398	/*
399	 * hostname as alphabetical name.
400	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
401	 * outer loop by AFs.
402	 */
403	for (afd = afdl; afd->a_af; afd++) {
404		*pai = ai0;
405
406		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
407			continue;
408
409		for (ex = explore; ex->e_af >= 0; ex++) {
410			*pai = ai0;
411
412			if (pai->ai_family == PF_UNSPEC)
413				pai->ai_family = afd->a_af;
414
415			if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
416					  WILD_AF(ex)))
417				continue;
418			if (!MATCH(pai->ai_socktype, ex->e_socktype,
419					WILD_SOCKTYPE(ex))) {
420				continue;
421			}
422			if (!MATCH(pai->ai_protocol, ex->e_protocol,
423					WILD_PROTOCOL(ex))) {
424				continue;
425			}
426
427			if (pai->ai_family == PF_UNSPEC)
428				pai->ai_family = ex->e_af;
429			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
430				pai->ai_socktype = ex->e_socktype;
431			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
432				pai->ai_protocol = ex->e_protocol;
433
434			error = explore_fqdn(pai, hostname, servname,
435				&cur->ai_next);
436
437			while (cur && cur->ai_next)
438				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