1 /* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 * Issues to be discussed:
34 *\li Thread safe-ness must be checked.
35 *\li 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 *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
39 * says to use inet_aton() to convert IPv4 numeric to binary (allows
40 * classful form as a result).
41 * current code - disallow classful form for IPv4 (due to use of inet_pton).
42 *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
44 * current code - SEGV on freeaddrinfo(NULL)
46 *\li We use getipnodebyname() just for thread-safeness. There's no intent
47 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 *\li The code filters out AFs that are not supported by the kernel,
50 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
51 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 *\li (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
54 * (1) what should we do against numeric hostname (2) what should we do
55 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
56 * non-loopback address configured? global address configured?
57 * \par Additional Issue:
58 * To avoid search order issue, we have a big amount of code duplicate
59 * from gethnamaddr.c and some other places. The issues that there's no
60 * lower layer function to lookup "IPv4 or IPv6" record. Calling
61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
63 * \li The code makes use of following calls when asked to resolver with
64 * ai_family = PF_UNSPEC:
65 *\code getipnodebyname(host, AF_INET6);
66 * getipnodebyname(host, AF_INET);
68 * \li This will result in the following queries if the node is configure to
69 * prefer /etc/hosts than DNS:
71 * lookup /etc/hosts for IPv6 address
72 * lookup DNS for IPv6 address
73 * lookup /etc/hosts for IPv4 address
74 * lookup DNS for IPv4 address
76 * which may not meet people's requirement.
77 * \li The right thing to happen is to have underlying layer which does
78 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
79 * This would result in a bit of code duplicate with _dns_ghbyname() and
83 #include "port_before.h"
85 #include <sys/types.h>
86 #include <sys/param.h>
87 #include <sys/socket.h>
90 #include <netinet/in.h>
92 #include <arpa/inet.h>
93 #include <arpa/nameser.h>
108 #include <isc/assertions.h>
110 #include "port_after.h"
112 #include "irs_data.h"
119 static const char in_addrany
[] = { 0, 0, 0, 0 };
120 static const char in6_addrany
[] = {
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
123 static const char in_loopback
[] = { 127, 0, 0, 1 };
124 static const char in6_loopback
[] = {
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
128 static const struct afd
{
133 const char *a_addrany
;
134 const char *a_loopback
;
137 {PF_INET6
, sizeof(struct in6_addr
),
138 sizeof(struct sockaddr_in6
),
139 offsetof(struct sockaddr_in6
, sin6_addr
),
140 in6_addrany
, in6_loopback
, 1},
141 {PF_INET
, sizeof(struct in_addr
),
142 sizeof(struct sockaddr_in
),
143 offsetof(struct sockaddr_in
, sin_addr
),
144 in_addrany
, in_loopback
, 0},
145 {0, 0, 0, 0, NULL
, NULL
, 0},
152 const char *e_protostr
;
154 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
155 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
156 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
159 static const struct explore explore
[] = {
161 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
163 { PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
164 { PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
165 { PF_INET6
, SOCK_RAW
, ANY
, NULL
, 0x05 },
166 { PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
167 { PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
168 { PF_INET
, SOCK_RAW
, ANY
, NULL
, 0x05 },
169 { -1, 0, 0, NULL
, 0 },
174 static int str_isnumber
__P((const char *));
175 static int explore_fqdn
__P((const struct addrinfo
*, const char *,
176 const char *, struct addrinfo
**));
177 static int explore_copy
__P((const struct addrinfo
*, const struct addrinfo
*,
178 struct addrinfo
**));
179 static int explore_null
__P((const struct addrinfo
*,
180 const char *, struct addrinfo
**));
181 static int explore_numeric
__P((const struct addrinfo
*, const char *,
182 const char *, struct addrinfo
**));
183 static int explore_numeric_scope
__P((const struct addrinfo
*, const char *,
184 const char *, struct addrinfo
**));
185 static int get_canonname
__P((const struct addrinfo
*,
186 struct addrinfo
*, const char *));
187 static struct addrinfo
*get_ai
__P((const struct addrinfo
*,
188 const struct afd
*, const char *));
189 static struct addrinfo
*copy_ai
__P((const struct addrinfo
*));
190 static int get_portmatch
__P((const struct addrinfo
*, const char *));
191 static int get_port
__P((const struct addrinfo
*, const char *, int));
192 static const struct afd
*find_afd
__P((int));
193 static int addrconfig
__P((int));
194 static int ip6_str2scopeid
__P((char *, struct sockaddr_in6
*,
195 u_int32_t
*scopeidp
));
196 static struct net_data
*init
__P((void));
198 struct addrinfo
*hostent2addrinfo
__P((struct hostent
*,
199 const struct addrinfo
*));
200 struct addrinfo
*addr2addrinfo
__P((const struct addrinfo
*,
204 static const char *ai_errlist
[] = {
206 "Address family for hostname not supported", /*%< EAI_ADDRFAMILY */
207 "Temporary failure in name resolution", /*%< EAI_AGAIN */
208 "Invalid value for ai_flags", /*%< EAI_BADFLAGS */
209 "Non-recoverable failure in name resolution", /*%< EAI_FAIL */
210 "ai_family not supported", /*%< EAI_FAMILY */
211 "Memory allocation failure", /*%< EAI_MEMORY */
212 "No address associated with hostname", /*%< EAI_NODATA */
213 "hostname nor servname provided, or not known", /*%< EAI_NONAME */
214 "servname not supported for ai_socktype", /*%< EAI_SERVICE */
215 "ai_socktype not supported", /*%< EAI_SOCKTYPE */
216 "System error returned in errno", /*%< EAI_SYSTEM */
217 "Invalid value for hints", /*%< EAI_BADHINTS */
218 "Resolved protocol is unknown", /*%< EAI_PROTOCOL */
219 "Unknown error", /*%< EAI_MAX */
223 /* XXX macros that make external reference is BAD. */
225 #define GET_AI(ai, afd, addr) \
227 /* external reference: pai, error, and label free */ \
228 (ai) = get_ai(pai, (afd), (addr)); \
229 if ((ai) == NULL) { \
230 error = EAI_MEMORY; \
233 } while (/*CONSTCOND*/0)
235 #define GET_PORT(ai, serv) \
237 /* external reference: error and label free */ \
238 error = get_port((ai), (serv), 0); \
241 } while (/*CONSTCOND*/0)
243 #define GET_CANONNAME(ai, str) \
245 /* external reference: pai, error and label free */ \
246 error = get_canonname(pai, (ai), (str)); \
249 } while (/*CONSTCOND*/0)
252 #define SETERROR(err) \
254 /* external reference: error, and label bad */ \
258 } while (/*CONSTCOND*/0)
260 #define SETERROR(err) \
262 /* external reference: error, and label bad */ \
264 if (error == error) \
266 } while (/*CONSTCOND*/0)
270 #define MATCH_FAMILY(x, y, w) \
271 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
272 #define MATCH(x, y, w) \
273 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
275 #if 0 /*%< bind8 has its own version */
280 if (ecode
< 0 || ecode
> EAI_MAX
)
282 return ai_errlist
[ecode
];
290 struct addrinfo
*next
;
294 if (ai
->ai_canonname
)
295 free(ai
->ai_canonname
);
296 /* no need to free(ai->ai_addr) */
312 (void)strtoul(p
, &ep
, 10);
313 if (errno
== 0 && ep
&& *ep
== '\0')
320 getaddrinfo(hostname
, servname
, hints
, res
)
321 const char *hostname
, *servname
;
322 const struct addrinfo
*hints
;
323 struct addrinfo
**res
;
325 struct addrinfo sentinel
;
326 struct addrinfo
*cur
;
328 struct addrinfo ai
, ai0
, *afai
= NULL
;
329 struct addrinfo
*pai
;
330 const struct explore
*ex
;
332 memset(&sentinel
, 0, sizeof(sentinel
));
336 pai
->ai_family
= PF_UNSPEC
;
337 pai
->ai_socktype
= ANY
;
338 pai
->ai_protocol
= ANY
;
339 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
341 * clear _ai_pad to preserve binary
342 * compatibility with previously compiled 64-bit
343 * applications in a pre-SUSv3 environment by
344 * guaranteeing the upper 32-bits are empty.
349 pai
->ai_canonname
= NULL
;
353 if (hostname
== NULL
&& servname
== NULL
)
356 /* error check for hints */
357 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
358 hints
->ai_addr
|| hints
->ai_next
)
359 SETERROR(EAI_BADHINTS
); /*%< xxx */
360 if (hints
->ai_flags
& ~AI_MASK
)
361 SETERROR(EAI_BADFLAGS
);
362 switch (hints
->ai_family
) {
368 SETERROR(EAI_FAMILY
);
370 memcpy(pai
, hints
, sizeof(*pai
));
372 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
374 * We need to clear _ai_pad to preserve binary
375 * compatibility. See prior comment.
380 * if both socktype/protocol are specified, check if they
381 * are meaningful combination.
383 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
384 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
385 if (pai
->ai_family
!= ex
->e_af
)
387 if (ex
->e_socktype
== ANY
)
389 if (ex
->e_protocol
== ANY
)
391 if (pai
->ai_socktype
== ex
->e_socktype
&&
392 pai
->ai_protocol
!= ex
->e_protocol
) {
393 SETERROR(EAI_BADHINTS
);
400 * post-2553: AI_ALL and AI_V4MAPPED are effective only against
401 * AF_INET6 query. They needs to be ignored if specified in other
404 switch (pai
->ai_flags
& (AI_ALL
| AI_V4MAPPED
)) {
406 case AI_ALL
| AI_V4MAPPED
:
407 if (pai
->ai_family
!= AF_INET6
)
408 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
413 SETERROR(EAI_BADFLAGS
);
415 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
421 * check for special cases. (1) numeric servname is disallowed if
422 * socktype/protocol are left unspecified. (2) servname is disallowed
423 * for raw and other inet{,6} sockets.
425 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
427 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
430 ai0
= *pai
; /* backup *pai */
432 if (pai
->ai_family
== PF_UNSPEC
) {
434 pai
->ai_family
= PF_INET6
;
436 pai
->ai_family
= PF_INET
;
439 error
= get_portmatch(pai
, servname
);
448 /* NULL hostname, or numeric hostname */
449 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
452 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
454 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
456 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
459 if (pai
->ai_family
== PF_UNSPEC
)
460 pai
->ai_family
= ex
->e_af
;
461 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
462 pai
->ai_socktype
= ex
->e_socktype
;
463 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
464 pai
->ai_protocol
= ex
->e_protocol
;
467 * if the servname does not match socktype/protocol, ignore it.
469 if (get_portmatch(pai
, servname
) != 0)
472 if (hostname
== NULL
) {
474 * filter out AFs that are not supported by the kernel
477 if (!addrconfig(pai
->ai_family
))
479 error
= explore_null(pai
, servname
, &cur
->ai_next
);
481 error
= explore_numeric_scope(pai
, hostname
, servname
,
487 while (cur
&& cur
->ai_next
)
493 * If numreic representation of AF1 can be interpreted as FQDN
494 * representation of AF2, we need to think again about the code below.
496 if (sentinel
.ai_next
)
499 if (pai
->ai_flags
& AI_NUMERICHOST
)
500 SETERROR(EAI_NONAME
);
501 if (hostname
== NULL
)
502 SETERROR(EAI_NONAME
);
505 * hostname as alphabetical name.
506 * We'll make sure that
507 * - if returning addrinfo list is empty, return non-zero error
508 * value (already known one or EAI_NONAME).
510 * + if we haven't had any errors, return 0 (i.e. success).
511 * + if we've had an error, free the list and return the error.
512 * without any assumption on the behavior of explore_fqdn().
515 /* first, try to query DNS for all possible address families. */
517 error
= explore_fqdn(pai
, hostname
, servname
, &afai
);
524 error
= EAI_NONAME
; /*%< we've had no errors. */
529 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
532 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
535 if (pai
->ai_family
== PF_UNSPEC
)
536 pai
->ai_family
= ex
->e_af
;
538 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
540 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
541 WILD_SOCKTYPE(ex
))) {
544 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
545 WILD_PROTOCOL(ex
))) {
551 * If AI_ADDRCONFIG is specified, check if we are
552 * expected to return the address family or not.
554 if ((pai
->ai_flags
& AI_ADDRCONFIG
) != 0 &&
555 !addrconfig(pai
->ai_family
))
559 if (pai
->ai_family
== PF_UNSPEC
)
560 pai
->ai_family
= ex
->e_af
;
561 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
562 pai
->ai_socktype
= ex
->e_socktype
;
563 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
564 pai
->ai_protocol
= ex
->e_protocol
;
567 * if the servname does not match socktype/protocol, ignore it.
569 if (get_portmatch(pai
, servname
) != 0)
572 if ((error
= explore_copy(pai
, afai
, &cur
->ai_next
)) != 0) {
577 while (cur
&& cur
->ai_next
)
581 freeaddrinfo(afai
); /*%< afai must not be NULL at this point. */
583 if (sentinel
.ai_next
) {
585 *res
= sentinel
.ai_next
;
589 * All the process succeeded, but we've had an empty list.
590 * This can happen if the given hints do not match our
598 if (sentinel
.ai_next
)
599 freeaddrinfo(sentinel
.ai_next
);
605 * FQDN hostname, DNS lookup
608 explore_fqdn(pai
, hostname
, servname
, res
)
609 const struct addrinfo
*pai
;
610 const char *hostname
;
611 const char *servname
;
612 struct addrinfo
**res
;
614 struct addrinfo
*result
;
615 struct addrinfo
*cur
;
616 struct net_data
*net_data
= init();
619 char tmp
[NS_MAXDNAME
];
622 INSIST(res
!= NULL
&& *res
== NULL
);
625 * if the servname does not match socktype/protocol, ignore it.
627 if (get_portmatch(pai
, servname
) != 0)
630 if (!net_data
|| !(ho
= net_data
->ho
))
632 #if 0 /*%< XXX (notyet) */
633 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
634 net_data
->ho_last
->h_addrtype
== af
) {
635 if (ns_samename(name
, net_data
->ho_last
->h_name
) == 1)
636 return (net_data
->ho_last
);
637 for (hap
= net_data
->ho_last
->h_aliases
; hap
&& *hap
; hap
++)
638 if (ns_samename(name
, *hap
) == 1)
639 return (net_data
->ho_last
);
642 if (!strchr(hostname
, '.') &&
643 (cp
= res_hostalias(net_data
->res
, hostname
,
646 result
= (*ho
->addrinfo
)(ho
, hostname
, pai
);
647 if (!net_data
->ho_stayopen
) {
650 if (result
== NULL
) {
668 case NETDB_SUCCESS
: /*%< should be impossible... */
675 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
676 GET_PORT(cur
, servname
); /*%< XXX: redundant lookups... */
677 /* canonname should already be filled. */
686 freeaddrinfo(result
);
691 explore_copy(pai
, src0
, res
)
692 const struct addrinfo
*pai
; /*%< seed */
693 const struct addrinfo
*src0
; /*%< source */
694 struct addrinfo
**res
;
697 struct addrinfo sentinel
, *cur
;
698 const struct addrinfo
*src
;
701 sentinel
.ai_next
= NULL
;
704 for (src
= src0
; src
!= NULL
; src
= src
->ai_next
) {
705 if (src
->ai_family
!= pai
->ai_family
)
708 cur
->ai_next
= copy_ai(src
);
714 cur
->ai_next
->ai_socktype
= pai
->ai_socktype
;
715 cur
->ai_next
->ai_protocol
= pai
->ai_protocol
;
719 *res
= sentinel
.ai_next
;
723 freeaddrinfo(sentinel
.ai_next
);
729 * passive socket -> anyaddr (0.0.0.0 or ::)
730 * non-passive socket -> localhost (127.0.0.1 or ::1)
733 explore_null(pai
, servname
, res
)
734 const struct addrinfo
*pai
;
735 const char *servname
;
736 struct addrinfo
**res
;
738 const struct afd
*afd
;
739 struct addrinfo
*cur
;
740 struct addrinfo sentinel
;
744 sentinel
.ai_next
= NULL
;
747 afd
= find_afd(pai
->ai_family
);
751 if (pai
->ai_flags
& AI_PASSIVE
) {
752 GET_AI(cur
->ai_next
, afd
, afd
->a_addrany
);
754 * GET_CANONNAME(cur->ai_next, "anyaddr");
756 GET_PORT(cur
->ai_next
, servname
);
758 GET_AI(cur
->ai_next
, afd
, afd
->a_loopback
);
760 * GET_CANONNAME(cur->ai_next, "localhost");
762 GET_PORT(cur
->ai_next
, servname
);
766 *res
= sentinel
.ai_next
;
770 if (sentinel
.ai_next
)
771 freeaddrinfo(sentinel
.ai_next
);
779 explore_numeric(pai
, hostname
, servname
, res
)
780 const struct addrinfo
*pai
;
781 const char *hostname
;
782 const char *servname
;
783 struct addrinfo
**res
;
785 const struct afd
*afd
;
786 struct addrinfo
*cur
;
787 struct addrinfo sentinel
;
792 sentinel
.ai_next
= NULL
;
795 afd
= find_afd(pai
->ai_family
);
800 #if 0 /*X/Open spec*/
802 if (inet_aton(hostname
, (struct in_addr
*)pton
) == 1) {
803 if (pai
->ai_family
== afd
->a_af
||
804 pai
->ai_family
== PF_UNSPEC
/*?*/) {
805 GET_AI(cur
->ai_next
, afd
, pton
);
806 GET_PORT(cur
->ai_next
, servname
);
810 SETERROR(EAI_FAMILY
); /*xxx*/
815 if (inet_pton(afd
->a_af
, hostname
, pton
) == 1) {
816 if (pai
->ai_family
== afd
->a_af
||
817 pai
->ai_family
== PF_UNSPEC
/*?*/) {
818 GET_AI(cur
->ai_next
, afd
, pton
);
819 GET_PORT(cur
->ai_next
, servname
);
823 SETERROR(EAI_FAMILY
); /*xxx*/
828 *res
= sentinel
.ai_next
;
833 if (sentinel
.ai_next
)
834 freeaddrinfo(sentinel
.ai_next
);
839 * numeric hostname with scope
842 explore_numeric_scope(pai
, hostname
, servname
, res
)
843 const struct addrinfo
*pai
;
844 const char *hostname
;
845 const char *servname
;
846 struct addrinfo
**res
;
848 #ifndef SCOPE_DELIMITER
849 return explore_numeric(pai
, hostname
, servname
, res
);
851 const struct afd
*afd
;
852 struct addrinfo
*cur
;
854 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
855 struct sockaddr_in6
*sin6
;
857 afd
= find_afd(pai
->ai_family
);
862 return explore_numeric(pai
, hostname
, servname
, res
);
864 cp
= strchr(hostname
, SCOPE_DELIMITER
);
866 return explore_numeric(pai
, hostname
, servname
, res
);
869 * Handle special case of <scoped_address><delimiter><scope id>
871 hostname2
= strdup(hostname
);
872 if (hostname2
== NULL
)
874 /* terminate at the delimiter */
875 hostname2
[cp
- hostname
] = '\0';
879 error
= explore_numeric(pai
, addr
, servname
, res
);
881 u_int32_t scopeid
= 0;
883 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
884 if (cur
->ai_family
!= AF_INET6
)
886 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
887 if (!ip6_str2scopeid(scope
, sin6
, &scopeid
)) {
889 return(EAI_NONAME
); /*%< XXX: is return OK? */
891 #ifdef HAVE_SIN6_SCOPE_ID
892 sin6
->sin6_scope_id
= scopeid
;
904 get_canonname(pai
, ai
, str
)
905 const struct addrinfo
*pai
;
909 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
910 ai
->ai_canonname
= (char *)malloc(strlen(str
) + 1);
911 if (ai
->ai_canonname
== NULL
)
913 strcpy(ai
->ai_canonname
, str
);
918 static struct addrinfo
*
919 get_ai(pai
, afd
, addr
)
920 const struct addrinfo
*pai
;
921 const struct afd
*afd
;
927 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
932 memcpy(ai
, pai
, sizeof(struct addrinfo
));
933 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
934 memset(ai
->ai_addr
, 0, (size_t)afd
->a_socklen
);
936 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
938 ai
->ai_addrlen
= afd
->a_socklen
;
939 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
940 p
= (char *)(void *)(ai
->ai_addr
);
941 memcpy(p
+ afd
->a_off
, addr
, (size_t)afd
->a_addrlen
);
945 /* XXX need to malloc() the same way we do from other functions! */
946 static struct addrinfo
*
948 const struct addrinfo
*pai
;
953 l
= sizeof(*ai
) + pai
->ai_addrlen
;
954 if ((ai
= (struct addrinfo
*)malloc(l
)) == NULL
)
957 memcpy(ai
, pai
, sizeof(*ai
));
958 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
959 memcpy(ai
->ai_addr
, pai
->ai_addr
, pai
->ai_addrlen
);
961 if (pai
->ai_canonname
) {
962 l
= strlen(pai
->ai_canonname
) + 1;
963 if ((ai
->ai_canonname
= malloc(l
)) == NULL
) {
967 strcpy(ai
->ai_canonname
, pai
->ai_canonname
); /* (checked) */
969 /* just to make sure */
970 ai
->ai_canonname
= NULL
;
979 get_portmatch(const struct addrinfo
*ai
, const char *servname
) {
981 /* get_port does not touch first argument. when matchonly == 1. */
982 /* LINTED const cast */
983 return get_port((const struct addrinfo
*)ai
, servname
, 1);
987 get_port(const struct addrinfo
*ai
, const char *servname
, int matchonly
) {
993 if (servname
== NULL
)
995 switch (ai
->ai_family
) {
1005 switch (ai
->ai_socktype
) {
1013 switch (ai
->ai_family
) {
1026 return EAI_SOCKTYPE
;
1029 if (str_isnumber(servname
)) {
1032 port
= atoi(servname
);
1033 if (port
< 0 || port
> 65535)
1037 switch (ai
->ai_socktype
) {
1049 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1055 switch (ai
->ai_family
) {
1057 ((struct sockaddr_in
*)(void *)
1058 ai
->ai_addr
)->sin_port
= port
;
1061 ((struct sockaddr_in6
*)(void *)
1062 ai
->ai_addr
)->sin6_port
= port
;
1070 static const struct afd
*
1074 const struct afd
*afd
;
1076 if (af
== PF_UNSPEC
)
1078 for (afd
= afdl
; afd
->a_af
; afd
++) {
1079 if (afd
->a_af
== af
)
1086 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1087 * will take care of it.
1088 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1089 * if the code is right or not.
1098 s
= socket(af
, SOCK_DGRAM
, 0);
1100 if (errno
!= EMFILE
)
1107 /* convert a string to a scope identifier. XXX: IPv6 specific */
1109 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
,
1110 u_int32_t
*scopeidp
)
1114 struct in6_addr
*a6
= &sin6
->sin6_addr
;
1117 /* empty scopeid portion is invalid */
1121 #ifdef USE_IFNAMELINKID
1122 if (IN6_IS_ADDR_LINKLOCAL(a6
) || IN6_IS_ADDR_MC_LINKLOCAL(a6
) ||
1123 IN6_IS_ADDR_MC_NODELOCAL(a6
)) {
1125 * Using interface names as link indices can be allowed
1126 * only when we can assume a one-to-one mappings between
1127 * links and interfaces. See comments in getnameinfo.c.
1129 scopeid
= if_nametoindex(scope
);
1132 *scopeidp
= scopeid
;
1137 /* still unclear about literal, allow numeric only - placeholder */
1138 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1140 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1143 goto trynumeric
; /*%< global */
1144 /* try to convert to a numeric id as a last resort */
1147 lscopeid
= strtoul(scope
, &ep
, 10);
1148 scopeid
= lscopeid
& 0xffffffff;
1149 if (errno
== 0 && ep
&& *ep
== '\0' && scopeid
== lscopeid
) {
1150 *scopeidp
= scopeid
;
1157 hostent2addrinfo(hp
, pai
)
1159 const struct addrinfo
*pai
;
1161 int i
, af
, error
= 0;
1162 char **aplist
= NULL
, *ap
;
1163 struct addrinfo sentinel
, *cur
;
1164 const struct afd
*afd
;
1166 af
= hp
->h_addrtype
;
1167 if (pai
->ai_family
!= AF_UNSPEC
&& af
!= pai
->ai_family
)
1174 aplist
= hp
->h_addr_list
;
1176 memset(&sentinel
, 0, sizeof(sentinel
));
1179 for (i
= 0; (ap
= aplist
[i
]) != NULL
; i
++) {
1180 #if 0 /*%< the trick seems too much */
1181 af
= hp
->h_addr_list
;
1182 if (af
== AF_INET6
&&
1183 IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
1185 ap
= ap
+ sizeof(struct in6_addr
)
1186 - sizeof(struct in_addr
);
1193 GET_AI(cur
->ai_next
, afd
, ap
);
1195 /* GET_PORT(cur->ai_next, servname); */
1196 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
1198 * RFC2553 says that ai_canonname will be set only for
1199 * the first element. we do it for all the elements,
1200 * just for convenience.
1202 GET_CANONNAME(cur
->ai_next
, hp
->h_name
);
1204 while (cur
->ai_next
) /*%< no need to loop, actually. */
1210 freeaddrinfo(cur
->ai_next
);
1211 cur
->ai_next
= NULL
;
1212 /* continue, without tht pointer CUR advanced. */
1215 return(sentinel
.ai_next
);
1219 addr2addrinfo(pai
, cp
)
1220 const struct addrinfo
*pai
;
1223 const struct afd
*afd
;
1225 afd
= find_afd(pai
->ai_family
);
1229 return(get_ai(pai
, afd
, cp
));
1232 static struct net_data
*
1235 struct net_data
*net_data
;
1237 if (!(net_data
= net_data_init(NULL
)))
1239 if (!net_data
->ho
) {
1240 net_data
->ho
= (*net_data
->irs
->ho_map
)(net_data
->irs
);
1241 if (!net_data
->ho
|| !net_data
->res
) {
1244 if (net_data
&& net_data
->res
)
1245 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1249 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);