Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / libbind / dist / irs / getaddrinfo.c
blob0f6b985ed9c610563bc779469a7964c0091c1eec
1 /* $NetBSD$ */
3 /* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 /*! \file
35 * Issues to be discussed:
36 *\li Thread safe-ness must be checked.
37 *\li 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 *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
41 * says to use inet_aton() to convert IPv4 numeric to binary (allows
42 * classful form as a result).
43 * current code - disallow classful form for IPv4 (due to use of inet_pton).
44 *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
45 * invalid.
46 * current code - SEGV on freeaddrinfo(NULL)
47 * Note:
48 *\li We use getipnodebyname() just for thread-safeness. There's no intent
49 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
50 * getipnodebyname().
51 *\li The code filters out AFs that are not supported by the kernel,
52 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
53 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
54 * in ai_flags?
55 *\li (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
56 * (1) what should we do against numeric hostname (2) what should we do
57 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
58 * non-loopback address configured? global address configured?
59 * \par Additional Issue:
60 * To avoid search order issue, we have a big amount of code duplicate
61 * from gethnamaddr.c and some other places. The issues that there's no
62 * lower layer function to lookup "IPv4 or IPv6" record. Calling
63 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
64 * follows:
65 * \li The code makes use of following calls when asked to resolver with
66 * ai_family = PF_UNSPEC:
67 *\code getipnodebyname(host, AF_INET6);
68 * getipnodebyname(host, AF_INET);
69 *\endcode
70 * \li This will result in the following queries if the node is configure to
71 * prefer /etc/hosts than DNS:
72 *\code
73 * lookup /etc/hosts for IPv6 address
74 * lookup DNS for IPv6 address
75 * lookup /etc/hosts for IPv4 address
76 * lookup DNS for IPv4 address
77 *\endcode
78 * which may not meet people's requirement.
79 * \li The right thing to happen is to have underlying layer which does
80 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
81 * This would result in a bit of code duplicate with _dns_ghbyname() and
82 * friends.
85 #include "port_before.h"
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <sys/socket.h>
91 #include <net/if.h>
92 #include <netinet/in.h>
94 #include <arpa/inet.h>
95 #include <arpa/nameser.h>
97 #include <netdb.h>
98 #include <resolv.h>
99 #include <string.h>
100 #include <stdlib.h>
101 #include <stddef.h>
102 #include <ctype.h>
103 #include <unistd.h>
104 #include <stdio.h>
105 #include <errno.h>
107 #include <stdarg.h>
109 #include <irs.h>
110 #include <isc/assertions.h>
112 #include "port_after.h"
114 #include "irs_data.h"
116 #define SUCCESS 0
117 #define ANY 0
118 #define YES 1
119 #define NO 0
121 static const char in_addrany[] = { 0, 0, 0, 0 };
122 static const char in6_addrany[] = {
123 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
125 static const char in_loopback[] = { 127, 0, 0, 1 };
126 static const char in6_loopback[] = {
127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
130 static const struct afd {
131 int a_af;
132 int a_addrlen;
133 int a_socklen;
134 int a_off;
135 const char *a_addrany;
136 const char *a_loopback;
137 int a_scoped;
138 } afdl [] = {
139 {PF_INET6, sizeof(struct in6_addr),
140 sizeof(struct sockaddr_in6),
141 offsetof(struct sockaddr_in6, sin6_addr),
142 in6_addrany, in6_loopback, 1},
143 {PF_INET, sizeof(struct in_addr),
144 sizeof(struct sockaddr_in),
145 offsetof(struct sockaddr_in, sin_addr),
146 in_addrany, in_loopback, 0},
147 {0, 0, 0, 0, NULL, NULL, 0},
150 struct explore {
151 int e_af;
152 int e_socktype;
153 int e_protocol;
154 const char *e_protostr;
155 int e_wild;
156 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
157 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
158 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
161 static const struct explore explore[] = {
162 #if 0
163 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
164 #endif
165 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
166 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
167 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
168 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
169 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
170 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
171 { -1, 0, 0, NULL, 0 },
174 #define PTON_MAX 16
176 static int str_isnumber __P((const char *));
177 static int explore_fqdn __P((const struct addrinfo *, const char *,
178 const char *, struct addrinfo **));
179 static int explore_copy __P((const struct addrinfo *, const struct addrinfo *,
180 struct addrinfo **));
181 static int explore_null __P((const struct addrinfo *,
182 const char *, struct addrinfo **));
183 static int explore_numeric __P((const struct addrinfo *, const char *,
184 const char *, struct addrinfo **));
185 static int explore_numeric_scope __P((const struct addrinfo *, const char *,
186 const char *, struct addrinfo **));
187 static int get_canonname __P((const struct addrinfo *,
188 struct addrinfo *, const char *));
189 static struct addrinfo *get_ai __P((const struct addrinfo *,
190 const struct afd *, const char *));
191 static struct addrinfo *copy_ai __P((const struct addrinfo *));
192 static int get_portmatch __P((const struct addrinfo *, const char *));
193 static int get_port __P((const struct addrinfo *, const char *, int));
194 static const struct afd *find_afd __P((int));
195 static int addrconfig __P((int));
196 static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *,
197 u_int32_t *scopeidp));
198 static struct net_data *init __P((void));
200 struct addrinfo *hostent2addrinfo __P((struct hostent *,
201 const struct addrinfo *));
202 struct addrinfo *addr2addrinfo __P((const struct addrinfo *,
203 const char *));
205 #if 0
206 static const char *ai_errlist[] = {
207 "Success",
208 "Address family for hostname not supported", /*%< EAI_ADDRFAMILY */
209 "Temporary failure in name resolution", /*%< EAI_AGAIN */
210 "Invalid value for ai_flags", /*%< EAI_BADFLAGS */
211 "Non-recoverable failure in name resolution", /*%< EAI_FAIL */
212 "ai_family not supported", /*%< EAI_FAMILY */
213 "Memory allocation failure", /*%< EAI_MEMORY */
214 "No address associated with hostname", /*%< EAI_NODATA */
215 "hostname nor servname provided, or not known", /*%< EAI_NONAME */
216 "servname not supported for ai_socktype", /*%< EAI_SERVICE */
217 "ai_socktype not supported", /*%< EAI_SOCKTYPE */
218 "System error returned in errno", /*%< EAI_SYSTEM */
219 "Invalid value for hints", /*%< EAI_BADHINTS */
220 "Resolved protocol is unknown", /*%< EAI_PROTOCOL */
221 "Unknown error", /*%< EAI_MAX */
223 #endif
225 /* XXX macros that make external reference is BAD. */
227 #define GET_AI(ai, afd, addr) \
228 do { \
229 /* external reference: pai, error, and label free */ \
230 (ai) = get_ai(pai, (afd), (addr)); \
231 if ((ai) == NULL) { \
232 error = EAI_MEMORY; \
233 goto free; \
235 } while (/*CONSTCOND*/0)
237 #define GET_PORT(ai, serv) \
238 do { \
239 /* external reference: error and label free */ \
240 error = get_port((ai), (serv), 0); \
241 if (error != 0) \
242 goto free; \
243 } while (/*CONSTCOND*/0)
245 #define GET_CANONNAME(ai, str) \
246 do { \
247 /* external reference: pai, error and label free */ \
248 error = get_canonname(pai, (ai), (str)); \
249 if (error != 0) \
250 goto free; \
251 } while (/*CONSTCOND*/0)
253 #ifndef SOLARIS2
254 #define SETERROR(err) \
255 do { \
256 /* external reference: error, and label bad */ \
257 error = (err); \
258 goto bad; \
259 /*NOTREACHED*/ \
260 } while (/*CONSTCOND*/0)
261 #else
262 #define SETERROR(err) \
263 do { \
264 /* external reference: error, and label bad */ \
265 error = (err); \
266 if (error == error) \
267 goto bad; \
268 } while (/*CONSTCOND*/0)
269 #endif
272 #define MATCH_FAMILY(x, y, w) \
273 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
274 #define MATCH(x, y, w) \
275 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
277 #if 0 /*%< bind8 has its own version */
278 char *
279 gai_strerror(ecode)
280 int ecode;
282 if (ecode < 0 || ecode > EAI_MAX)
283 ecode = EAI_MAX;
284 return ai_errlist[ecode];
286 #endif
288 void
289 freeaddrinfo(ai)
290 struct addrinfo *ai;
292 struct addrinfo *next;
294 do {
295 next = ai->ai_next;
296 if (ai->ai_canonname)
297 free(ai->ai_canonname);
298 /* no need to free(ai->ai_addr) */
299 free(ai);
300 ai = next;
301 } while (ai);
304 static int
305 str_isnumber(p)
306 const char *p;
308 char *ep;
310 if (*p == '\0')
311 return NO;
312 ep = NULL;
313 errno = 0;
314 (void)strtoul(p, &ep, 10);
315 if (errno == 0 && ep && *ep == '\0')
316 return YES;
317 else
318 return NO;
322 getaddrinfo(hostname, servname, hints, res)
323 const char *hostname, *servname;
324 const struct addrinfo *hints;
325 struct addrinfo **res;
327 struct addrinfo sentinel;
328 struct addrinfo *cur;
329 int error = 0;
330 struct addrinfo ai, ai0, *afai = NULL;
331 struct addrinfo *pai;
332 const struct explore *ex;
334 memset(&sentinel, 0, sizeof(sentinel));
335 cur = &sentinel;
336 pai = &ai;
337 pai->ai_flags = 0;
338 pai->ai_family = PF_UNSPEC;
339 pai->ai_socktype = ANY;
340 pai->ai_protocol = ANY;
341 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
343 * clear _ai_pad to preserve binary
344 * compatibility with previously compiled 64-bit
345 * applications in a pre-SUSv3 environment by
346 * guaranteeing the upper 32-bits are empty.
348 pai->_ai_pad = 0;
349 #endif
350 pai->ai_addrlen = 0;
351 pai->ai_canonname = NULL;
352 pai->ai_addr = NULL;
353 pai->ai_next = NULL;
355 if (hostname == NULL && servname == NULL)
356 return EAI_NONAME;
357 if (hints) {
358 /* error check for hints */
359 if (hints->ai_addrlen || hints->ai_canonname ||
360 hints->ai_addr || hints->ai_next)
361 SETERROR(EAI_BADHINTS); /*%< xxx */
362 if (hints->ai_flags & ~AI_MASK)
363 SETERROR(EAI_BADFLAGS);
364 switch (hints->ai_family) {
365 case PF_UNSPEC:
366 case PF_INET:
367 case PF_INET6:
368 break;
369 default:
370 SETERROR(EAI_FAMILY);
372 memcpy(pai, hints, sizeof(*pai));
374 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
376 * We need to clear _ai_pad to preserve binary
377 * compatibility. See prior comment.
379 pai->_ai_pad = 0;
380 #endif
382 * if both socktype/protocol are specified, check if they
383 * are meaningful combination.
385 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
386 for (ex = explore; ex->e_af >= 0; ex++) {
387 if (pai->ai_family != ex->e_af)
388 continue;
389 if (ex->e_socktype == ANY)
390 continue;
391 if (ex->e_protocol == ANY)
392 continue;
393 if (pai->ai_socktype == ex->e_socktype &&
394 pai->ai_protocol != ex->e_protocol) {
395 SETERROR(EAI_BADHINTS);
402 * post-2553: AI_ALL and AI_V4MAPPED are effective only against
403 * AF_INET6 query. They needs to be ignored if specified in other
404 * occassions.
406 switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) {
407 case AI_V4MAPPED:
408 case AI_ALL | AI_V4MAPPED:
409 if (pai->ai_family != AF_INET6)
410 pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
411 break;
412 case AI_ALL:
413 #if 1
414 /* illegal */
415 SETERROR(EAI_BADFLAGS);
416 #else
417 pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED);
418 break;
419 #endif
423 * check for special cases. (1) numeric servname is disallowed if
424 * socktype/protocol are left unspecified. (2) servname is disallowed
425 * for raw and other inet{,6} sockets.
427 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
428 #ifdef PF_INET6
429 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
430 #endif
432 ai0 = *pai; /* backup *pai */
434 if (pai->ai_family == PF_UNSPEC) {
435 #ifdef PF_INET6
436 pai->ai_family = PF_INET6;
437 #else
438 pai->ai_family = PF_INET;
439 #endif
441 error = get_portmatch(pai, servname);
442 if (error)
443 SETERROR(error);
445 *pai = ai0;
448 ai0 = *pai;
450 /* NULL hostname, or numeric hostname */
451 for (ex = explore; ex->e_af >= 0; ex++) {
452 *pai = ai0;
454 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
455 continue;
456 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
457 continue;
458 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
459 continue;
461 if (pai->ai_family == PF_UNSPEC)
462 pai->ai_family = ex->e_af;
463 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
464 pai->ai_socktype = ex->e_socktype;
465 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
466 pai->ai_protocol = ex->e_protocol;
469 * if the servname does not match socktype/protocol, ignore it.
471 if (get_portmatch(pai, servname) != 0)
472 continue;
474 if (hostname == NULL) {
476 * filter out AFs that are not supported by the kernel
477 * XXX errno?
479 if (!addrconfig(pai->ai_family))
480 continue;
481 error = explore_null(pai, servname, &cur->ai_next);
482 } else
483 error = explore_numeric_scope(pai, hostname, servname,
484 &cur->ai_next);
486 if (error)
487 goto free;
489 while (cur && cur->ai_next)
490 cur = cur->ai_next;
494 * XXX
495 * If numreic representation of AF1 can be interpreted as FQDN
496 * representation of AF2, we need to think again about the code below.
498 if (sentinel.ai_next)
499 goto good;
501 if (pai->ai_flags & AI_NUMERICHOST)
502 SETERROR(EAI_NONAME);
503 if (hostname == NULL)
504 SETERROR(EAI_NONAME);
507 * hostname as alphabetical name.
508 * We'll make sure that
509 * - if returning addrinfo list is empty, return non-zero error
510 * value (already known one or EAI_NONAME).
511 * - otherwise,
512 * + if we haven't had any errors, return 0 (i.e. success).
513 * + if we've had an error, free the list and return the error.
514 * without any assumption on the behavior of explore_fqdn().
517 /* first, try to query DNS for all possible address families. */
518 *pai = ai0;
519 error = explore_fqdn(pai, hostname, servname, &afai);
520 if (error) {
521 if (afai != NULL)
522 freeaddrinfo(afai);
523 goto free;
525 if (afai == NULL) {
526 error = EAI_NONAME; /*%< we've had no errors. */
527 goto free;
531 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
532 * outer loop by AFs.
534 for (ex = explore; ex->e_af >= 0; ex++) {
535 *pai = ai0;
537 if (pai->ai_family == PF_UNSPEC)
538 pai->ai_family = ex->e_af;
540 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
541 continue;
542 if (!MATCH(pai->ai_socktype, ex->e_socktype,
543 WILD_SOCKTYPE(ex))) {
544 continue;
546 if (!MATCH(pai->ai_protocol, ex->e_protocol,
547 WILD_PROTOCOL(ex))) {
548 continue;
551 #ifdef AI_ADDRCONFIG
553 * If AI_ADDRCONFIG is specified, check if we are
554 * expected to return the address family or not.
556 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 &&
557 !addrconfig(pai->ai_family))
558 continue;
559 #endif
561 if (pai->ai_family == PF_UNSPEC)
562 pai->ai_family = ex->e_af;
563 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
564 pai->ai_socktype = ex->e_socktype;
565 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
566 pai->ai_protocol = ex->e_protocol;
569 * if the servname does not match socktype/protocol, ignore it.
571 if (get_portmatch(pai, servname) != 0)
572 continue;
574 if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) {
575 freeaddrinfo(afai);
576 goto free;
579 while (cur && cur->ai_next)
580 cur = cur->ai_next;
583 freeaddrinfo(afai); /*%< afai must not be NULL at this point. */
585 if (sentinel.ai_next) {
586 good:
587 *res = sentinel.ai_next;
588 return(SUCCESS);
589 } else {
591 * All the process succeeded, but we've had an empty list.
592 * This can happen if the given hints do not match our
593 * candidates.
595 error = EAI_NONAME;
598 free:
599 bad:
600 if (sentinel.ai_next)
601 freeaddrinfo(sentinel.ai_next);
602 *res = NULL;
603 return(error);
607 * FQDN hostname, DNS lookup
609 static int
610 explore_fqdn(pai, hostname, servname, res)
611 const struct addrinfo *pai;
612 const char *hostname;
613 const char *servname;
614 struct addrinfo **res;
616 struct addrinfo *result;
617 struct addrinfo *cur;
618 struct net_data *net_data = init();
619 struct irs_ho *ho;
620 int error = 0;
621 char tmp[NS_MAXDNAME];
622 const char *cp;
624 INSIST(res != NULL && *res == NULL);
627 * if the servname does not match socktype/protocol, ignore it.
629 if (get_portmatch(pai, servname) != 0)
630 return(0);
632 if (!net_data || !(ho = net_data->ho))
633 return(0);
634 #if 0 /*%< XXX (notyet) */
635 if (net_data->ho_stayopen && net_data->ho_last &&
636 net_data->ho_last->h_addrtype == af) {
637 if (ns_samename(name, net_data->ho_last->h_name) == 1)
638 return (net_data->ho_last);
639 for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++)
640 if (ns_samename(name, *hap) == 1)
641 return (net_data->ho_last);
643 #endif
644 if (!strchr(hostname, '.') &&
645 (cp = res_hostalias(net_data->res, hostname,
646 tmp, sizeof(tmp))))
647 hostname = cp;
648 result = (*ho->addrinfo)(ho, hostname, pai);
649 if (!net_data->ho_stayopen) {
650 (*ho->minimize)(ho);
652 if (result == NULL) {
653 int e = h_errno;
655 switch(e) {
656 case NETDB_INTERNAL:
657 error = EAI_SYSTEM;
658 break;
659 case TRY_AGAIN:
660 error = EAI_AGAIN;
661 break;
662 case NO_RECOVERY:
663 error = EAI_FAIL;
664 break;
665 case HOST_NOT_FOUND:
666 case NO_DATA:
667 error = EAI_NONAME;
668 break;
669 default:
670 case NETDB_SUCCESS: /*%< should be impossible... */
671 error = EAI_NONAME;
672 break;
674 goto free;
677 for (cur = result; cur; cur = cur->ai_next) {
678 GET_PORT(cur, servname); /*%< XXX: redundant lookups... */
679 /* canonname should already be filled. */
682 *res = result;
684 return(0);
686 free:
687 if (result)
688 freeaddrinfo(result);
689 return error;
692 static int
693 explore_copy(pai, src0, res)
694 const struct addrinfo *pai; /*%< seed */
695 const struct addrinfo *src0; /*%< source */
696 struct addrinfo **res;
698 int error;
699 struct addrinfo sentinel, *cur;
700 const struct addrinfo *src;
702 error = 0;
703 sentinel.ai_next = NULL;
704 cur = &sentinel;
706 for (src = src0; src != NULL; src = src->ai_next) {
707 if (src->ai_family != pai->ai_family)
708 continue;
710 cur->ai_next = copy_ai(src);
711 if (!cur->ai_next) {
712 error = EAI_MEMORY;
713 goto fail;
716 cur->ai_next->ai_socktype = pai->ai_socktype;
717 cur->ai_next->ai_protocol = pai->ai_protocol;
718 cur = cur->ai_next;
721 *res = sentinel.ai_next;
722 return 0;
724 fail:
725 freeaddrinfo(sentinel.ai_next);
726 return error;
730 * hostname == NULL.
731 * passive socket -> anyaddr (0.0.0.0 or ::)
732 * non-passive socket -> localhost (127.0.0.1 or ::1)
734 static int
735 explore_null(pai, servname, res)
736 const struct addrinfo *pai;
737 const char *servname;
738 struct addrinfo **res;
740 const struct afd *afd;
741 struct addrinfo *cur;
742 struct addrinfo sentinel;
743 int error;
745 *res = NULL;
746 sentinel.ai_next = NULL;
747 cur = &sentinel;
749 afd = find_afd(pai->ai_family);
750 if (afd == NULL)
751 return 0;
753 if (pai->ai_flags & AI_PASSIVE) {
754 GET_AI(cur->ai_next, afd, afd->a_addrany);
755 /* xxx meaningless?
756 * GET_CANONNAME(cur->ai_next, "anyaddr");
758 GET_PORT(cur->ai_next, servname);
759 } else {
760 GET_AI(cur->ai_next, afd, afd->a_loopback);
761 /* xxx meaningless?
762 * GET_CANONNAME(cur->ai_next, "localhost");
764 GET_PORT(cur->ai_next, servname);
766 cur = cur->ai_next;
768 *res = sentinel.ai_next;
769 return 0;
771 free:
772 if (sentinel.ai_next)
773 freeaddrinfo(sentinel.ai_next);
774 return error;
778 * numeric hostname
780 static int
781 explore_numeric(pai, hostname, servname, res)
782 const struct addrinfo *pai;
783 const char *hostname;
784 const char *servname;
785 struct addrinfo **res;
787 const struct afd *afd;
788 struct addrinfo *cur;
789 struct addrinfo sentinel;
790 int error;
791 char pton[PTON_MAX];
793 *res = NULL;
794 sentinel.ai_next = NULL;
795 cur = &sentinel;
797 afd = find_afd(pai->ai_family);
798 if (afd == NULL)
799 return 0;
801 switch (afd->a_af) {
802 #if 0 /*X/Open spec*/
803 case AF_INET:
804 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
805 if (pai->ai_family == afd->a_af ||
806 pai->ai_family == PF_UNSPEC /*?*/) {
807 GET_AI(cur->ai_next, afd, pton);
808 GET_PORT(cur->ai_next, servname);
809 while (cur->ai_next)
810 cur = cur->ai_next;
811 } else
812 SETERROR(EAI_FAMILY); /*xxx*/
814 break;
815 #endif
816 default:
817 if (inet_pton(afd->a_af, hostname, pton) == 1) {
818 if (pai->ai_family == afd->a_af ||
819 pai->ai_family == PF_UNSPEC /*?*/) {
820 GET_AI(cur->ai_next, afd, pton);
821 GET_PORT(cur->ai_next, servname);
822 while (cur->ai_next)
823 cur = cur->ai_next;
824 } else
825 SETERROR(EAI_FAMILY); /*xxx*/
827 break;
830 *res = sentinel.ai_next;
831 return 0;
833 free:
834 bad:
835 if (sentinel.ai_next)
836 freeaddrinfo(sentinel.ai_next);
837 return error;
841 * numeric hostname with scope
843 static int
844 explore_numeric_scope(pai, hostname, servname, res)
845 const struct addrinfo *pai;
846 const char *hostname;
847 const char *servname;
848 struct addrinfo **res;
850 #ifndef SCOPE_DELIMITER
851 return explore_numeric(pai, hostname, servname, res);
852 #else
853 const struct afd *afd;
854 struct addrinfo *cur;
855 int error;
856 char *cp, *hostname2 = NULL, *scope, *addr;
857 struct sockaddr_in6 *sin6;
859 afd = find_afd(pai->ai_family);
860 if (afd == NULL)
861 return 0;
863 if (!afd->a_scoped)
864 return explore_numeric(pai, hostname, servname, res);
866 cp = strchr(hostname, SCOPE_DELIMITER);
867 if (cp == NULL)
868 return explore_numeric(pai, hostname, servname, res);
871 * Handle special case of <scoped_address><delimiter><scope id>
873 hostname2 = strdup(hostname);
874 if (hostname2 == NULL)
875 return EAI_MEMORY;
876 /* terminate at the delimiter */
877 hostname2[cp - hostname] = '\0';
878 addr = hostname2;
879 scope = cp + 1;
881 error = explore_numeric(pai, addr, servname, res);
882 if (error == 0) {
883 u_int32_t scopeid = 0;
885 for (cur = *res; cur; cur = cur->ai_next) {
886 if (cur->ai_family != AF_INET6)
887 continue;
888 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
889 if (!ip6_str2scopeid(scope, sin6, &scopeid)) {
890 free(hostname2);
891 return(EAI_NONAME); /*%< XXX: is return OK? */
893 #ifdef HAVE_SIN6_SCOPE_ID
894 sin6->sin6_scope_id = scopeid;
895 #endif
899 free(hostname2);
901 return error;
902 #endif
905 static int
906 get_canonname(pai, ai, str)
907 const struct addrinfo *pai;
908 struct addrinfo *ai;
909 const char *str;
911 if ((pai->ai_flags & AI_CANONNAME) != 0) {
912 ai->ai_canonname = (char *)malloc(strlen(str) + 1);
913 if (ai->ai_canonname == NULL)
914 return EAI_MEMORY;
915 strcpy(ai->ai_canonname, str);
917 return 0;
920 static struct addrinfo *
921 get_ai(pai, afd, addr)
922 const struct addrinfo *pai;
923 const struct afd *afd;
924 const char *addr;
926 char *p;
927 struct addrinfo *ai;
929 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
930 + (afd->a_socklen));
931 if (ai == NULL)
932 return NULL;
934 memcpy(ai, pai, sizeof(struct addrinfo));
935 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
936 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
937 #ifdef HAVE_SA_LEN
938 ai->ai_addr->sa_len = afd->a_socklen;
939 #endif
940 ai->ai_addrlen = afd->a_socklen;
941 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
942 p = (char *)(void *)(ai->ai_addr);
943 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
944 return ai;
947 /* XXX need to malloc() the same way we do from other functions! */
948 static struct addrinfo *
949 copy_ai(pai)
950 const struct addrinfo *pai;
952 struct addrinfo *ai;
953 size_t l;
955 l = sizeof(*ai) + pai->ai_addrlen;
956 if ((ai = (struct addrinfo *)malloc(l)) == NULL)
957 return NULL;
958 memset(ai, 0, l);
959 memcpy(ai, pai, sizeof(*ai));
960 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
961 memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
963 if (pai->ai_canonname) {
964 l = strlen(pai->ai_canonname) + 1;
965 if ((ai->ai_canonname = malloc(l)) == NULL) {
966 free(ai);
967 return NULL;
969 strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */
970 } else {
971 /* just to make sure */
972 ai->ai_canonname = NULL;
975 ai->ai_next = NULL;
977 return ai;
980 static int
981 get_portmatch(const struct addrinfo *ai, const char *servname) {
983 /* get_port does not touch first argument. when matchonly == 1. */
984 /* LINTED const cast */
985 return get_port((const struct addrinfo *)ai, servname, 1);
988 static int
989 get_port(const struct addrinfo *ai, const char *servname, int matchonly) {
990 const char *proto;
991 struct servent *sp;
992 int port;
993 int allownumeric;
995 if (servname == NULL)
996 return 0;
997 switch (ai->ai_family) {
998 case AF_INET:
999 #ifdef AF_INET6
1000 case AF_INET6:
1001 #endif
1002 break;
1003 default:
1004 return 0;
1007 switch (ai->ai_socktype) {
1008 case SOCK_RAW:
1009 return EAI_SERVICE;
1010 case SOCK_DGRAM:
1011 case SOCK_STREAM:
1012 allownumeric = 1;
1013 break;
1014 case ANY:
1015 switch (ai->ai_family) {
1016 case AF_INET:
1017 #ifdef AF_INET6
1018 case AF_INET6:
1019 #endif
1020 allownumeric = 1;
1021 break;
1022 default:
1023 allownumeric = 0;
1024 break;
1026 break;
1027 default:
1028 return EAI_SOCKTYPE;
1031 if (str_isnumber(servname)) {
1032 if (!allownumeric)
1033 return EAI_SERVICE;
1034 port = atoi(servname);
1035 if (port < 0 || port > 65535)
1036 return EAI_SERVICE;
1037 port = htons(port);
1038 } else {
1039 switch (ai->ai_socktype) {
1040 case SOCK_DGRAM:
1041 proto = "udp";
1042 break;
1043 case SOCK_STREAM:
1044 proto = "tcp";
1045 break;
1046 default:
1047 proto = NULL;
1048 break;
1051 if ((sp = getservbyname(servname, proto)) == NULL)
1052 return EAI_SERVICE;
1053 port = sp->s_port;
1056 if (!matchonly) {
1057 switch (ai->ai_family) {
1058 case AF_INET:
1059 ((struct sockaddr_in *)(void *)
1060 ai->ai_addr)->sin_port = port;
1061 break;
1062 case AF_INET6:
1063 ((struct sockaddr_in6 *)(void *)
1064 ai->ai_addr)->sin6_port = port;
1065 break;
1069 return 0;
1072 static const struct afd *
1073 find_afd(af)
1074 int af;
1076 const struct afd *afd;
1078 if (af == PF_UNSPEC)
1079 return NULL;
1080 for (afd = afdl; afd->a_af; afd++) {
1081 if (afd->a_af == af)
1082 return afd;
1084 return NULL;
1088 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1089 * will take care of it.
1090 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1091 * if the code is right or not.
1093 static int
1094 addrconfig(af)
1095 int af;
1097 int s;
1099 /* XXX errno */
1100 s = socket(af, SOCK_DGRAM, 0);
1101 if (s < 0) {
1102 if (errno != EMFILE)
1103 return 0;
1104 } else
1105 close(s);
1106 return 1;
1109 /* convert a string to a scope identifier. XXX: IPv6 specific */
1110 static int
1111 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6,
1112 u_int32_t *scopeidp)
1114 u_int32_t scopeid;
1115 u_long lscopeid;
1116 struct in6_addr *a6 = &sin6->sin6_addr;
1117 char *ep;
1119 /* empty scopeid portion is invalid */
1120 if (*scope == '\0')
1121 return (0);
1123 #ifdef USE_IFNAMELINKID
1124 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
1125 IN6_IS_ADDR_MC_NODELOCAL(a6)) {
1127 * Using interface names as link indices can be allowed
1128 * only when we can assume a one-to-one mappings between
1129 * links and interfaces. See comments in getnameinfo.c.
1131 scopeid = if_nametoindex(scope);
1132 if (scopeid == 0)
1133 goto trynumeric;
1134 *scopeidp = scopeid;
1135 return (1);
1137 #endif
1139 /* still unclear about literal, allow numeric only - placeholder */
1140 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1141 goto trynumeric;
1142 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1143 goto trynumeric;
1144 else
1145 goto trynumeric; /*%< global */
1146 /* try to convert to a numeric id as a last resort */
1147 trynumeric:
1148 errno = 0;
1149 lscopeid = strtoul(scope, &ep, 10);
1150 scopeid = lscopeid & 0xffffffff;
1151 if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) {
1152 *scopeidp = scopeid;
1153 return (1);
1154 } else
1155 return (0);
1158 struct addrinfo *
1159 hostent2addrinfo(hp, pai)
1160 struct hostent *hp;
1161 const struct addrinfo *pai;
1163 int i, af, error = 0;
1164 char **aplist = NULL, *ap;
1165 struct addrinfo sentinel, *cur;
1166 const struct afd *afd;
1168 af = hp->h_addrtype;
1169 if (pai->ai_family != AF_UNSPEC && af != pai->ai_family)
1170 return(NULL);
1172 afd = find_afd(af);
1173 if (afd == NULL)
1174 return(NULL);
1176 aplist = hp->h_addr_list;
1178 memset(&sentinel, 0, sizeof(sentinel));
1179 cur = &sentinel;
1181 for (i = 0; (ap = aplist[i]) != NULL; i++) {
1182 #if 0 /*%< the trick seems too much */
1183 af = hp->h_addr_list;
1184 if (af == AF_INET6 &&
1185 IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
1186 af = AF_INET;
1187 ap = ap + sizeof(struct in6_addr)
1188 - sizeof(struct in_addr);
1190 afd = find_afd(af);
1191 if (afd == NULL)
1192 continue;
1193 #endif /* 0 */
1195 GET_AI(cur->ai_next, afd, ap);
1197 /* GET_PORT(cur->ai_next, servname); */
1198 if ((pai->ai_flags & AI_CANONNAME) != 0) {
1200 * RFC2553 says that ai_canonname will be set only for
1201 * the first element. we do it for all the elements,
1202 * just for convenience.
1204 GET_CANONNAME(cur->ai_next, hp->h_name);
1206 while (cur->ai_next) /*%< no need to loop, actually. */
1207 cur = cur->ai_next;
1208 continue;
1210 free:
1211 if (cur->ai_next)
1212 freeaddrinfo(cur->ai_next);
1213 cur->ai_next = NULL;
1214 /* continue, without tht pointer CUR advanced. */
1217 return(sentinel.ai_next);
1220 struct addrinfo *
1221 addr2addrinfo(pai, cp)
1222 const struct addrinfo *pai;
1223 const char *cp;
1225 const struct afd *afd;
1227 afd = find_afd(pai->ai_family);
1228 if (afd == NULL)
1229 return(NULL);
1231 return(get_ai(pai, afd, cp));
1234 static struct net_data *
1235 init()
1237 struct net_data *net_data;
1239 if (!(net_data = net_data_init(NULL)))
1240 goto error;
1241 if (!net_data->ho) {
1242 net_data->ho = (*net_data->irs->ho_map)(net_data->irs);
1243 if (!net_data->ho || !net_data->res) {
1244 error:
1245 errno = EIO;
1246 if (net_data && net_data->res)
1247 RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL);
1248 return (NULL);
1251 (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL);
1254 return (net_data);