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