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
104 static int translate = NO;
105 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
106 #endif
107 
108 static const char in_addrany[] = { 0, 0, 0, 0 };
109 static const char in6_addrany[] = {
110 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
111 };
112 static const char in_loopback[] = { 127, 0, 0, 1 };
113 static const char in6_loopback[] = {
114 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
115 };
116 
117 struct 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 
124 static 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 
146 struct 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 
157 static 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 
179 static int str_isnumber __P((const char *));
180 static int explore_fqdn __P((const struct addrinfo *, const char *,
181 	const char *, struct addrinfo **));
182 static int explore_null __P((const struct addrinfo *, const char *,
183 	const char *, struct addrinfo **));
184 static int explore_numeric __P((const struct addrinfo *, const char *,
185 	const char *, struct addrinfo **));
186 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
187 	const char *, struct addrinfo **));
188 static int get_name __P((const char *, const struct afd *, struct addrinfo **,
189 	char *, const struct addrinfo *, const char *));
190 static int get_canonname __P((const struct addrinfo *,
191 	struct addrinfo *, const char *));
192 static struct addrinfo *get_ai __P((const struct addrinfo *,
193 	const struct afd *, const char *));
194 static int get_portmatch __P((const struct addrinfo *, const char *));
195 static int get_port __P((struct addrinfo *, const char *, int));
196 static const struct afd *find_afd __P((int));
197 
198 static 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) \
219 do { \
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) \
229 do { \
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) \
237 do { \
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) \
245 do { \
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)
257 char *
gai_strerror(ecode)258 gai_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 
267 void
freeaddrinfo(ai)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
str_isnumber(p)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
getaddrinfo(hostname,servname,hints,res)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 #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  */
514 static int
explore_fqdn(pai,hostname,servname,res)515 explore_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 
669 free:
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  */
688 static int
explore_null(pai,hostname,servname,res)689 explore_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 
742 free:
743 	if (sentinel.ai_next)
744 		freeaddrinfo(sentinel.ai_next);
745 	return error;
746 }
747 
748 /*
749  * numeric hostname
750  */
751 static int
explore_numeric(pai,hostname,servname,res)752 explore_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 
830 free:
831 bad:
832 	if (sentinel.ai_next)
833 		freeaddrinfo(sentinel.ai_next);
834 	return error;
835 }
836 
837 /*
838  * numeric hostname with scope
839  */
840 static int
explore_numeric_scope(pai,hostname,servname,res)841 explore_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 
911 static int
get_name(addr,afd,res,numaddr,pai,servname)912 get_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 
980 static int
get_canonname(pai,ai,str)981 get_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 
994 static struct addrinfo *
get_ai(pai,afd,addr)995 get_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 
1021 static int
get_portmatch(ai,servname)1022 get_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 
1031 static int
get_port(ai,servname,matchonly)1032 get_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 
1108 static const struct afd *
find_afd(af)1109 find_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