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