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
30/*
31 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
32 *
33 * Issues to be discussed:
34 * - Thread safe-ness must be checked.
35 * - Return values.  There are nonstandard return values defined and used
36 *   in the source code.  This is because RFC2553 is silent about which error
37 *   code must be returned for which situation.
38 * Note:
39 * - We use getipnodebyname() just for thread-safeness.  There's no intent
40 *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
41 *   getipnodebyname().
42 * - The code filters out AFs that are not supported by the kernel,
43 *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
44 *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
45 *   in ai_flags?
46 */
47
48#ifdef HAVE_CONFIG_H
49#include <config.h>
50#endif
51
52#ifndef lint
53static const char rcsid[] _U_ =
54     "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.13 2003/11/16 09:36:48 guy Exp $";
55#endif
56
57#include <sys/types.h>
58#include <sys/param.h>
59#if 0
60#include <sys/sysctl.h>
61#endif
62#include <sys/socket.h>
63#include <net/if.h>
64#include <netinet/in.h>
65#include <arpa/inet.h>
66#include <arpa/nameser.h>
67#include <netdb.h>
68#include <resolv.h>
69#include <string.h>
70#include <stdlib.h>
71#include <stddef.h>
72#include <ctype.h>
73#include <unistd.h>
74#include <stdio.h>
75#include <errno.h>
76
77#ifndef HAVE_U_INT32_T
78#include "bittypes.h"
79#endif
80
81#ifndef HAVE_SOCKADDR_STORAGE
82#include "sockstorage.h"
83#endif
84
85#ifdef NEED_ADDRINFO_H
86#include "addrinfo.h"
87#endif
88
89#if defined(__KAME__) && defined(INET6)
90# define FAITH
91#endif
92
93#define SUCCESS 0
94#define ANY 0
95#define YES 1
96#define NO  0
97
98#ifdef FAITH
99static int translate = NO;
100static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
101#endif
102
103static const char in_addrany[] = { 0, 0, 0, 0 };
104static const char in6_addrany[] = {
105	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106};
107static const char in_loopback[] = { 127, 0, 0, 1 };
108static const char in6_loopback[] = {
109	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
110};
111
112struct sockinet {
113	u_char	si_len;
114	u_char	si_family;
115	u_short	si_port;
116	u_int32_t si_scope_id;
117};
118
119static const struct afd {
120	int a_af;
121	int a_addrlen;
122	int a_socklen;
123	int a_off;
124	const char *a_addrany;
125	const char *a_loopback;
126	int a_scoped;
127} afdl [] = {
128#ifdef INET6
129	{PF_INET6, sizeof(struct in6_addr),
130	 sizeof(struct sockaddr_in6),
131	 offsetof(struct sockaddr_in6, sin6_addr),
132	 in6_addrany, in6_loopback, 1},
133#endif
134	{PF_INET, sizeof(struct in_addr),
135	 sizeof(struct sockaddr_in),
136	 offsetof(struct sockaddr_in, sin_addr),
137	 in_addrany, in_loopback, 0},
138	{0, 0, 0, 0, NULL, NULL, 0},
139};
140
141struct explore {
142	int e_af;
143	int e_socktype;
144	int e_protocol;
145	const char *e_protostr;
146	int e_wild;
147#define WILD_AF(ex)		((ex)->e_wild & 0x01)
148#define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
149#define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
150};
151
152static const struct explore explore[] = {
153#if 0
154	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
155#endif
156#ifdef INET6
157	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
158	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
159	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
160#endif
161	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
162	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
163	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
164	{ -1, 0, 0, NULL, 0 },
165};
166
167#ifdef INET6
168#define PTON_MAX	16
169#else
170#define PTON_MAX	4
171#endif
172
173
174static int str_isnumber (const char *);
175static int explore_fqdn (const struct addrinfo *, const char *,
176	const char *, struct addrinfo **);
177static int explore_null (const struct addrinfo *, const char *,
178	const char *, struct addrinfo **);
179static int explore_numeric (const struct addrinfo *, const char *,
180	const char *, struct addrinfo **);
181static int explore_numeric_scope (const struct addrinfo *, const char *,
182	const char *, struct addrinfo **);
183static int get_name (const char *, const struct afd *, struct addrinfo **,
184	char *, const struct addrinfo *, const char *);
185static int get_canonname (const struct addrinfo *,
186	struct addrinfo *, const char *);
187static struct addrinfo *get_ai (const struct addrinfo *,
188	const struct afd *, const char *);
189static int get_portmatch (const struct addrinfo *, const char *);
190static int get_port (struct addrinfo *, const char *, int);
191static const struct afd *find_afd (int);
192
193static char *ai_errlist[] = {
194	"Success",
195	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
196	"Temporary failure in name resolution",		/* EAI_AGAIN      */
197	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
198	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
199	"ai_family not supported",			/* EAI_FAMILY     */
200	"Memory allocation failure", 			/* EAI_MEMORY     */
201	"No address associated with hostname", 		/* EAI_NODATA     */
202	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
203	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
204	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
205	"System error returned in errno", 		/* EAI_SYSTEM     */
206	"Invalid value for hints",			/* EAI_BADHINTS	  */
207	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
208	"Unknown error", 				/* EAI_MAX        */
209};
210
211/* XXX macros that make external reference is BAD. */
212
213#define GET_AI(ai, afd, addr) \
214do { \
215	/* external reference: pai, error, and label free */ \
216	(ai) = get_ai(pai, (afd), (addr)); \
217	if ((ai) == NULL) { \
218		error = EAI_MEMORY; \
219		goto free; \
220	} \
221} while (0)
222
223#define GET_PORT(ai, serv) \
224do { \
225	/* external reference: error and label free */ \
226	error = get_port((ai), (serv), 0); \
227	if (error != 0) \
228		goto free; \
229} while (0)
230
231#define GET_CANONNAME(ai, str) \
232do { \
233	/* external reference: pai, error and label free */ \
234	error = get_canonname(pai, (ai), (str)); \
235	if (error != 0) \
236		goto free; \
237} while (0)
238
239#define ERR(err) \
240do { \
241	/* external reference: error, and label bad */ \
242	error = (err); \
243	goto bad; \
244} while (0)
245
246#define MATCH_FAMILY(x, y, w) \
247	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
248#define MATCH(x, y, w) \
249	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
250
251char *
252gai_strerror(ecode)
253	int ecode;
254{
255	if (ecode < 0 || ecode > EAI_MAX)
256		ecode = EAI_MAX;
257	return ai_errlist[ecode];
258}
259
260void
261freeaddrinfo(ai)
262	struct addrinfo *ai;
263{
264	struct addrinfo *next;
265
266	do {
267		next = ai->ai_next;
268		if (ai->ai_canonname)
269			free(ai->ai_canonname);
270		/* no need to free(ai->ai_addr) */
271		free(ai);
272	} while ((ai = next) != NULL);
273}
274
275static int
276str_isnumber(p)
277	const char *p;
278{
279	char *q = (char *)p;
280	while (*q) {
281		if (! isdigit(*q))
282			return NO;
283		q++;
284	}
285	return YES;
286}
287
288int
289getaddrinfo(hostname, servname, hints, res)
290	const char *hostname, *servname;
291	const struct addrinfo *hints;
292	struct addrinfo **res;
293{
294	struct addrinfo sentinel;
295	struct addrinfo *cur;
296	int error = 0;
297	struct addrinfo ai;
298	struct addrinfo ai0;
299	struct addrinfo *pai;
300	const struct afd *afd;
301	const struct explore *ex;
302
303#ifdef FAITH
304	static int firsttime = 1;
305
306	if (firsttime) {
307		/* translator hack */
308		char *q = getenv("GAI");
309		if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
310			translate = YES;
311		firsttime = 0;
312	}
313#endif
314
315	sentinel.ai_next = NULL;
316	cur = &sentinel;
317	pai = &ai;
318	pai->ai_flags = 0;
319	pai->ai_family = PF_UNSPEC;
320	pai->ai_socktype = ANY;
321	pai->ai_protocol = ANY;
322	pai->ai_addrlen = 0;
323	pai->ai_canonname = NULL;
324	pai->ai_addr = NULL;
325	pai->ai_next = NULL;
326
327	if (hostname == NULL && servname == NULL)
328		return EAI_NONAME;
329	if (hints) {
330		/* error check for hints */
331		if (hints->ai_addrlen || hints->ai_canonname ||
332		    hints->ai_addr || hints->ai_next)
333			ERR(EAI_BADHINTS); /* xxx */
334		if (hints->ai_flags & ~AI_MASK)
335			ERR(EAI_BADFLAGS);
336		switch (hints->ai_family) {
337		case PF_UNSPEC:
338		case PF_INET:
339#ifdef INET6
340		case PF_INET6:
341#endif
342			break;
343		default:
344			ERR(EAI_FAMILY);
345		}
346		memcpy(pai, hints, sizeof(*pai));
347
348		/*
349		 * if both socktype/protocol are specified, check if they
350		 * are meaningful combination.
351		 */
352		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
353			for (ex = explore; ex->e_af >= 0; ex++) {
354				if (pai->ai_family != ex->e_af)
355					continue;
356				if (ex->e_socktype == ANY)
357					continue;
358				if (ex->e_protocol == ANY)
359					continue;
360				if (pai->ai_socktype == ex->e_socktype
361				 && pai->ai_protocol != ex->e_protocol) {
362					ERR(EAI_BADHINTS);
363				}
364			}
365		}
366	}
367
368	/*
369	 * check for special cases.  (1) numeric servname is disallowed if
370	 * socktype/protocol are left unspecified. (2) servname is disallowed
371	 * for raw and other inet{,6} sockets.
372	 */
373	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
374#ifdef PF_INET6
375	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
376#endif
377	    ) {
378		ai0 = *pai;
379
380		if (pai->ai_family == PF_UNSPEC) {
381#ifdef PF_INET6
382			pai->ai_family = PF_INET6;
383#else
384			pai->ai_family = PF_INET;
385#endif
386		}
387		error = get_portmatch(pai, servname);
388		if (error)
389			ERR(error);
390
391		*pai = ai0;
392	}
393
394	ai0 = *pai;
395
396	/* NULL hostname, or numeric hostname */
397	for (ex = explore; ex->e_af >= 0; ex++) {
398		*pai = ai0;
399
400		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
401			continue;
402		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
403			continue;
404		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
405			continue;
406
407		if (pai->ai_family == PF_UNSPEC)
408			pai->ai_family = ex->e_af;
409		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
410			pai->ai_socktype = ex->e_socktype;
411		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
412			pai->ai_protocol = ex->e_protocol;
413
414		if (hostname == NULL)
415			error = explore_null(pai, hostname, servname, &cur->ai_next);
416		else
417			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
418
419		if (error)
420			goto free;
421
422		while (cur && cur->ai_next)
423			cur = cur->ai_next;
424	}
425
426	/*
427	 * XXX
428	 * If numreic representation of AF1 can be interpreted as FQDN
429	 * representation of AF2, we need to think again about the code below.
430	 */
431	if (sentinel.ai_next)
432		goto good;
433
434	if (pai->ai_flags & AI_NUMERICHOST)
435		ERR(EAI_NONAME);
436	if (hostname == NULL)
437		ERR(EAI_NONAME);
438
439	/*
440	 * hostname as alphabetical name.
441	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
442	 * outer loop by AFs.
443	 */
444	for (afd = afdl; afd->a_af; afd++) {
445		*pai = ai0;
446
447		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
448			continue;
449
450		for (ex = explore; ex->e_af >= 0; ex++) {
451			*pai = ai0;
452
453			if (pai->ai_family == PF_UNSPEC)
454				pai->ai_family = afd->a_af;
455
456			if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
457				continue;
458			if (!MATCH(pai->ai_socktype, ex->e_socktype,
459					WILD_SOCKTYPE(ex))) {
460				continue;
461			}
462			if (!MATCH(pai->ai_protocol, ex->e_protocol,
463					WILD_PROTOCOL(ex))) {
464				continue;
465			}
466
467			if (pai->ai_family == PF_UNSPEC)
468				pai->ai_family = ex->e_af;
469			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
470				pai->ai_socktype = ex->e_socktype;
471			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
472				pai->ai_protocol = ex->e_protocol;
473
474			error = explore_fqdn(pai, hostname, servname,
475				&cur->ai_next);
476
477			while (cur && cur->ai_next)
478				cur = cur->ai_next;
479		}
480	}
481
482	/* XXX */
483	if (sentinel.ai_next)
484		error = 0;
485
486	if (error)
487		goto free;
488	if (error == 0) {
489		if (sentinel.ai_next) {
490 good:
491			*res = sentinel.ai_next;
492			return SUCCESS;
493		} else
494			error = EAI_FAIL;
495	}
496 free:
497 bad:
498	if (sentinel.ai_next)
499		freeaddrinfo(sentinel.ai_next);
500	*res = NULL;
501	return error;
502}
503
504/*
505 * FQDN hostname, DNS lookup
506 */
507static int
508explore_fqdn(pai, hostname, servname, res)
509	const struct addrinfo *pai;
510	const char *hostname;
511	const char *servname;
512	struct addrinfo **res;
513{
514	struct hostent *hp;
515	int h_error;
516	int af;
517	char **aplist = NULL, *apbuf = NULL;
518	char *ap;
519	struct addrinfo sentinel, *cur;
520	int i;
521#ifndef USE_GETIPNODEBY
522	int naddrs;
523#endif
524	const struct afd *afd;
525	int error;
526
527	*res = NULL;
528	sentinel.ai_next = NULL;
529	cur = &sentinel;
530
531	/*
532	 * Do not filter unsupported AFs here.  We need to honor content of
533	 * databases (/etc/hosts, DNS and others).  Otherwise we cannot
534	 * replace gethostbyname() by getaddrinfo().
535	 */
536
537	/*
538	 * if the servname does not match socktype/protocol, ignore it.
539	 */
540	if (get_portmatch(pai, servname) != 0)
541		return 0;
542
543	afd = find_afd(pai->ai_family);
544
545	/*
546	 * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
547	 * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
548	 * handling code by ourselves in case we don't have getipnodebyname().
549	 */
550#ifdef USE_GETIPNODEBY
551	hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
552#else
553#ifdef HAVE_GETHOSTBYNAME2
554	hp = gethostbyname2(hostname, pai->ai_family);
555#else
556	if (pai->ai_family != AF_INET)
557		return 0;
558	hp = gethostbyname(hostname);
559#ifdef HAVE_H_ERRNO
560	h_error = h_errno;
561#else
562	h_error = EINVAL;
563#endif
564#endif /*HAVE_GETHOSTBYNAME2*/
565#endif /*USE_GETIPNODEBY*/
566
567	if (hp == NULL) {
568		switch (h_error) {
569		case HOST_NOT_FOUND:
570		case NO_DATA:
571			error = EAI_NODATA;
572			break;
573		case TRY_AGAIN:
574			error = EAI_AGAIN;
575			break;
576		case NO_RECOVERY:
577		case NETDB_INTERNAL:
578		default:
579			error = EAI_FAIL;
580			break;
581		}
582	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
583			|| (hp->h_addr_list[0] == NULL)) {
584#ifdef USE_GETIPNODEBY
585		freehostent(hp);
586#endif
587		hp = NULL;
588		error = EAI_FAIL;
589	}
590
591	if (hp == NULL)
592		goto free;
593
594#ifdef USE_GETIPNODEBY
595	aplist = hp->h_addr_list;
596#else
597	/*
598	 * hp will be overwritten if we use gethostbyname2().
599	 * always deep copy for simplification.
600	 */
601	for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
602		;
603	naddrs++;
604	aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
605	apbuf = (char *)malloc(hp->h_length * naddrs);
606	if (aplist == NULL || apbuf == NULL) {
607		error = EAI_MEMORY;
608		goto free;
609	}
610	memset(aplist, 0, sizeof(aplist[0]) * naddrs);
611	for (i = 0; i < naddrs; i++) {
612		if (hp->h_addr_list[i] == NULL) {
613			aplist[i] = NULL;
614			continue;
615		}
616		memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
617			hp->h_length);
618		aplist[i] = &apbuf[i * hp->h_length];
619	}
620#endif
621
622	for (i = 0; aplist[i] != NULL; i++) {
623		af = hp->h_addrtype;
624		ap = aplist[i];
625#ifdef AF_INET6
626		if (af == AF_INET6
627		 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
628			af = AF_INET;
629			ap = ap + sizeof(struct in6_addr)
630				- sizeof(struct in_addr);
631		}
632#endif
633
634		if (af != pai->ai_family)
635			continue;
636
637		if ((pai->ai_flags & AI_CANONNAME) == 0) {
638			GET_AI(cur->ai_next, afd, ap);
639			GET_PORT(cur->ai_next, servname);
640		} else {
641			/*
642			 * if AI_CANONNAME and if reverse lookup
643			 * fail, return ai anyway to pacify
644			 * calling application.
645			 *
646			 * XXX getaddrinfo() is a name->address
647			 * translation function, and it looks
648			 * strange that we do addr->name
649			 * translation here.
650			 */
651			get_name(ap, afd, &cur->ai_next,
652				ap, pai, servname);
653		}
654
655		while (cur && cur->ai_next)
656			cur = cur->ai_next;
657	}
658
659	*res = sentinel.ai_next;
660	return 0;
661
662free:
663#ifdef USE_GETIPNODEBY
664	if (hp)
665		freehostent(hp);
666#endif
667	if (aplist)
668		free(aplist);
669	if (apbuf)
670		free(apbuf);
671	if (sentinel.ai_next)
672		freeaddrinfo(sentinel.ai_next);
673	return error;
674}
675
676/*
677 * hostname == NULL.
678 * passive socket -> anyaddr (0.0.0.0 or ::)
679 * non-passive socket -> localhost (127.0.0.1 or ::1)
680 */
681static int
682explore_null(pai, hostname, servname, res)
683	const struct addrinfo *pai;
684	const char *hostname;
685	const char *servname;
686	struct addrinfo **res;
687{
688	int s;
689	const struct afd *afd;
690	struct addrinfo *cur;
691	struct addrinfo sentinel;
692	int error;
693
694	*res = NULL;
695	sentinel.ai_next = NULL;
696	cur = &sentinel;
697
698	/*
699	 * filter out AFs that are not supported by the kernel
700	 * XXX errno?
701	 */
702	s = socket(pai->ai_family, SOCK_DGRAM, 0);
703	if (s < 0) {
704		if (errno != EMFILE)
705			return 0;
706	} else
707		close(s);
708
709	/*
710	 * if the servname does not match socktype/protocol, ignore it.
711	 */
712	if (get_portmatch(pai, servname) != 0)
713		return 0;
714
715	afd = find_afd(pai->ai_family);
716
717	if (pai->ai_flags & AI_PASSIVE) {
718		GET_AI(cur->ai_next, afd, afd->a_addrany);
719		/* xxx meaningless?
720		 * GET_CANONNAME(cur->ai_next, "anyaddr");
721		 */
722		GET_PORT(cur->ai_next, servname);
723	} else {
724		GET_AI(cur->ai_next, afd, afd->a_loopback);
725		/* xxx meaningless?
726		 * GET_CANONNAME(cur->ai_next, "localhost");
727		 */
728		GET_PORT(cur->ai_next, servname);
729	}
730	cur = cur->ai_next;
731
732	*res = sentinel.ai_next;
733	return 0;
734
735free:
736	if (sentinel.ai_next)
737		freeaddrinfo(sentinel.ai_next);
738	return error;
739}
740
741/*
742 * numeric hostname
743 */
744static int
745explore_numeric(pai, hostname, servname, res)
746	const struct addrinfo *pai;
747	const char *hostname;
748	const char *servname;
749	struct addrinfo **res;
750{
751	const struct afd *afd;
752	struct addrinfo *cur;
753	struct addrinfo sentinel;
754	int error;
755	char pton[PTON_MAX];
756	int flags;
757
758	*res = NULL;
759	sentinel.ai_next = NULL;
760	cur = &sentinel;
761
762	/*
763	 * if the servname does not match socktype/protocol, ignore it.
764	 */
765	if (get_portmatch(pai, servname) != 0)
766		return 0;
767
768	afd = find_afd(pai->ai_family);
769	flags = pai->ai_flags;
770
771	if (inet_pton(afd->a_af, hostname, pton) == 1) {
772		u_int32_t v4a;
773#ifdef INET6
774		u_char pfx;
775#endif
776
777		switch (afd->a_af) {
778		case AF_INET:
779			v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
780			if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
781				flags &= ~AI_CANONNAME;
782			v4a >>= IN_CLASSA_NSHIFT;
783			if (v4a == 0 || v4a == IN_LOOPBACKNET)
784				flags &= ~AI_CANONNAME;
785			break;
786#ifdef INET6
787		case AF_INET6:
788			pfx = ((struct in6_addr *)pton)->s6_addr[0];
789			if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
790				flags &= ~AI_CANONNAME;
791			break;
792#endif
793		}
794
795		if (pai->ai_family == afd->a_af ||
796		    pai->ai_family == PF_UNSPEC /*?*/) {
797			if ((flags & AI_CANONNAME) == 0) {
798				GET_AI(cur->ai_next, afd, pton);
799				GET_PORT(cur->ai_next, servname);
800			} else {
801				/*
802				 * if AI_CANONNAME and if reverse lookup
803				 * fail, return ai anyway to pacify
804				 * calling application.
805				 *
806				 * XXX getaddrinfo() is a name->address
807				 * translation function, and it looks
808				 * strange that we do addr->name
809				 * translation here.
810				 */
811				get_name(pton, afd, &cur->ai_next,
812					pton, pai, servname);
813			}
814			while (cur && cur->ai_next)
815				cur = cur->ai_next;
816		} else
817			ERR(EAI_FAMILY);	/*xxx*/
818	}
819
820	*res = sentinel.ai_next;
821	return 0;
822
823free:
824bad:
825	if (sentinel.ai_next)
826		freeaddrinfo(sentinel.ai_next);
827	return error;
828}
829
830/*
831 * numeric hostname with scope
832 */
833static int
834explore_numeric_scope(pai, hostname, servname, res)
835	const struct addrinfo *pai;
836	const char *hostname;
837	const char *servname;
838	struct addrinfo **res;
839{
840#ifndef SCOPE_DELIMITER
841	return explore_numeric(pai, hostname, servname, res);
842#else
843	const struct afd *afd;
844	struct addrinfo *cur;
845	int error;
846	char *cp, *hostname2 = NULL;
847	int scope;
848	struct sockaddr_in6 *sin6;
849
850	/*
851	 * if the servname does not match socktype/protocol, ignore it.
852	 */
853	if (get_portmatch(pai, servname) != 0)
854		return 0;
855
856	afd = find_afd(pai->ai_family);
857	if (!afd->a_scoped)
858		return explore_numeric(pai, hostname, servname, res);
859
860	cp = strchr(hostname, SCOPE_DELIMITER);
861	if (cp == NULL)
862		return explore_numeric(pai, hostname, servname, res);
863
864	/*
865	 * Handle special case of <scoped_address><delimiter><scope id>
866	 */
867	hostname2 = strdup(hostname);
868	if (hostname2 == NULL)
869		return EAI_MEMORY;
870	/* terminate at the delimiter */
871	hostname2[cp - hostname] = '\0';
872
873	cp++;
874	switch (pai->ai_family) {
875#ifdef INET6
876	case AF_INET6:
877		scope = if_nametoindex(cp);
878		if (scope == 0) {
879			free(hostname2);
880			return (EAI_NONAME);
881		}
882		break;
883#endif
884	}
885
886	error = explore_numeric(pai, hostname2, servname, res);
887	if (error == 0) {
888		for (cur = *res; cur; cur = cur->ai_next) {
889			if (cur->ai_family != AF_INET6)
890				continue;
891			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
892			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
893			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
894				sin6->sin6_scope_id = scope;
895		}
896	}
897
898	free(hostname2);
899
900	return error;
901#endif
902}
903
904static int
905get_name(addr, afd, res, numaddr, pai, servname)
906	const char *addr;
907	const struct afd *afd;
908	struct addrinfo **res;
909	char *numaddr;
910	const struct addrinfo *pai;
911	const char *servname;
912{
913	struct hostent *hp = NULL;
914	struct addrinfo *cur = NULL;
915	int error = 0;
916	char *ap = NULL, *cn = NULL;
917#ifdef USE_GETIPNODEBY
918	int h_error;
919
920	hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
921#else
922	hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
923#endif
924	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
925#ifdef USE_GETIPNODEBY
926		GET_AI(cur, afd, hp->h_addr_list[0]);
927		GET_PORT(cur, servname);
928		GET_CANONNAME(cur, hp->h_name);
929#else
930		/* hp will be damaged if we use gethostbyaddr() */
931		if ((ap = (char *)malloc(hp->h_length)) == NULL) {
932			error = EAI_MEMORY;
933			goto free;
934		}
935		memcpy(ap, hp->h_addr_list[0], hp->h_length);
936		if ((cn = strdup(hp->h_name)) == NULL) {
937			error = EAI_MEMORY;
938			goto free;
939		}
940
941		GET_AI(cur, afd, ap);
942		GET_PORT(cur, servname);
943		GET_CANONNAME(cur, cn);
944		free(ap); ap = NULL;
945		free(cn); cn = NULL;
946#endif
947	} else {
948		GET_AI(cur, afd, numaddr);
949		GET_PORT(cur, servname);
950	}
951
952#ifdef USE_GETIPNODEBY
953	if (hp)
954		freehostent(hp);
955#endif
956	*res = cur;
957	return SUCCESS;
958 free:
959	if (cur)
960		freeaddrinfo(cur);
961	if (ap)
962		free(ap);
963	if (cn)
964		free(cn);
965#ifdef USE_GETIPNODEBY
966	if (hp)
967		freehostent(hp);
968#endif
969	*res = NULL;
970	return error;
971}
972
973static int
974get_canonname(pai, ai, str)
975	const struct addrinfo *pai;
976	struct addrinfo *ai;
977	const char *str;
978{
979	if ((pai->ai_flags & AI_CANONNAME) != 0) {
980		ai->ai_canonname = (char *)malloc(strlen(str) + 1);
981		if (ai->ai_canonname == NULL)
982			return EAI_MEMORY;
983		strcpy(ai->ai_canonname, str);
984	}
985	return 0;
986}
987
988static struct addrinfo *
989get_ai(pai, afd, addr)
990	const struct addrinfo *pai;
991	const struct afd *afd;
992	const char *addr;
993{
994	char *p;
995	struct addrinfo *ai;
996
997	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
998		+ (afd->a_socklen));
999	if (ai == NULL)
1000		return NULL;
1001
1002	memcpy(ai, pai, sizeof(struct addrinfo));
1003	ai->ai_addr = (struct sockaddr *)(ai + 1);
1004	memset(ai->ai_addr, 0, afd->a_socklen);
1005#ifdef HAVE_SOCKADDR_SA_LEN
1006	ai->ai_addr->sa_len = afd->a_socklen;
1007#endif
1008	ai->ai_addrlen = afd->a_socklen;
1009	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1010	p = (char *)(ai->ai_addr);
1011	memcpy(p + afd->a_off, addr, afd->a_addrlen);
1012	return ai;
1013}
1014
1015static int
1016get_portmatch(ai, servname)
1017	const struct addrinfo *ai;
1018	const char *servname;
1019{
1020
1021	/* get_port does not touch first argument. when matchonly == 1. */
1022	return get_port((struct addrinfo *)ai, servname, 1);
1023}
1024
1025static int
1026get_port(ai, servname, matchonly)
1027	struct addrinfo *ai;
1028	const char *servname;
1029	int matchonly;
1030{
1031	const char *proto;
1032	struct servent *sp;
1033	int port;
1034	int allownumeric;
1035
1036	if (servname == NULL)
1037		return 0;
1038	switch (ai->ai_family) {
1039	case AF_INET:
1040#ifdef AF_INET6
1041	case AF_INET6:
1042#endif
1043		break;
1044	default:
1045		return 0;
1046	}
1047
1048	switch (ai->ai_socktype) {
1049	case SOCK_RAW:
1050		return EAI_SERVICE;
1051	case SOCK_DGRAM:
1052	case SOCK_STREAM:
1053		allownumeric = 1;
1054		break;
1055	case ANY:
1056		allownumeric = 0;
1057		break;
1058	default:
1059		return EAI_SOCKTYPE;
1060	}
1061
1062	if (str_isnumber(servname)) {
1063		if (!allownumeric)
1064			return EAI_SERVICE;
1065		port = htons(atoi(servname));
1066		if (port < 0 || port > 65535)
1067			return EAI_SERVICE;
1068	} else {
1069		switch (ai->ai_socktype) {
1070		case SOCK_DGRAM:
1071			proto = "udp";
1072			break;
1073		case SOCK_STREAM:
1074			proto = "tcp";
1075			break;
1076		default:
1077			proto = NULL;
1078			break;
1079		}
1080
1081		if ((sp = getservbyname(servname, proto)) == NULL)
1082			return EAI_SERVICE;
1083		port = sp->s_port;
1084	}
1085
1086	if (!matchonly) {
1087		switch (ai->ai_family) {
1088		case AF_INET:
1089			((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
1090			break;
1091#ifdef INET6
1092		case AF_INET6:
1093			((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
1094			break;
1095#endif
1096		}
1097	}
1098
1099	return 0;
1100}
1101
1102static const struct afd *
1103find_afd(af)
1104	int af;
1105{
1106	const struct afd *afd;
1107
1108	if (af == PF_UNSPEC)
1109		return NULL;
1110	for (afd = afdl; afd->a_af; afd++) {
1111		if (afd->a_af == af)
1112			return afd;
1113	}
1114	return NULL;
1115}
1116