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