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