3 /* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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
46 * current code - SEGV on freeaddrinfo(NULL)
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
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
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
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);
70 * \li This will result in the following queries if the node is configure to
71 * prefer /etc/hosts than DNS:
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
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
85 #include "port_before.h"
87 #include <sys/types.h>
88 #include <sys/param.h>
89 #include <sys/socket.h>
92 #include <netinet/in.h>
94 #include <arpa/inet.h>
95 #include <arpa/nameser.h>
110 #include <isc/assertions.h>
112 #include "port_after.h"
114 #include "irs_data.h"
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
{
135 const char *a_addrany
;
136 const char *a_loopback
;
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},
154 const char *e_protostr
;
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
[] = {
163 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
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 },
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
*,
206 static const char *ai_errlist
[] = {
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 */
225 /* XXX macros that make external reference is BAD. */
227 #define GET_AI(ai, afd, addr) \
229 /* external reference: pai, error, and label free */ \
230 (ai) = get_ai(pai, (afd), (addr)); \
231 if ((ai) == NULL) { \
232 error = EAI_MEMORY; \
235 } while (/*CONSTCOND*/0)
237 #define GET_PORT(ai, serv) \
239 /* external reference: error and label free */ \
240 error = get_port((ai), (serv), 0); \
243 } while (/*CONSTCOND*/0)
245 #define GET_CANONNAME(ai, str) \
247 /* external reference: pai, error and label free */ \
248 error = get_canonname(pai, (ai), (str)); \
251 } while (/*CONSTCOND*/0)
254 #define SETERROR(err) \
256 /* external reference: error, and label bad */ \
260 } while (/*CONSTCOND*/0)
262 #define SETERROR(err) \
264 /* external reference: error, and label bad */ \
266 if (error == error) \
268 } while (/*CONSTCOND*/0)
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 */
282 if (ecode
< 0 || ecode
> EAI_MAX
)
284 return ai_errlist
[ecode
];
292 struct addrinfo
*next
;
296 if (ai
->ai_canonname
)
297 free(ai
->ai_canonname
);
298 /* no need to free(ai->ai_addr) */
314 (void)strtoul(p
, &ep
, 10);
315 if (errno
== 0 && ep
&& *ep
== '\0')
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
;
330 struct addrinfo ai
, ai0
, *afai
= NULL
;
331 struct addrinfo
*pai
;
332 const struct explore
*ex
;
334 memset(&sentinel
, 0, sizeof(sentinel
));
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.
351 pai
->ai_canonname
= NULL
;
355 if (hostname
== NULL
&& servname
== NULL
)
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
) {
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.
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
)
389 if (ex
->e_socktype
== ANY
)
391 if (ex
->e_protocol
== ANY
)
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
406 switch (pai
->ai_flags
& (AI_ALL
| AI_V4MAPPED
)) {
408 case AI_ALL
| AI_V4MAPPED
:
409 if (pai
->ai_family
!= AF_INET6
)
410 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
415 SETERROR(EAI_BADFLAGS
);
417 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
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)
429 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
432 ai0
= *pai
; /* backup *pai */
434 if (pai
->ai_family
== PF_UNSPEC
) {
436 pai
->ai_family
= PF_INET6
;
438 pai
->ai_family
= PF_INET
;
441 error
= get_portmatch(pai
, servname
);
450 /* NULL hostname, or numeric hostname */
451 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
454 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
456 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
458 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
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)
474 if (hostname
== NULL
) {
476 * filter out AFs that are not supported by the kernel
479 if (!addrconfig(pai
->ai_family
))
481 error
= explore_null(pai
, servname
, &cur
->ai_next
);
483 error
= explore_numeric_scope(pai
, hostname
, servname
,
489 while (cur
&& cur
->ai_next
)
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
)
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).
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. */
519 error
= explore_fqdn(pai
, hostname
, servname
, &afai
);
526 error
= EAI_NONAME
; /*%< we've had no errors. */
531 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
534 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
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
)))
542 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
543 WILD_SOCKTYPE(ex
))) {
546 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
547 WILD_PROTOCOL(ex
))) {
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
))
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)
574 if ((error
= explore_copy(pai
, afai
, &cur
->ai_next
)) != 0) {
579 while (cur
&& cur
->ai_next
)
583 freeaddrinfo(afai
); /*%< afai must not be NULL at this point. */
585 if (sentinel
.ai_next
) {
587 *res
= sentinel
.ai_next
;
591 * All the process succeeded, but we've had an empty list.
592 * This can happen if the given hints do not match our
600 if (sentinel
.ai_next
)
601 freeaddrinfo(sentinel
.ai_next
);
607 * FQDN hostname, DNS lookup
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();
621 char tmp
[NS_MAXDNAME
];
624 INSIST(res
!= NULL
&& *res
== NULL
);
627 * if the servname does not match socktype/protocol, ignore it.
629 if (get_portmatch(pai
, servname
) != 0)
632 if (!net_data
|| !(ho
= net_data
->ho
))
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
);
644 if (!strchr(hostname
, '.') &&
645 (cp
= res_hostalias(net_data
->res
, hostname
,
648 result
= (*ho
->addrinfo
)(ho
, hostname
, pai
);
649 if (!net_data
->ho_stayopen
) {
652 if (result
== NULL
) {
670 case NETDB_SUCCESS
: /*%< should be impossible... */
677 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
678 GET_PORT(cur
, servname
); /*%< XXX: redundant lookups... */
679 /* canonname should already be filled. */
688 freeaddrinfo(result
);
693 explore_copy(pai
, src0
, res
)
694 const struct addrinfo
*pai
; /*%< seed */
695 const struct addrinfo
*src0
; /*%< source */
696 struct addrinfo
**res
;
699 struct addrinfo sentinel
, *cur
;
700 const struct addrinfo
*src
;
703 sentinel
.ai_next
= NULL
;
706 for (src
= src0
; src
!= NULL
; src
= src
->ai_next
) {
707 if (src
->ai_family
!= pai
->ai_family
)
710 cur
->ai_next
= copy_ai(src
);
716 cur
->ai_next
->ai_socktype
= pai
->ai_socktype
;
717 cur
->ai_next
->ai_protocol
= pai
->ai_protocol
;
721 *res
= sentinel
.ai_next
;
725 freeaddrinfo(sentinel
.ai_next
);
731 * passive socket -> anyaddr (0.0.0.0 or ::)
732 * non-passive socket -> localhost (127.0.0.1 or ::1)
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
;
746 sentinel
.ai_next
= NULL
;
749 afd
= find_afd(pai
->ai_family
);
753 if (pai
->ai_flags
& AI_PASSIVE
) {
754 GET_AI(cur
->ai_next
, afd
, afd
->a_addrany
);
756 * GET_CANONNAME(cur->ai_next, "anyaddr");
758 GET_PORT(cur
->ai_next
, servname
);
760 GET_AI(cur
->ai_next
, afd
, afd
->a_loopback
);
762 * GET_CANONNAME(cur->ai_next, "localhost");
764 GET_PORT(cur
->ai_next
, servname
);
768 *res
= sentinel
.ai_next
;
772 if (sentinel
.ai_next
)
773 freeaddrinfo(sentinel
.ai_next
);
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
;
794 sentinel
.ai_next
= NULL
;
797 afd
= find_afd(pai
->ai_family
);
802 #if 0 /*X/Open spec*/
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
);
812 SETERROR(EAI_FAMILY
); /*xxx*/
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
);
825 SETERROR(EAI_FAMILY
); /*xxx*/
830 *res
= sentinel
.ai_next
;
835 if (sentinel
.ai_next
)
836 freeaddrinfo(sentinel
.ai_next
);
841 * numeric hostname with scope
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
);
853 const struct afd
*afd
;
854 struct addrinfo
*cur
;
856 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
857 struct sockaddr_in6
*sin6
;
859 afd
= find_afd(pai
->ai_family
);
864 return explore_numeric(pai
, hostname
, servname
, res
);
866 cp
= strchr(hostname
, SCOPE_DELIMITER
);
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
)
876 /* terminate at the delimiter */
877 hostname2
[cp
- hostname
] = '\0';
881 error
= explore_numeric(pai
, addr
, servname
, res
);
883 u_int32_t scopeid
= 0;
885 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
886 if (cur
->ai_family
!= AF_INET6
)
888 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
889 if (!ip6_str2scopeid(scope
, sin6
, &scopeid
)) {
891 return(EAI_NONAME
); /*%< XXX: is return OK? */
893 #ifdef HAVE_SIN6_SCOPE_ID
894 sin6
->sin6_scope_id
= scopeid
;
906 get_canonname(pai
, ai
, str
)
907 const struct addrinfo
*pai
;
911 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
912 ai
->ai_canonname
= (char *)malloc(strlen(str
) + 1);
913 if (ai
->ai_canonname
== NULL
)
915 strcpy(ai
->ai_canonname
, str
);
920 static struct addrinfo
*
921 get_ai(pai
, afd
, addr
)
922 const struct addrinfo
*pai
;
923 const struct afd
*afd
;
929 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
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
);
938 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
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
);
947 /* XXX need to malloc() the same way we do from other functions! */
948 static struct addrinfo
*
950 const struct addrinfo
*pai
;
955 l
= sizeof(*ai
) + pai
->ai_addrlen
;
956 if ((ai
= (struct addrinfo
*)malloc(l
)) == NULL
)
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
) {
969 strcpy(ai
->ai_canonname
, pai
->ai_canonname
); /* (checked) */
971 /* just to make sure */
972 ai
->ai_canonname
= NULL
;
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);
989 get_port(const struct addrinfo
*ai
, const char *servname
, int matchonly
) {
995 if (servname
== NULL
)
997 switch (ai
->ai_family
) {
1007 switch (ai
->ai_socktype
) {
1015 switch (ai
->ai_family
) {
1028 return EAI_SOCKTYPE
;
1031 if (str_isnumber(servname
)) {
1034 port
= atoi(servname
);
1035 if (port
< 0 || port
> 65535)
1039 switch (ai
->ai_socktype
) {
1051 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1057 switch (ai
->ai_family
) {
1059 ((struct sockaddr_in
*)(void *)
1060 ai
->ai_addr
)->sin_port
= port
;
1063 ((struct sockaddr_in6
*)(void *)
1064 ai
->ai_addr
)->sin6_port
= port
;
1072 static const struct afd
*
1076 const struct afd
*afd
;
1078 if (af
== PF_UNSPEC
)
1080 for (afd
= afdl
; afd
->a_af
; afd
++) {
1081 if (afd
->a_af
== af
)
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.
1100 s
= socket(af
, SOCK_DGRAM
, 0);
1102 if (errno
!= EMFILE
)
1109 /* convert a string to a scope identifier. XXX: IPv6 specific */
1111 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
,
1112 u_int32_t
*scopeidp
)
1116 struct in6_addr
*a6
= &sin6
->sin6_addr
;
1119 /* empty scopeid portion is invalid */
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
);
1134 *scopeidp
= scopeid
;
1139 /* still unclear about literal, allow numeric only - placeholder */
1140 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1142 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1145 goto trynumeric
; /*%< global */
1146 /* try to convert to a numeric id as a last resort */
1149 lscopeid
= strtoul(scope
, &ep
, 10);
1150 scopeid
= lscopeid
& 0xffffffff;
1151 if (errno
== 0 && ep
&& *ep
== '\0' && scopeid
== lscopeid
) {
1152 *scopeidp
= scopeid
;
1159 hostent2addrinfo(hp
, pai
)
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
)
1176 aplist
= hp
->h_addr_list
;
1178 memset(&sentinel
, 0, sizeof(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
)) {
1187 ap
= ap
+ sizeof(struct in6_addr
)
1188 - sizeof(struct in_addr
);
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. */
1212 freeaddrinfo(cur
->ai_next
);
1213 cur
->ai_next
= NULL
;
1214 /* continue, without tht pointer CUR advanced. */
1217 return(sentinel
.ai_next
);
1221 addr2addrinfo(pai
, cp
)
1222 const struct addrinfo
*pai
;
1225 const struct afd
*afd
;
1227 afd
= find_afd(pai
->ai_family
);
1231 return(get_ai(pai
, afd
, cp
));
1234 static struct net_data
*
1237 struct net_data
*net_data
;
1239 if (!(net_data
= net_data_init(NULL
)))
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
) {
1246 if (net_data
&& net_data
->res
)
1247 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1251 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);