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