xref: /freebsd/lib/libc/net/getaddrinfo.c (revision 807a5caa14df5ff04b331e24b45893f6a2f6bc1b)
1 /*
2  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
34  *
35  * Issues to be discussed:
36  * - Thread safe-ness must be checked.
37  * - Return values.  There are nonstandard return values defined and used
38  *   in the source code.  This is because RFC2553 is silent about which error
39  *   code must be returned for which situation.
40  * Note:
41  * - We use getipnodebyname() just for thread-safeness.  There's no intent
42  *   to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
43  *   getipnodebyname().
44  * - The code filters out AFs that are not supported by the kernel,
45  *   when globbing NULL hostname (to loopback, or wildcard).  Is it the right
46  *   thing to do?  What is the relationship with post-RFC2553 AI_ADDRCONFIG
47  *   in ai_flags?
48  */
49 
50 #include <sys/types.h>
51 #include <sys/param.h>
52 #include <sys/socket.h>
53 #include <net/if.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
56 #include <arpa/nameser.h>
57 #include <netdb.h>
58 #include <resolv.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <stddef.h>
62 #include <ctype.h>
63 #include <unistd.h>
64 #include <stdio.h>
65 
66 #if defined(__KAME__) && defined(INET6)
67 # define FAITH
68 #endif
69 
70 #define	SUCCESS 0
71 #define	ANY 0
72 #define	YES 1
73 #define	NO  0
74 
75 static const char in_addrany[] = { 0, 0, 0, 0 };
76 static const char in6_addrany[] = {
77 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
78 };
79 static const char in_loopback[] = { 127, 0, 0, 1 };
80 static const char in6_loopback[] = {
81 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
82 };
83 
84 static const struct afd {
85 	int a_af;
86 	int a_addrlen;
87 	int a_socklen;
88 	int a_off;
89 	const char *a_addrany;
90 	const char *a_loopback;
91 	int a_scoped;
92 } afdl [] = {
93 #ifdef INET6
94 #define	N_INET6 0
95 	{PF_INET6, sizeof(struct in6_addr),
96 	 sizeof(struct sockaddr_in6),
97 	 offsetof(struct sockaddr_in6, sin6_addr),
98 	 in6_addrany, in6_loopback, 1},
99 #define	N_INET 1
100 #else
101 #define	N_INET 0
102 #endif
103 	{PF_INET, sizeof(struct in_addr),
104 	 sizeof(struct sockaddr_in),
105 	 offsetof(struct sockaddr_in, sin_addr),
106 	 in_addrany, in_loopback, 0},
107 	{0, 0, 0, 0, NULL, NULL, 0},
108 };
109 
110 struct explore {
111 	int e_af;
112 	int e_socktype;
113 	int e_protocol;
114 	const char *e_protostr;
115 	int e_wild;
116 #define	WILD_AF(ex)		((ex)->e_wild & 0x01)
117 #define	WILD_SOCKTYPE(ex)	((ex)->e_wild & 0x02)
118 #define	WILD_PROTOCOL(ex)	((ex)->e_wild & 0x04)
119 };
120 
121 static const struct explore explore[] = {
122 #ifdef INET6
123 	{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
124 	{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
125 	{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
126 #endif
127 	{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
128 	{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
129 	{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
130 	{ -1, 0, 0, NULL, 0 },
131 };
132 
133 #ifdef INET6
134 #define	PTON_MAX	16
135 #else
136 #define	PTON_MAX	4
137 #endif
138 
139 
140 static int str_isnumber __P((const char *));
141 static int explore_fqdn __P((const struct addrinfo *, const char *,
142 	const char *, struct addrinfo **));
143 static int explore_null __P((const struct addrinfo *, const char *,
144 	const char *, struct addrinfo **));
145 static int explore_numeric __P((const struct addrinfo *, const char *,
146 	const char *, struct addrinfo **));
147 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
148 	const char *, struct addrinfo **));
149 static int get_canonname __P((const struct addrinfo *,
150 	struct addrinfo *, const char *));
151 static struct addrinfo *get_ai __P((const struct addrinfo *,
152 	const struct afd *, const char *));
153 static int get_portmatch __P((const struct addrinfo *, const char *));
154 static int get_port __P((struct addrinfo *, const char *, int));
155 static const struct afd *find_afd __P((int));
156 
157 static char *ai_errlist[] = {
158 	"Success",
159 	"Address family for hostname not supported",	/* EAI_ADDRFAMILY */
160 	"Temporary failure in name resolution",		/* EAI_AGAIN      */
161 	"Invalid value for ai_flags",		       	/* EAI_BADFLAGS   */
162 	"Non-recoverable failure in name resolution", 	/* EAI_FAIL       */
163 	"ai_family not supported",			/* EAI_FAMILY     */
164 	"Memory allocation failure", 			/* EAI_MEMORY     */
165 	"No address associated with hostname", 		/* EAI_NODATA     */
166 	"hostname nor servname provided, or not known",	/* EAI_NONAME     */
167 	"servname not supported for ai_socktype",	/* EAI_SERVICE    */
168 	"ai_socktype not supported", 			/* EAI_SOCKTYPE   */
169 	"System error returned in errno", 		/* EAI_SYSTEM     */
170 	"Invalid value for hints",			/* EAI_BADHINTS	  */
171 	"Resolved protocol is unknown",			/* EAI_PROTOCOL   */
172 	"Argument res is NULL",				/* EAI_RESNULL	  */
173 	"Unknown error", 				/* EAI_MAX        */
174 };
175 
176 /* XXX macros that make external reference is BAD. */
177 
178 #define	GET_AI(ai, afd, addr) \
179 do { \
180 	/* external reference: pai, error, and label free */ \
181 	(ai) = get_ai(pai, (afd), (addr)); \
182 	if ((ai) == NULL) { \
183 		error = EAI_MEMORY; \
184 		goto free; \
185 	} \
186 } while (0)
187 
188 #define	GET_PORT(ai, serv) \
189 do { \
190 	/* external reference: error and label free */ \
191 	error = get_port((ai), (serv), 0); \
192 	if (error != 0) \
193 		goto free; \
194 } while (0)
195 
196 #define	GET_CANONNAME(ai, str) \
197 do { \
198 	/* external reference: pai, error and label free */ \
199 	error = get_canonname(pai, (ai), (str)); \
200 	if (error != 0) \
201 		goto free; \
202 } while (0)
203 
204 #define	ERR(err) \
205 do { \
206 	/* external reference: error, and label bad */ \
207 	error = (err); \
208 	goto bad; \
209 } while (0)
210 
211 #define	MATCH_FAMILY(x, y, w) \
212 	((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
213 #define	MATCH(x, y, w) \
214 	((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
215 
216 char *
217 gai_strerror(ecode)
218 	int ecode;
219 {
220 	if (ecode < 0 || ecode > EAI_MAX)
221 		ecode = EAI_MAX;
222 	return ai_errlist[ecode];
223 }
224 
225 void
226 freeaddrinfo(ai)
227 	struct addrinfo *ai;
228 {
229 	struct addrinfo *next;
230 
231 	do {
232 		next = ai->ai_next;
233 		if (ai->ai_canonname)
234 			free(ai->ai_canonname);
235 		/* no need to free(ai->ai_addr) */
236 		free(ai);
237 	} while ((ai = next) != NULL);
238 }
239 
240 static int
241 str_isnumber(p)
242 	const char *p;
243 {
244 	char *q = (char *)p;
245 	while (*q) {
246 		if (! isdigit(*q))
247 			return NO;
248 		q++;
249 	}
250 	return YES;
251 }
252 
253 int
254 getaddrinfo(hostname, servname, hints, res)
255 	const char *hostname, *servname;
256 	const struct addrinfo *hints;
257 	struct addrinfo **res;
258 {
259 	struct addrinfo sentinel;
260 	struct addrinfo *cur;
261 	int error = 0;
262 	struct addrinfo ai;
263 	struct addrinfo ai0;
264 	struct addrinfo *pai;
265 	const struct afd *afd;
266 	const struct explore *ex;
267 
268 	sentinel.ai_next = NULL;
269 	cur = &sentinel;
270 	pai = &ai;
271 	pai->ai_flags = 0;
272 	pai->ai_family = PF_UNSPEC;
273 	pai->ai_socktype = ANY;
274 	pai->ai_protocol = ANY;
275 	pai->ai_addrlen = 0;
276 	pai->ai_canonname = NULL;
277 	pai->ai_addr = NULL;
278 	pai->ai_next = NULL;
279 
280 	if (hostname == NULL && servname == NULL)
281 		return EAI_NONAME;
282 	if (res == NULL)
283 		return EAI_RESNULL; /* xxx */
284 	if (hints) {
285 		/* error check for hints */
286 		if (hints->ai_addrlen || hints->ai_canonname ||
287 		    hints->ai_addr || hints->ai_next)
288 			ERR(EAI_BADHINTS); /* xxx */
289 		if (hints->ai_flags & ~AI_MASK)
290 			ERR(EAI_BADFLAGS);
291 		switch (hints->ai_family) {
292 		case PF_UNSPEC:
293 		case PF_INET:
294 #ifdef INET6
295 		case PF_INET6:
296 #endif
297 			break;
298 		default:
299 			ERR(EAI_FAMILY);
300 		}
301 		memcpy(pai, hints, sizeof(*pai));
302 
303 		/*
304 		 * if both socktype/protocol are specified, check if they
305 		 * are meaningful combination.
306 		 */
307 		if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
308 			int matched = 0;
309 
310 			for (ex = explore; ex->e_af >= 0; ex++) {
311 				if (pai->ai_family != ex->e_af)
312 					continue;
313 				if (ex->e_socktype == ANY)
314 					continue;
315 				if (ex->e_protocol == ANY)
316 					continue;
317 				if (pai->ai_socktype == ex->e_socktype
318 				 && pai->ai_protocol == ex->e_protocol)
319 					matched = 1;
320 				else
321 					continue;
322 				if (matched == 0)
323 					ERR(EAI_BADHINTS);
324 			}
325 		}
326 	}
327 
328 	/* backup original pai contents */
329 	ai0 = *pai;
330 
331 	/*
332 	 * special cases check for inet and inet6 sockets.
333 	 * (1) servname is disallowed for raw sockets.
334 	 * (2) numeric servname is disallowed if socktype/protocol is left
335 	 *     unspecified.
336 	 */
337 	if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
338 #ifdef INET6
339 	    || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
340 #endif
341 	    ) {
342 		*pai = ai0;
343 
344 		if (pai->ai_family == PF_UNSPEC)
345 #ifdef INET6
346 			pai->ai_family = PF_INET6;
347 #else
348 			pai->ai_family = PF_INET;
349 #endif
350 		error = get_portmatch(pai, servname);
351 		if (error)
352 			ERR(error);
353 	}
354 
355 	/* NULL hostname, or numeric hostname */
356 	for (ex = explore; ex->e_af >= 0; ex++) {
357 		*pai = ai0;
358 
359 		if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
360 			continue;
361 		if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
362 			continue;
363 		if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
364 			continue;
365 
366 		if (pai->ai_family == PF_UNSPEC)
367 			pai->ai_family = ex->e_af;
368 		if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
369 			pai->ai_socktype = ex->e_socktype;
370 		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
371 			pai->ai_protocol = ex->e_protocol;
372 
373 		if (hostname == NULL)
374 			error = explore_null(pai, hostname, servname, &cur->ai_next);
375 		else
376 			error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
377 
378 		if (error)
379 			goto free;
380 
381 		while (cur && cur->ai_next)
382 			cur = cur->ai_next;
383 	}
384 
385 	/*
386 	 * XXX
387 	 * If numreic representation of AF1 can be interpreted as FQDN
388 	 * representation of AF2, we need to think again about the code below.
389 	 */
390 	if (sentinel.ai_next)
391 		goto good;
392 
393 	if (pai->ai_flags & AI_NUMERICHOST)
394 		ERR(EAI_NONAME);
395 	if (hostname == NULL)
396 		ERR(EAI_NONAME);
397 
398 	/*
399 	 * hostname as alphabetical name.
400 	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
401 	 * outer loop by AFs.
402 	 */
403 	for (afd = afdl; afd->a_af; afd++) {
404 		*pai = ai0;
405 
406 		if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
407 			continue;
408 
409 		for (ex = explore; ex->e_af >= 0; ex++) {
410 			*pai = ai0;
411 
412 			if (pai->ai_family == PF_UNSPEC)
413 				pai->ai_family = afd->a_af;
414 
415 			if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
416 					  WILD_AF(ex)))
417 				continue;
418 			if (!MATCH(pai->ai_socktype, ex->e_socktype,
419 					WILD_SOCKTYPE(ex))) {
420 				continue;
421 			}
422 			if (!MATCH(pai->ai_protocol, ex->e_protocol,
423 					WILD_PROTOCOL(ex))) {
424 				continue;
425 			}
426 
427 			if (pai->ai_family == PF_UNSPEC)
428 				pai->ai_family = ex->e_af;
429 			if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
430 				pai->ai_socktype = ex->e_socktype;
431 			if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
432 				pai->ai_protocol = ex->e_protocol;
433 
434 			error = explore_fqdn(pai, hostname, servname,
435 				&cur->ai_next);
436 
437 			while (cur && cur->ai_next)
438 				cur = cur->ai_next;
439 		}
440 	}
441 
442 	/* XXX: if any addrinfo found, SUCCESS return even if (error != 0) */
443 	if (sentinel.ai_next) {
444  good:
445 		*res = sentinel.ai_next;
446 		return SUCCESS;
447 	}
448 	/* else, failed */
449  free:
450  bad:
451 	if (error == 0)
452 		error = EAI_FAIL;
453 	if (sentinel.ai_next)
454 		freeaddrinfo(sentinel.ai_next);
455 	*res = NULL;
456 	return error;
457 }
458 
459 /*
460  * FQDN hostname, DNS lookup
461  */
462 static int
463 explore_fqdn(pai, hostname, servname, res)
464 	const struct addrinfo *pai;
465 	const char *hostname;
466 	const char *servname;
467 	struct addrinfo **res;
468 {
469 	struct hostent *hp;
470 	int h_error;
471 	int af;
472 	char *ap;
473 	struct addrinfo sentinel, *cur;
474 	int i;
475 	const struct afd *afd;
476 	int error;
477 
478 	*res = NULL;
479 	sentinel.ai_next = NULL;
480 	cur = &sentinel;
481 
482 	/*
483 	 * if the servname does not match socktype/protocol, ignore it.
484 	 */
485 	if (get_portmatch(pai, servname) != 0)
486 		return 0;
487 
488 	afd = find_afd(pai->ai_family);
489 	if (afd == NULL)
490 		return 0;
491 
492 	hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG,
493 			     &h_error);
494 	if (hp == NULL) {
495 		switch (h_error) {
496 		case HOST_NOT_FOUND:
497 		case NO_DATA:
498 			error = EAI_NODATA;
499 			break;
500 		case TRY_AGAIN:
501 			error = EAI_AGAIN;
502 			break;
503 		case NO_RECOVERY:
504 		case NETDB_INTERNAL:
505 		default:
506 			error = EAI_FAIL;
507 			break;
508 		}
509 	} else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
510 			|| (hp->h_addr_list[0] == NULL)) {
511 		freehostent(hp);
512 		hp = NULL;
513 		error = EAI_FAIL;
514 	}
515 
516 	if (hp == NULL)
517 		goto free;
518 
519 	for (i = 0; hp->h_addr_list[i] != NULL; i++) {
520 		af = hp->h_addrtype;
521 		ap = hp->h_addr_list[i];
522 
523 		if (af != pai->ai_family)
524 			continue;
525 
526 		GET_AI(cur->ai_next, afd, ap);
527 		GET_PORT(cur->ai_next, servname);
528 		if ((pai->ai_flags & AI_CANONNAME) != 0) {
529 			/*
530 			 * RFC2553 says that ai_canonname will be set only for
531 			 * the first element.  we do it for all the elements,
532 			 * just for convenience.
533 			 */
534 			GET_CANONNAME(cur->ai_next, hp->h_name);
535 		}
536 
537 		while (cur && cur->ai_next)
538 			cur = cur->ai_next;
539 	}
540 
541 	*res = sentinel.ai_next;
542 	return 0;
543 
544 free:
545 	if (hp)
546 		freehostent(hp);
547 	if (sentinel.ai_next)
548 		freeaddrinfo(sentinel.ai_next);
549 	return error;
550 }
551 
552 /*
553  * hostname == NULL.
554  * passive socket -> anyaddr (0.0.0.0 or ::)
555  * non-passive socket -> localhost (127.0.0.1 or ::1)
556  */
557 static int
558 explore_null(pai, hostname, servname, res)
559 	const struct addrinfo *pai;
560 	const char *hostname;
561 	const char *servname;
562 	struct addrinfo **res;
563 {
564 	int s;
565 	const struct afd *afd;
566 	struct addrinfo *cur;
567 	struct addrinfo sentinel;
568 	int error;
569 
570 	*res = NULL;
571 	sentinel.ai_next = NULL;
572 	cur = &sentinel;
573 
574 	/*
575 	 * filter out AFs that are not supported by the kernel
576 	 * XXX errno?
577 	 */
578 	s = socket(pai->ai_family, SOCK_DGRAM, 0);
579 	if (s < 0)
580 		return 0;
581 	_close(s);
582 	afd = find_afd(pai->ai_family);
583 	if (afd == NULL)
584 		return 0;
585 
586 	GET_AI(cur->ai_next, afd,
587 	       (pai->ai_flags & AI_PASSIVE) ? afd->a_addrany : afd->a_loopback
588 	       );
589 	/* xxx meaningless?
590 	 * GET_CANONNAME(cur->ai_next, "anyaddr");
591 	 * or
592 	 * GET_CANONNAME(cur->ai_next, "localhost");
593 	 */
594 	/* if the servname does not match socktype/protocol, ignored */
595 	GET_PORT(cur->ai_next, servname);
596 
597 	*res = sentinel.ai_next;
598 	return 0;
599 
600 free:
601 	if (sentinel.ai_next)
602 		freeaddrinfo(sentinel.ai_next);
603 	return error;
604 }
605 
606 /*
607  * numeric hostname
608  */
609 static int
610 explore_numeric(pai, hostname, servname, res)
611 	const struct addrinfo *pai;
612 	const char *hostname;
613 	const char *servname;
614 	struct addrinfo **res;
615 {
616 	const struct afd *afd;
617 	struct addrinfo *cur;
618 	struct addrinfo sentinel;
619 	int error;
620 	char pton[PTON_MAX];
621 	int flags;
622 
623 	*res = NULL;
624 	sentinel.ai_next = NULL;
625 	cur = &sentinel;
626 
627 	/*
628 	 * if the servname does not match socktype/protocol, ignore it.
629 	 */
630 	if (get_portmatch(pai, servname) != 0)
631 		return 0;
632 
633 	afd = find_afd(pai->ai_family);
634 	if (afd == NULL)
635 		return 0;
636 	flags = pai->ai_flags;
637 
638 	if ((afd->a_af == AF_INET
639 	     ? inet_aton(hostname, (struct in_addr *)pton)
640 	     : inet_pton(afd->a_af, hostname, pton)) == 1) {
641 		if (pai->ai_family == afd->a_af ||
642 		    pai->ai_family == PF_UNSPEC /*?*/) {
643 			GET_AI(cur->ai_next, afd, pton);
644 			GET_PORT(cur->ai_next, servname);
645 			while (cur && cur->ai_next)
646 				cur = cur->ai_next;
647 		} else
648 			ERR(EAI_FAMILY);	/*xxx*/
649 	}
650 
651 	*res = sentinel.ai_next;
652 	return 0;
653 
654 free:
655 bad:
656 	if (sentinel.ai_next)
657 		freeaddrinfo(sentinel.ai_next);
658 	return error;
659 }
660 
661 /*
662  * numeric hostname with scope
663  */
664 static int
665 explore_numeric_scope(pai, hostname, servname, res)
666 	const struct addrinfo *pai;
667 	const char *hostname;
668 	const char *servname;
669 	struct addrinfo **res;
670 {
671 #ifndef SCOPE_DELIMITER
672 	return explore_numeric(pai, hostname, servname, res);
673 #else
674 	const struct afd *afd;
675 	struct addrinfo *cur;
676 	int error;
677 	char *cp, *hostname2 = NULL;
678 	int scope;
679 #ifdef INET6
680 	struct sockaddr_in6 *sin6;
681 #endif
682 
683 	/*
684 	 * if the servname does not match socktype/protocol, ignore it.
685 	 */
686 	if (get_portmatch(pai, servname) != 0)
687 		return 0;
688 
689 	afd = find_afd(pai->ai_family);
690 	if (afd == NULL)
691 		return 0;
692 	if (!afd->a_scoped)
693 		return explore_numeric(pai, hostname, servname, res);
694 
695 	cp = strchr(hostname, SCOPE_DELIMITER);
696 	if (cp == NULL)
697 		return explore_numeric(pai, hostname, servname, res);
698 
699 	/*
700 	 * Handle special case of <scoped_address><delimiter><scope id>
701 	 */
702 	hostname2 = strdup(hostname);
703 	if (hostname2 == NULL)
704 		return EAI_MEMORY;
705 	/* terminate at the delimiter */
706 	hostname2[cp - hostname] = '\0';
707 
708 	cp++;
709 	switch (pai->ai_family) {
710 #ifdef INET6
711 	case AF_INET6:
712 		scope = if_nametoindex(cp);
713 		if (scope == 0) {
714 			error = EAI_SYSTEM;
715 			goto free;
716 		}
717 		break;
718 #endif
719 	}
720 
721 	error = explore_numeric(pai, hostname2, servname, res);
722 	if (error == 0) {
723 		for (cur = *res; cur; cur = cur->ai_next) {
724 #ifdef INET6
725 			if (cur->ai_family != AF_INET6)
726 				continue;
727 			sin6 = (struct sockaddr_in6 *)cur->ai_addr;
728 			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
729 			    IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
730 				sin6->sin6_scope_id = scope;
731 #endif
732 		}
733 	}
734 
735 #ifdef INET6
736 free:
737 #endif
738 	free(hostname2);
739 
740 	return error;
741 #endif
742 }
743 
744 static int
745 get_canonname(pai, ai, str)
746 	const struct addrinfo *pai;
747 	struct addrinfo *ai;
748 	const char *str;
749 {
750 	if ((pai->ai_flags & AI_CANONNAME) != 0) {
751 		ai->ai_canonname = (char *)malloc(strlen(str) + 1);
752 		if (ai->ai_canonname == NULL)
753 			return EAI_MEMORY;
754 		strcpy(ai->ai_canonname, str);
755 	}
756 	return 0;
757 }
758 
759 static struct addrinfo *
760 get_ai(pai, afd, addr)
761 	const struct addrinfo *pai;
762 	const struct afd *afd;
763 	const char *addr;
764 {
765 	char *p;
766 	struct addrinfo *ai;
767 #ifdef FAITH
768 	struct in6_addr faith_prefix;
769 	char *fp_str;
770 	int translate = 0;
771 #endif
772 
773 #ifdef FAITH
774 	/*
775 	 * Transfrom an IPv4 addr into a special IPv6 addr format for
776 	 * IPv6->IPv4 translation gateway. (only TCP is supported now)
777 	 *
778 	 * +-----------------------------------+------------+
779 	 * | faith prefix part (12 bytes)      | embedded   |
780 	 * |                                   | IPv4 addr part (4 bytes)
781 	 * +-----------------------------------+------------+
782 	 *
783 	 * faith prefix part is specified as ascii IPv6 addr format
784 	 * in environmental variable GAI.
785 	 * For FAITH to work correctly, routing to faith prefix must be
786 	 * setup toward a machine where a FAITH daemon operates.
787 	 * Also, the machine must enable some mechanizm
788 	 * (e.g. faith interface hack) to divert those packet with
789 	 * faith prefixed destination addr to user-land FAITH daemon.
790 	 */
791 	fp_str = getenv("GAI");
792 	if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
793 	    afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
794 		u_int32_t v4a;
795 		u_int8_t v4a_top;
796 
797 		memcpy(&v4a, addr, sizeof v4a);
798 		v4a_top = v4a >> IN_CLASSA_NSHIFT;
799 		if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
800 		    v4a_top != 0 && v4a != IN_LOOPBACKNET) {
801 			afd = &afdl[N_INET6];
802 			memcpy(&faith_prefix.s6_addr[12], addr,
803 			       sizeof(struct in_addr));
804 			translate = 1;
805 		}
806 	}
807 #endif
808 
809 	ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
810 		+ (afd->a_socklen));
811 	if (ai == NULL)
812 		return NULL;
813 
814 	memcpy(ai, pai, sizeof(struct addrinfo));
815 	ai->ai_addr = (struct sockaddr *)(ai + 1);
816 	memset(ai->ai_addr, 0, afd->a_socklen);
817 	ai->ai_addr->sa_len = afd->a_socklen;
818 	ai->ai_addrlen = afd->a_socklen;
819 	ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
820 	p = (char *)(ai->ai_addr);
821 #ifdef FAITH
822 	if (translate == 1)
823 		memcpy(p + afd->a_off, &faith_prefix, afd->a_addrlen);
824 	else
825 #endif
826 	memcpy(p + afd->a_off, addr, afd->a_addrlen);
827 
828 	return ai;
829 }
830 
831 static int
832 get_portmatch(ai, servname)
833 	const struct addrinfo *ai;
834 	const char *servname;
835 {
836 	/* get_port does not touch first argument. when matchonly == 1. */
837 	return get_port((struct addrinfo *)ai, servname, 1);
838 }
839 
840 static int
841 get_port(ai, servname, matchonly)
842 	struct addrinfo *ai;
843 	const char *servname;
844 	int matchonly;
845 {
846 	const char *proto;
847 	struct servent *sp;
848 	int port;
849 	int allownumeric;
850 
851 	if (servname == NULL)
852 		return 0;
853 	if (ai->ai_family != AF_INET
854 #ifdef INET6
855 	    && ai->ai_family != AF_INET6
856 #endif
857 	    )
858 		return 0;
859 
860 	switch (ai->ai_socktype) {
861 	case SOCK_RAW:
862 		return EAI_SERVICE;
863 	case SOCK_DGRAM:
864 	case SOCK_STREAM:
865 		allownumeric = 1;
866 		break;
867 	case ANY:
868 		allownumeric = 0;
869 		break;
870 	default:
871 		return EAI_SOCKTYPE;
872 	}
873 
874 	if (str_isnumber(servname)) {
875 		if (!allownumeric)
876 			return EAI_SERVICE;
877 		port = htons(atoi(servname));
878 		if (port < 0 || port > 65535)
879 			return EAI_SERVICE;
880 	} else {
881 		switch (ai->ai_socktype) {
882 		case SOCK_DGRAM:
883 			proto = "udp";
884 			break;
885 		case SOCK_STREAM:
886 			proto = "tcp";
887 			break;
888 		default:
889 			proto = NULL;
890 			break;
891 		}
892 
893 		if ((sp = getservbyname(servname, proto)) == NULL)
894 			return EAI_SERVICE;
895 		port = sp->s_port;
896 	}
897 
898 	if (!matchonly) {
899 		switch (ai->ai_family) {
900 		case AF_INET:
901 			((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
902 			break;
903 #ifdef INET6
904 		case AF_INET6:
905 			((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
906 			break;
907 #endif
908 		}
909 	}
910 
911 	return 0;
912 }
913 
914 static const struct afd *
915 find_afd(af)
916 	int af;
917 {
918 	const struct afd *afd;
919 
920 	if (af == PF_UNSPEC)
921 		return NULL;
922 	for (afd = afdl; afd->a_af; afd++) {
923 		if (afd->a_af == af)
924 			return afd;
925 	}
926 	return NULL;
927 }
928