xref: /netbsd-src/lib/libc/net/getaddrinfo.c (revision 95d875fb90b1458e4f1de6950286ddcd6644bc61)
1 /*	$NetBSD: getaddrinfo.c,v 1.17 1999/12/27 10:20:59 itojun Exp $	*/
2 
3 /*
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
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 resolving FQDNs and globbing NULL hostname.  Is it the right
46  *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
47  *   in ai_flags?
48  */
49 
50 #if 0
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54 #else
55 #define HAVE_SOCKADDR_SA_LEN
56 #endif
57 
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #if 0
61 #include <sys/sysctl.h>
62 #endif
63 #include <sys/socket.h>
64 #include <net/if.h>
65 #include <netinet/in.h>
66 #include <arpa/inet.h>
67 #include <arpa/nameser.h>
68 #include <netdb.h>
69 #include <resolv.h>
70 #include <string.h>
71 #include <stdlib.h>
72 #include <stddef.h>
73 #include <ctype.h>
74 #include <unistd.h>
75 #include <stdio.h>
76 #include <errno.h>
77 
78 #if 0
79 #ifndef HAVE_PORTABLE_PROTOTYPE
80 #include "cdecl_ext.h"
81 #endif
82 
83 #ifndef HAVE_U_INT32_T
84 #include "bittypes.h"
85 #endif
86 
87 #ifndef HAVE_SOCKADDR_STORAGE
88 #include "sockstorage.h"
89 #endif
90 
91 #ifndef HAVE_ADDRINFO
92 #include "addrinfo.h"
93 #endif
94 
95 #if defined(__KAME__) && defined(INET6)
96 # define FAITH
97 #endif
98 #endif
99 
100 #define SUCCESS 0
101 #define ANY 0
102 #define YES 1
103 #define NO  0
104 
105 #ifdef FAITH
106 static int translate = NO;
107 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
108 #endif
109 
110 static const char in_addrany[] = { 0, 0, 0, 0 };
111 static const char in6_addrany[] = {
112 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
113 };
114 static const char in_loopback[] = { 127, 0, 0, 1 };
115 static const char in6_loopback[] = {
116 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
117 };
118 
119 struct sockinet {
120 	u_char	si_len;
121 	u_char	si_family;
122 	u_short	si_port;
123 	u_int32_t si_scope_id;
124 };
125 
126 static const struct afd {
127 	int a_af;
128 	int a_addrlen;
129 	int a_socklen;
130 	int a_off;
131 	const char *a_addrany;
132 	const char *a_loopback;
133 	int a_scoped;
134 } afdl [] = {
135 #ifdef INET6
136 	{PF_INET6, sizeof(struct in6_addr),
137 	 sizeof(struct sockaddr_in6),
138 	 offsetof(struct sockaddr_in6, sin6_addr),
139 	 in6_addrany, in6_loopback, 1},
140 #endif
141 	{PF_INET, sizeof(struct in_addr),
142 	 sizeof(struct sockaddr_in),
143 	 offsetof(struct sockaddr_in, sin_addr),
144 	 in_addrany, in_loopback, 0},
145 	{0, 0, 0, 0, NULL, NULL, 0},
146 };
147 
148 struct explore {
149 	int e_af;
150 	int e_socktype;
151 	int e_protocol;
152 	const char *e_protostr;
153 	int e_wild;
154 #define WILD_AF(ex)		((ex)->e_wild & 0x01)
155 #define WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
156 #define WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
157 };
158 
159 static const struct explore explore[] = {
160 #if 0
161 	{ PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
162 #endif
163 #ifdef INET6
164 	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
165 	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
166 	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
167 #endif
168 	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
169 	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
170 	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
171 	{ -1, 0, 0, NULL, 0 },
172 };
173 
174 #ifdef INET6
175 #define PTON_MAX	16
176 #else
177 #define PTON_MAX	4
178 #endif
179 
180 
181 static int str_isnumber __P((const char *));
182 static int explore_fqdn __P((const struct addrinfo *, const char *,
183 	const char *, struct addrinfo **));
184 static int explore_null __P((const struct addrinfo *, const char *,
185 	const char *, struct addrinfo **));
186 static int explore_numeric __P((const struct addrinfo *, const char *,
187 	const char *, struct addrinfo **));
188 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
189 	const char *, struct addrinfo **));
190 static int get_name __P((const char *, const struct afd *, struct addrinfo **,
191 	char *, const struct addrinfo *, const char *));
192 static int get_canonname __P((const struct addrinfo *,
193 	struct addrinfo *, const char *));
194 static struct addrinfo *get_ai __P((const struct addrinfo *,
195 	const struct afd *, const char *));
196 static int get_portmatch __P((const struct addrinfo *, const char *));
197 static int get_port __P((struct addrinfo *, const char *, int));
198 static const struct afd *find_afd __P((int));
199 
200 static char *ai_errlist[] = {
201 	"Success",
202 	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
203 	"Temporary failure in name resolution",		/* EAI_AGAIN      */
204 	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
205 	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
206 	"ai_family not supported",			/* EAI_FAMILY     */
207 	"Memory allocation failure", 			/* EAI_MEMORY     */
208 	"No address associated with hostname", 		/* EAI_NODATA     */
209 	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
210 	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
211 	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
212 	"System error returned in errno", 		/* EAI_SYSTEM     */
213 	"Invalid value for hints",			/* EAI_BADHINTS	  */
214 	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
215 	"Unknown error", 				/* EAI_MAX        */
216 };
217 
218 /* XXX macros that make external reference is BAD. */
219 
220 #define GET_AI(ai, afd, addr) \
221 do { \
222 	/* external reference: pai, error, and label free */ \
223 	(ai) = get_ai(pai, (afd), (addr)); \
224 	if ((ai) == NULL) { \
225 		error = EAI_MEMORY; \
226 		goto free; \
227 	} \
228 } while (0)
229 
230 #define GET_PORT(ai, serv) \
231 do { \
232 	/* external reference: error and label free */ \
233 	error = get_port((ai), (serv), 0); \
234 	if (error != 0) \
235 		goto free; \
236 } while (0)
237 
238 #define GET_CANONNAME(ai, str) \
239 do { \
240 	/* external reference: pai, error and label free */ \
241 	error = get_canonname(pai, (ai), (str)); \
242 	if (error != 0) \
243 		goto free; \
244 } while (0)
245 
246 #define ERR(err) \
247 do { \
248 	/* external reference: error, and label bad */ \
249 	error = (err); \
250 	goto bad; \
251 } while (0)
252 
253 #define MATCH_FAMILY(x, y, w) \
254 	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
255 #define MATCH(x, y, w) \
256 	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
257 
258 char *
259 gai_strerror(ecode)
260 	int ecode;
261 {
262 	if (ecode < 0 || ecode > EAI_MAX)
263 		ecode = EAI_MAX;
264 	return ai_errlist[ecode];
265 }
266 
267 void
268 freeaddrinfo(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 
282 static int
283 str_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 
295 int
296 getaddrinfo(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 	 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)) {
382 		ai0 = *pai;
383 
384 		if (pai->ai_family == PF_UNSPEC)
385 			pai->ai_family = PF_INET6;
386 		error = get_portmatch(pai, servname);
387 		if (error)
388 			ERR(error);
389 
390 		*pai = ai0;
391 	}
392 
393 	ai0 = *pai;
394 
395 	/* NULL hostname, or numeric hostname */
396 	for (ex = explore; ex->e_af >= 0; ex++) {
397 		*pai = ai0;
398 
399 		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
400 			continue;
401 		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
402 			continue;
403 		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
404 			continue;
405 
406 		if (pai->ai_family == PF_UNSPEC)
407 			pai->ai_family = ex->e_af;
408 		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
409 			pai->ai_socktype = ex->e_socktype;
410 		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
411 			pai->ai_protocol = ex->e_protocol;
412 
413 		if (hostname == NULL)
414 			error = explore_null(pai, hostname, servname, &cur->ai_next);
415 		else
416 			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
417 
418 		if (error)
419 			goto free;
420 
421 		while (cur && cur->ai_next)
422 			cur = cur->ai_next;
423 	}
424 
425 	/*
426 	 * XXX
427 	 * If numreic representation of AF1 can be interpreted as FQDN
428 	 * representation of AF2, we need to think again about the code below.
429 	 */
430 	if (sentinel.ai_next)
431 		goto good;
432 
433 	if (pai->ai_flags & AI_NUMERICHOST)
434 		ERR(EAI_NONAME);
435 	if (hostname == NULL)
436 		ERR(EAI_NONAME);
437 
438 	/*
439 	 * hostname as alphabetical name.
440 	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
441 	 * outer loop by AFs.
442 	 */
443 	for (afd = afdl; afd->a_af; afd++) {
444 		*pai = ai0;
445 
446 		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
447 			continue;
448 
449 		for (ex = explore; ex->e_af >= 0; ex++) {
450 			*pai = ai0;
451 
452 			if (pai->ai_family == PF_UNSPEC)
453 				pai->ai_family = afd->a_af;
454 
455 			if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
456 				continue;
457 			if (!MATCH(pai->ai_socktype, ex->e_socktype,
458 					WILD_SOCKTYPE(ex))) {
459 				continue;
460 			}
461 			if (!MATCH(pai->ai_protocol, ex->e_protocol,
462 					WILD_PROTOCOL(ex))) {
463 				continue;
464 			}
465 
466 			if (pai->ai_family == PF_UNSPEC)
467 				pai->ai_family = ex->e_af;
468 			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
469 				pai->ai_socktype = ex->e_socktype;
470 			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
471 				pai->ai_protocol = ex->e_protocol;
472 
473 			error = explore_fqdn(pai, hostname, servname,
474 				&cur->ai_next);
475 
476 			while (cur && cur->ai_next)
477 				cur = cur->ai_next;
478 		}
479 	}
480 
481 	/* XXX */
482 	if (sentinel.ai_next)
483 		error = 0;
484 
485 	if (error)
486 		goto free;
487 	if (error == 0) {
488 		if (sentinel.ai_next) {
489  good:
490 			*res = sentinel.ai_next;
491 			return SUCCESS;
492 		} else
493 			error = EAI_FAIL;
494 	}
495  free:
496  bad:
497 	if (sentinel.ai_next)
498 		freeaddrinfo(sentinel.ai_next);
499 	*res = NULL;
500 	return error;
501 }
502 
503 /*
504  * FQDN hostname, DNS lookup
505  */
506 static int
507 explore_fqdn(pai, hostname, servname, res)
508 	const struct addrinfo *pai;
509 	const char *hostname;
510 	const char *servname;
511 	struct addrinfo **res;
512 {
513 	int s;
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 	 * filter out AFs that are not supported by the kernel
533 	 * XXX errno?
534 	 */
535 	s = socket(pai->ai_family, SOCK_DGRAM, 0);
536 	if (s < 0) {
537 		if (errno != EMFILE)
538 			return 0;
539 	} else
540 		close(s);
541 
542 	/*
543 	 * if the servname does not match socktype/protocol, ignore it.
544 	 */
545 	if (get_portmatch(pai, servname) != 0)
546 		return 0;
547 
548 	afd = find_afd(pai->ai_family);
549 
550 	/*
551 	 * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
552 	 * rather than hardcoding it.  we may need to add AI_ADDRCONFIG
553 	 * handling code by ourselves in case we don't have getipnodebyname().
554 	 */
555 #ifdef USE_GETIPNODEBY
556 	hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
557 #else
558 	hp = gethostbyname2(hostname, pai->ai_family);
559 	h_error = h_errno;
560 #endif
561 
562 	if (hp == NULL) {
563 		switch (h_error) {
564 		case HOST_NOT_FOUND:
565 		case NO_DATA:
566 			error = EAI_NODATA;
567 			break;
568 		case TRY_AGAIN:
569 			error = EAI_AGAIN;
570 			break;
571 		case NO_RECOVERY:
572 		case NETDB_INTERNAL:
573 		default:
574 			error = EAI_FAIL;
575 			break;
576 		}
577 	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
578 			|| (hp->h_addr_list[0] == NULL)) {
579 #ifdef USE_GETIPNODEBY
580 		freehostent(hp);
581 #endif
582 		hp = NULL;
583 		error = EAI_FAIL;
584 	}
585 
586 	if (hp == NULL)
587 		goto free;
588 
589 #ifdef USE_GETIPNODEBY
590 	aplist = hp->h_addr_list;
591 #else
592 	/*
593 	 * hp will be overwritten if we use gethostbyname2().
594 	 * always deep copy for simplification.
595 	 */
596 	for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
597 		;
598 	naddrs++;
599 	aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
600 	apbuf = (char *)malloc(hp->h_length * naddrs);
601 	if (aplist == NULL || apbuf == NULL) {
602 		error = EAI_MEMORY;
603 		goto free;
604 	}
605 	memset(aplist, 0, sizeof(aplist[0]) * naddrs);
606 	for (i = 0; i < naddrs; i++) {
607 		if (hp->h_addr_list[i] == NULL) {
608 			aplist[i] = NULL;
609 			continue;
610 		}
611 		memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
612 			hp->h_length);
613 		aplist[i] = &apbuf[i * hp->h_length];
614 	}
615 #endif
616 
617 	for (i = 0; aplist[i] != NULL; i++) {
618 		af = hp->h_addrtype;
619 		ap = aplist[i];
620 		if (af == AF_INET6
621 		 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
622 			af = AF_INET;
623 			ap = ap + sizeof(struct in6_addr)
624 				- sizeof(struct in_addr);
625 		}
626 
627 		if (af != pai->ai_family)
628 			continue;
629 
630 		if ((pai->ai_flags & AI_CANONNAME) == 0) {
631 			GET_AI(cur->ai_next, afd, ap);
632 			GET_PORT(cur->ai_next, servname);
633 		} else {
634 			/*
635 			 * if AI_CANONNAME and if reverse lookup
636 			 * fail, return ai anyway to pacify
637 			 * calling application.
638 			 *
639 			 * XXX getaddrinfo() is a name->address
640 			 * translation function, and it looks
641 			 * strange that we do addr->name
642 			 * translation here.
643 			 */
644 			get_name(ap, afd, &cur->ai_next,
645 				ap, pai, servname);
646 		}
647 
648 		while (cur && cur->ai_next)
649 			cur = cur->ai_next;
650 	}
651 
652 	*res = sentinel.ai_next;
653 	return 0;
654 
655 free:
656 #ifdef USE_GETIPNODEBY
657 	if (hp)
658 		freehostent(hp);
659 #endif
660 	if (aplist)
661 		free(aplist);
662 	if (apbuf)
663 		free(apbuf);
664 	if (sentinel.ai_next)
665 		freeaddrinfo(sentinel.ai_next);
666 	return error;
667 }
668 
669 /*
670  * hostname == NULL.
671  * passive socket -> anyaddr (0.0.0.0 or ::)
672  * non-passive socket -> localhost (127.0.0.1 or ::1)
673  */
674 static int
675 explore_null(pai, hostname, servname, res)
676 	const struct addrinfo *pai;
677 	const char *hostname;
678 	const char *servname;
679 	struct addrinfo **res;
680 {
681 	int s;
682 	const struct afd *afd;
683 	struct addrinfo *cur;
684 	struct addrinfo sentinel;
685 	int error;
686 
687 	*res = NULL;
688 	sentinel.ai_next = NULL;
689 	cur = &sentinel;
690 
691 	/*
692 	 * filter out AFs that are not supported by the kernel
693 	 * XXX errno?
694 	 */
695 	s = socket(pai->ai_family, SOCK_DGRAM, 0);
696 	if (s < 0) {
697 		if (errno != EMFILE)
698 			return 0;
699 	} else
700 		close(s);
701 
702 	/*
703 	 * if the servname does not match socktype/protocol, ignore it.
704 	 */
705 	if (get_portmatch(pai, servname) != 0)
706 		return 0;
707 
708 	afd = find_afd(pai->ai_family);
709 
710 	if (pai->ai_flags & AI_PASSIVE) {
711 		GET_AI(cur->ai_next, afd, afd->a_addrany);
712 		/* xxx meaningless?
713 		 * GET_CANONNAME(cur->ai_next, "anyaddr");
714 		 */
715 		GET_PORT(cur->ai_next, servname);
716 	} else {
717 		GET_AI(cur->ai_next, afd, afd->a_loopback);
718 		/* xxx meaningless?
719 		 * GET_CANONNAME(cur->ai_next, "localhost");
720 		 */
721 		GET_PORT(cur->ai_next, servname);
722 	}
723 	cur = cur->ai_next;
724 
725 	*res = sentinel.ai_next;
726 	return 0;
727 
728 free:
729 	if (sentinel.ai_next)
730 		freeaddrinfo(sentinel.ai_next);
731 	return error;
732 }
733 
734 /*
735  * numeric hostname
736  */
737 static int
738 explore_numeric(pai, hostname, servname, res)
739 	const struct addrinfo *pai;
740 	const char *hostname;
741 	const char *servname;
742 	struct addrinfo **res;
743 {
744 	const struct afd *afd;
745 	struct addrinfo *cur;
746 	struct addrinfo sentinel;
747 	int error;
748 	char pton[PTON_MAX];
749 	int flags;
750 
751 	*res = NULL;
752 	sentinel.ai_next = NULL;
753 	cur = &sentinel;
754 
755 	/*
756 	 * if the servname does not match socktype/protocol, ignore it.
757 	 */
758 	if (get_portmatch(pai, servname) != 0)
759 		return 0;
760 
761 	afd = find_afd(pai->ai_family);
762 	flags = pai->ai_flags;
763 
764 	if (inet_pton(afd->a_af, hostname, pton) == 1) {
765 		u_int32_t v4a;
766 #ifdef INET6
767 		u_char pfx;
768 #endif
769 
770 		switch (afd->a_af) {
771 		case AF_INET:
772 			v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
773 			if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
774 				flags &= ~AI_CANONNAME;
775 			v4a >>= IN_CLASSA_NSHIFT;
776 			if (v4a == 0 || v4a == IN_LOOPBACKNET)
777 				flags &= ~AI_CANONNAME;
778 			break;
779 #ifdef INET6
780 		case AF_INET6:
781 			pfx = ((struct in6_addr *)pton)->s6_addr[0];
782 			if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
783 				flags &= ~AI_CANONNAME;
784 			break;
785 #endif
786 		}
787 
788 		if (pai->ai_family == afd->a_af ||
789 		    pai->ai_family == PF_UNSPEC /*?*/) {
790 			if ((flags & AI_CANONNAME) == 0) {
791 				GET_AI(cur->ai_next, afd, pton);
792 				GET_PORT(cur->ai_next, servname);
793 			} else {
794 				/*
795 				 * if AI_CANONNAME and if reverse lookup
796 				 * fail, return ai anyway to pacify
797 				 * calling application.
798 				 *
799 				 * XXX getaddrinfo() is a name->address
800 				 * translation function, and it looks
801 				 * strange that we do addr->name
802 				 * translation here.
803 				 */
804 				get_name(pton, afd, &cur->ai_next,
805 					pton, pai, servname);
806 			}
807 			while (cur && cur->ai_next)
808 				cur = cur->ai_next;
809 		} else
810 			ERR(EAI_FAMILY);	/*xxx*/
811 	}
812 
813 	*res = sentinel.ai_next;
814 	return 0;
815 
816 free:
817 bad:
818 	if (sentinel.ai_next)
819 		freeaddrinfo(sentinel.ai_next);
820 	return error;
821 }
822 
823 /*
824  * numeric hostname with scope
825  */
826 static int
827 explore_numeric_scope(pai, hostname, servname, res)
828 	const struct addrinfo *pai;
829 	const char *hostname;
830 	const char *servname;
831 	struct addrinfo **res;
832 {
833 #ifndef SCOPE_DELIMITER
834 	return explore_numeric(pai, hostname, servname, res);
835 #else
836 	const struct afd *afd;
837 	struct addrinfo *cur;
838 	int error;
839 	char *cp, *hostname2 = NULL;
840 	int scope;
841 	struct sockaddr_in6 *sin6;
842 
843 	/*
844 	 * if the servname does not match socktype/protocol, ignore it.
845 	 */
846 	if (get_portmatch(pai, servname) != 0)
847 		return 0;
848 
849 	afd = find_afd(pai->ai_family);
850 	if (!afd->a_scoped)
851 		return explore_numeric(pai, hostname, servname, res);
852 
853 	cp = strchr(hostname, SCOPE_DELIMITER);
854 	if (cp == NULL)
855 		return explore_numeric(pai, hostname, servname, res);
856 
857 	/*
858 	 * Handle special case of <scoped_address><delimiter><scope id>
859 	 */
860 	hostname2 = strdup(hostname);
861 	if (hostname2 == NULL)
862 		return EAI_MEMORY;
863 	/* terminate at the delimiter */
864 	hostname2[cp - hostname] = '\0';
865 
866 	cp++;
867 	switch (pai->ai_family) {
868 #ifdef INET6
869 	case AF_INET6:
870 		scope = if_nametoindex(cp);
871 		if (scope == 0) {
872 			free(hostname2);
873 			return (EAI_NONAME);
874 		}
875 		break;
876 #endif
877 	}
878 
879 	error = explore_numeric(pai, hostname2, servname, res);
880 	if (error == 0) {
881 		for (cur = *res; cur; cur = cur->ai_next) {
882 			if (cur->ai_family != AF_INET6)
883 				continue;
884 			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
885 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
886 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
887 				sin6->sin6_scope_id = scope;
888 		}
889 	}
890 
891 	free(hostname2);
892 
893 	return error;
894 #endif
895 }
896 
897 static int
898 get_name(addr, afd, res, numaddr, pai, servname)
899 	const char *addr;
900 	const struct afd *afd;
901 	struct addrinfo **res;
902 	char *numaddr;
903 	const struct addrinfo *pai;
904 	const char *servname;
905 {
906 	struct hostent *hp = NULL;
907 	struct addrinfo *cur = NULL;
908 	int error = 0;
909 	char *ap = NULL, *cn = NULL;
910 #ifdef USE_GETIPNODEBY
911 	int h_error;
912 
913 	hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
914 #else
915 	hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
916 #endif
917 	if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
918 #ifdef USE_GETIPNODEBY
919 		GET_AI(cur, afd, hp->h_addr_list[0]);
920 		GET_PORT(cur, servname);
921 		GET_CANONNAME(cur, hp->h_name);
922 #else
923 		/* hp will be damaged if we use gethostbyaddr() */
924 		if ((ap = (char *)malloc(hp->h_length)) == NULL) {
925 			error = EAI_MEMORY;
926 			goto free;
927 		}
928 		memcpy(ap, hp->h_addr_list[0], hp->h_length);
929 		if ((cn = strdup(hp->h_name)) == NULL) {
930 			error = EAI_MEMORY;
931 			goto free;
932 		}
933 
934 		GET_AI(cur, afd, ap);
935 		GET_PORT(cur, servname);
936 		GET_CANONNAME(cur, cn);
937 		free(ap); ap = NULL;
938 		free(cn); cn = NULL;
939 #endif
940 	} else {
941 		GET_AI(cur, afd, numaddr);
942 		GET_PORT(cur, servname);
943 	}
944 
945 #ifdef USE_GETIPNODEBY
946 	if (hp)
947 		freehostent(hp);
948 #endif
949 	*res = cur;
950 	return SUCCESS;
951  free:
952 	if (cur)
953 		freeaddrinfo(cur);
954 	if (ap)
955 		free(ap);
956 	if (cn)
957 		free(cn);
958 #ifdef USE_GETIPNODEBY
959 	if (hp)
960 		freehostent(hp);
961 #endif
962 	*res = NULL;
963 	return error;
964 }
965 
966 static int
967 get_canonname(pai, ai, str)
968 	const struct addrinfo *pai;
969 	struct addrinfo *ai;
970 	const char *str;
971 {
972 	if ((pai->ai_flags & AI_CANONNAME) != 0) {
973 		ai->ai_canonname = (char *)malloc(strlen(str) + 1);
974 		if (ai->ai_canonname == NULL)
975 			return EAI_MEMORY;
976 		strcpy(ai->ai_canonname, str);
977 	}
978 	return 0;
979 }
980 
981 static struct addrinfo *
982 get_ai(pai, afd, addr)
983 	const struct addrinfo *pai;
984 	const struct afd *afd;
985 	const char *addr;
986 {
987 	char *p;
988 	struct addrinfo *ai;
989 
990 	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
991 		+ (afd->a_socklen));
992 	if (ai == NULL)
993 		return NULL;
994 
995 	memcpy(ai, pai, sizeof(struct addrinfo));
996 	ai->ai_addr = (struct sockaddr *)(ai + 1);
997 	memset(ai->ai_addr, 0, afd->a_socklen);
998 #ifdef HAVE_SOCKADDR_SA_LEN
999 	ai->ai_addr->sa_len = afd->a_socklen;
1000 #endif
1001 	ai->ai_addrlen = afd->a_socklen;
1002 	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1003 	p = (char *)(ai->ai_addr);
1004 	memcpy(p + afd->a_off, addr, afd->a_addrlen);
1005 	return ai;
1006 }
1007 
1008 static int
1009 get_portmatch(ai, servname)
1010 	const struct addrinfo *ai;
1011 	const char *servname;
1012 {
1013 
1014 	/* get_port does not touch first argument. when matchonly == 1. */
1015 	return get_port((struct addrinfo *)ai, servname, 1);
1016 }
1017 
1018 static int
1019 get_port(ai, servname, matchonly)
1020 	struct addrinfo *ai;
1021 	const char *servname;
1022 	int matchonly;
1023 {
1024 	const char *proto;
1025 	struct servent *sp;
1026 	int port;
1027 	int allownumeric;
1028 
1029 	if (servname == NULL)
1030 		return 0;
1031 	if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
1032 		return 0;
1033 
1034 	switch (ai->ai_socktype) {
1035 	case SOCK_RAW:
1036 		return EAI_SERVICE;
1037 	case SOCK_DGRAM:
1038 	case SOCK_STREAM:
1039 		allownumeric = 1;
1040 		break;
1041 	case ANY:
1042 		allownumeric = 0;
1043 		break;
1044 	default:
1045 		return EAI_SOCKTYPE;
1046 	}
1047 
1048 	if (str_isnumber(servname)) {
1049 		if (!allownumeric)
1050 			return EAI_SERVICE;
1051 		port = htons(atoi(servname));
1052 		if (port < 0 || port > 65535)
1053 			return EAI_SERVICE;
1054 	} else {
1055 		switch (ai->ai_socktype) {
1056 		case SOCK_DGRAM:
1057 			proto = "udp";
1058 			break;
1059 		case SOCK_STREAM:
1060 			proto = "tcp";
1061 			break;
1062 		default:
1063 			proto = NULL;
1064 			break;
1065 		}
1066 
1067 		if ((sp = getservbyname(servname, proto)) == NULL)
1068 			return EAI_SERVICE;
1069 		port = sp->s_port;
1070 	}
1071 
1072 	if (!matchonly) {
1073 		switch (ai->ai_family) {
1074 		case AF_INET:
1075 			((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
1076 			break;
1077 #ifdef INET6
1078 		case AF_INET6:
1079 			((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
1080 			break;
1081 #endif
1082 		}
1083 	}
1084 
1085 	return 0;
1086 }
1087 
1088 static const struct afd *
1089 find_afd(af)
1090 	int af;
1091 {
1092 	const struct afd *afd;
1093 
1094 	if (af == PF_UNSPEC)
1095 		return NULL;
1096 	for (afd = afdl; afd->a_af; afd++) {
1097 		if (afd->a_af == af)
1098 			return afd;
1099 	}
1100 	return NULL;
1101 }
1102