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 free(ai
->ai_canonname
);
295 /* no need to free(ai->ai_addr) */
311 (void)strtoul(p
, &ep
, 10);
312 if (errno
== 0 && ep
&& *ep
== '\0')
319 getaddrinfo(hostname
, servname
, hints
, res
)
320 const char *hostname
, *servname
;
321 const struct addrinfo
*hints
;
322 struct addrinfo
**res
;
324 struct addrinfo sentinel
;
325 struct addrinfo
*cur
;
327 struct addrinfo ai
, ai0
, *afai
= NULL
;
328 struct addrinfo
*pai
;
329 const struct explore
*ex
;
331 memset(&sentinel
, 0, sizeof(sentinel
));
335 pai
->ai_family
= PF_UNSPEC
;
336 pai
->ai_socktype
= ANY
;
337 pai
->ai_protocol
= ANY
;
338 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
340 * clear _ai_pad to preserve binary
341 * compatibility with previously compiled 64-bit
342 * applications in a pre-SUSv3 environment by
343 * guaranteeing the upper 32-bits are empty.
348 pai
->ai_canonname
= NULL
;
352 if (hostname
== NULL
&& servname
== NULL
)
355 /* error check for hints */
356 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
357 hints
->ai_addr
|| hints
->ai_next
)
358 SETERROR(EAI_BADHINTS
); /*%< xxx */
359 if (hints
->ai_flags
& ~AI_MASK
)
360 SETERROR(EAI_BADFLAGS
);
361 switch (hints
->ai_family
) {
367 SETERROR(EAI_FAMILY
);
369 memcpy(pai
, hints
, sizeof(*pai
));
371 #if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9)
373 * We need to clear _ai_pad to preserve binary
374 * compatibility. See prior comment.
379 * if both socktype/protocol are specified, check if they
380 * are meaningful combination.
382 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
383 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
384 if (pai
->ai_family
!= ex
->e_af
)
386 if (ex
->e_socktype
== ANY
)
388 if (ex
->e_protocol
== ANY
)
390 if (pai
->ai_socktype
== ex
->e_socktype
&&
391 pai
->ai_protocol
!= ex
->e_protocol
) {
392 SETERROR(EAI_BADHINTS
);
399 * post-2553: AI_ALL and AI_V4MAPPED are effective only against
400 * AF_INET6 query. They needs to be ignored if specified in other
403 switch (pai
->ai_flags
& (AI_ALL
| AI_V4MAPPED
)) {
405 case AI_ALL
| AI_V4MAPPED
:
406 if (pai
->ai_family
!= AF_INET6
)
407 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
412 SETERROR(EAI_BADFLAGS
);
414 pai
->ai_flags
&= ~(AI_ALL
| AI_V4MAPPED
);
420 * check for special cases. (1) numeric servname is disallowed if
421 * socktype/protocol are left unspecified. (2) servname is disallowed
422 * for raw and other inet{,6} sockets.
424 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
426 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
429 ai0
= *pai
; /* backup *pai */
431 if (pai
->ai_family
== PF_UNSPEC
) {
433 pai
->ai_family
= PF_INET6
;
435 pai
->ai_family
= PF_INET
;
438 error
= get_portmatch(pai
, servname
);
447 /* NULL hostname, or numeric hostname */
448 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
451 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
453 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
455 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
458 if (pai
->ai_family
== PF_UNSPEC
)
459 pai
->ai_family
= ex
->e_af
;
460 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
461 pai
->ai_socktype
= ex
->e_socktype
;
462 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
463 pai
->ai_protocol
= ex
->e_protocol
;
466 * if the servname does not match socktype/protocol, ignore it.
468 if (get_portmatch(pai
, servname
) != 0)
471 if (hostname
== NULL
) {
473 * filter out AFs that are not supported by the kernel
476 if (!addrconfig(pai
->ai_family
))
478 error
= explore_null(pai
, servname
, &cur
->ai_next
);
480 error
= explore_numeric_scope(pai
, hostname
, servname
,
486 while (cur
&& cur
->ai_next
)
492 * If numreic representation of AF1 can be interpreted as FQDN
493 * representation of AF2, we need to think again about the code below.
495 if (sentinel
.ai_next
)
498 if (pai
->ai_flags
& AI_NUMERICHOST
)
499 SETERROR(EAI_NONAME
);
500 if (hostname
== NULL
)
501 SETERROR(EAI_NONAME
);
504 * hostname as alphabetical name.
505 * We'll make sure that
506 * - if returning addrinfo list is empty, return non-zero error
507 * value (already known one or EAI_NONAME).
509 * + if we haven't had any errors, return 0 (i.e. success).
510 * + if we've had an error, free the list and return the error.
511 * without any assumption on the behavior of explore_fqdn().
514 /* first, try to query DNS for all possible address families. */
516 error
= explore_fqdn(pai
, hostname
, servname
, &afai
);
523 error
= EAI_NONAME
; /*%< we've had no errors. */
528 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
531 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
534 if (pai
->ai_family
== PF_UNSPEC
)
535 pai
->ai_family
= ex
->e_af
;
537 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
539 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
540 WILD_SOCKTYPE(ex
))) {
543 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
544 WILD_PROTOCOL(ex
))) {
550 * If AI_ADDRCONFIG is specified, check if we are
551 * expected to return the address family or not.
553 if ((pai
->ai_flags
& AI_ADDRCONFIG
) != 0 &&
554 !addrconfig(pai
->ai_family
))
558 if (pai
->ai_family
== PF_UNSPEC
)
559 pai
->ai_family
= ex
->e_af
;
560 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
561 pai
->ai_socktype
= ex
->e_socktype
;
562 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
563 pai
->ai_protocol
= ex
->e_protocol
;
566 * if the servname does not match socktype/protocol, ignore it.
568 if (get_portmatch(pai
, servname
) != 0)
571 if ((error
= explore_copy(pai
, afai
, &cur
->ai_next
)) != 0) {
576 while (cur
&& cur
->ai_next
)
580 freeaddrinfo(afai
); /*%< afai must not be NULL at this point. */
582 if (sentinel
.ai_next
) {
584 *res
= sentinel
.ai_next
;
588 * All the process succeeded, but we've had an empty list.
589 * This can happen if the given hints do not match our
597 if (sentinel
.ai_next
)
598 freeaddrinfo(sentinel
.ai_next
);
604 * FQDN hostname, DNS lookup
607 explore_fqdn(pai
, hostname
, servname
, res
)
608 const struct addrinfo
*pai
;
609 const char *hostname
;
610 const char *servname
;
611 struct addrinfo
**res
;
613 struct addrinfo
*result
;
614 struct addrinfo
*cur
;
615 struct net_data
*net_data
= init();
618 char tmp
[NS_MAXDNAME
];
621 INSIST(res
!= NULL
&& *res
== NULL
);
624 * if the servname does not match socktype/protocol, ignore it.
626 if (get_portmatch(pai
, servname
) != 0)
629 if (!net_data
|| !(ho
= net_data
->ho
))
631 #if 0 /*%< XXX (notyet) */
632 if (net_data
->ho_stayopen
&& net_data
->ho_last
&&
633 net_data
->ho_last
->h_addrtype
== af
) {
634 if (ns_samename(name
, net_data
->ho_last
->h_name
) == 1)
635 return (net_data
->ho_last
);
636 for (hap
= net_data
->ho_last
->h_aliases
; hap
&& *hap
; hap
++)
637 if (ns_samename(name
, *hap
) == 1)
638 return (net_data
->ho_last
);
641 if (!strchr(hostname
, '.') &&
642 (cp
= res_hostalias(net_data
->res
, hostname
,
645 result
= (*ho
->addrinfo
)(ho
, hostname
, pai
);
646 if (!net_data
->ho_stayopen
) {
649 if (result
== NULL
) {
667 case NETDB_SUCCESS
: /*%< should be impossible... */
674 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
675 GET_PORT(cur
, servname
); /*%< XXX: redundant lookups... */
676 /* canonname should already be filled. */
685 freeaddrinfo(result
);
690 explore_copy(pai
, src0
, res
)
691 const struct addrinfo
*pai
; /*%< seed */
692 const struct addrinfo
*src0
; /*%< source */
693 struct addrinfo
**res
;
696 struct addrinfo sentinel
, *cur
;
697 const struct addrinfo
*src
;
700 sentinel
.ai_next
= NULL
;
703 for (src
= src0
; src
!= NULL
; src
= src
->ai_next
) {
704 if (src
->ai_family
!= pai
->ai_family
)
707 cur
->ai_next
= copy_ai(src
);
713 cur
->ai_next
->ai_socktype
= pai
->ai_socktype
;
714 cur
->ai_next
->ai_protocol
= pai
->ai_protocol
;
718 *res
= sentinel
.ai_next
;
722 freeaddrinfo(sentinel
.ai_next
);
728 * passive socket -> anyaddr (0.0.0.0 or ::)
729 * non-passive socket -> localhost (127.0.0.1 or ::1)
732 explore_null(pai
, servname
, res
)
733 const struct addrinfo
*pai
;
734 const char *servname
;
735 struct addrinfo
**res
;
737 const struct afd
*afd
;
738 struct addrinfo
*cur
;
739 struct addrinfo sentinel
;
743 sentinel
.ai_next
= NULL
;
746 afd
= find_afd(pai
->ai_family
);
750 if (pai
->ai_flags
& AI_PASSIVE
) {
751 GET_AI(cur
->ai_next
, afd
, afd
->a_addrany
);
753 * GET_CANONNAME(cur->ai_next, "anyaddr");
755 GET_PORT(cur
->ai_next
, servname
);
757 GET_AI(cur
->ai_next
, afd
, afd
->a_loopback
);
759 * GET_CANONNAME(cur->ai_next, "localhost");
761 GET_PORT(cur
->ai_next
, servname
);
765 *res
= sentinel
.ai_next
;
769 if (sentinel
.ai_next
)
770 freeaddrinfo(sentinel
.ai_next
);
778 explore_numeric(pai
, hostname
, servname
, res
)
779 const struct addrinfo
*pai
;
780 const char *hostname
;
781 const char *servname
;
782 struct addrinfo
**res
;
784 const struct afd
*afd
;
785 struct addrinfo
*cur
;
786 struct addrinfo sentinel
;
791 sentinel
.ai_next
= NULL
;
794 afd
= find_afd(pai
->ai_family
);
799 #if 0 /*X/Open spec*/
801 if (inet_aton(hostname
, (struct in_addr
*)pton
) == 1) {
802 if (pai
->ai_family
== afd
->a_af
||
803 pai
->ai_family
== PF_UNSPEC
/*?*/) {
804 GET_AI(cur
->ai_next
, afd
, pton
);
805 GET_PORT(cur
->ai_next
, servname
);
809 SETERROR(EAI_FAMILY
); /*xxx*/
814 if (inet_pton(afd
->a_af
, hostname
, pton
) == 1) {
815 if (pai
->ai_family
== afd
->a_af
||
816 pai
->ai_family
== PF_UNSPEC
/*?*/) {
817 GET_AI(cur
->ai_next
, afd
, pton
);
818 GET_PORT(cur
->ai_next
, servname
);
822 SETERROR(EAI_FAMILY
); /*xxx*/
827 *res
= sentinel
.ai_next
;
832 if (sentinel
.ai_next
)
833 freeaddrinfo(sentinel
.ai_next
);
838 * numeric hostname with scope
841 explore_numeric_scope(pai
, hostname
, servname
, res
)
842 const struct addrinfo
*pai
;
843 const char *hostname
;
844 const char *servname
;
845 struct addrinfo
**res
;
847 #ifndef SCOPE_DELIMITER
848 return explore_numeric(pai
, hostname
, servname
, res
);
850 const struct afd
*afd
;
851 struct addrinfo
*cur
;
853 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
854 struct sockaddr_in6
*sin6
;
856 afd
= find_afd(pai
->ai_family
);
861 return explore_numeric(pai
, hostname
, servname
, res
);
863 cp
= strchr(hostname
, SCOPE_DELIMITER
);
865 return explore_numeric(pai
, hostname
, servname
, res
);
868 * Handle special case of <scoped_address><delimiter><scope id>
870 hostname2
= strdup(hostname
);
871 if (hostname2
== NULL
)
873 /* terminate at the delimiter */
874 hostname2
[cp
- hostname
] = '\0';
878 error
= explore_numeric(pai
, addr
, servname
, res
);
880 u_int32_t scopeid
= 0;
882 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
883 if (cur
->ai_family
!= AF_INET6
)
885 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
886 if (!ip6_str2scopeid(scope
, sin6
, &scopeid
)) {
888 return(EAI_NONAME
); /*%< XXX: is return OK? */
890 #ifdef HAVE_SIN6_SCOPE_ID
891 sin6
->sin6_scope_id
= scopeid
;
903 get_canonname(pai
, ai
, str
)
904 const struct addrinfo
*pai
;
908 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
909 ai
->ai_canonname
= (char *)malloc(strlen(str
) + 1);
910 if (ai
->ai_canonname
== NULL
)
912 strcpy(ai
->ai_canonname
, str
);
917 static struct addrinfo
*
918 get_ai(pai
, afd
, addr
)
919 const struct addrinfo
*pai
;
920 const struct afd
*afd
;
926 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
931 memcpy(ai
, pai
, sizeof(struct addrinfo
));
932 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
933 memset(ai
->ai_addr
, 0, (size_t)afd
->a_socklen
);
935 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
937 ai
->ai_addrlen
= afd
->a_socklen
;
938 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
939 p
= (char *)(void *)(ai
->ai_addr
);
940 memcpy(p
+ afd
->a_off
, addr
, (size_t)afd
->a_addrlen
);
944 /* XXX need to malloc() the same way we do from other functions! */
945 static struct addrinfo
*
947 const struct addrinfo
*pai
;
952 l
= sizeof(*ai
) + pai
->ai_addrlen
;
953 if ((ai
= (struct addrinfo
*)malloc(l
)) == NULL
)
956 memcpy(ai
, pai
, sizeof(*ai
));
957 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
958 memcpy(ai
->ai_addr
, pai
->ai_addr
, pai
->ai_addrlen
);
960 if (pai
->ai_canonname
) {
961 l
= strlen(pai
->ai_canonname
) + 1;
962 if ((ai
->ai_canonname
= malloc(l
)) == NULL
) {
966 strcpy(ai
->ai_canonname
, pai
->ai_canonname
); /* (checked) */
968 /* just to make sure */
969 ai
->ai_canonname
= NULL
;
978 get_portmatch(const struct addrinfo
*ai
, const char *servname
) {
980 /* get_port does not touch first argument. when matchonly == 1. */
981 /* LINTED const cast */
982 return get_port((const struct addrinfo
*)ai
, servname
, 1);
986 get_port(const struct addrinfo
*ai
, const char *servname
, int matchonly
) {
992 if (servname
== NULL
)
994 switch (ai
->ai_family
) {
1004 switch (ai
->ai_socktype
) {
1012 switch (ai
->ai_family
) {
1025 return EAI_SOCKTYPE
;
1028 if (str_isnumber(servname
)) {
1031 port
= atoi(servname
);
1032 if (port
< 0 || port
> 65535)
1036 switch (ai
->ai_socktype
) {
1048 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1054 switch (ai
->ai_family
) {
1056 ((struct sockaddr_in
*)(void *)
1057 ai
->ai_addr
)->sin_port
= port
;
1060 ((struct sockaddr_in6
*)(void *)
1061 ai
->ai_addr
)->sin6_port
= port
;
1069 static const struct afd
*
1073 const struct afd
*afd
;
1075 if (af
== PF_UNSPEC
)
1077 for (afd
= afdl
; afd
->a_af
; afd
++) {
1078 if (afd
->a_af
== af
)
1085 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1086 * will take care of it.
1087 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1088 * if the code is right or not.
1097 s
= socket(af
, SOCK_DGRAM
, 0);
1099 if (errno
!= EMFILE
)
1106 /* convert a string to a scope identifier. XXX: IPv6 specific */
1108 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
,
1109 u_int32_t
*scopeidp
)
1113 struct in6_addr
*a6
= &sin6
->sin6_addr
;
1116 /* empty scopeid portion is invalid */
1120 #ifdef USE_IFNAMELINKID
1121 if (IN6_IS_ADDR_LINKLOCAL(a6
) || IN6_IS_ADDR_MC_LINKLOCAL(a6
) ||
1122 IN6_IS_ADDR_MC_NODELOCAL(a6
)) {
1124 * Using interface names as link indices can be allowed
1125 * only when we can assume a one-to-one mappings between
1126 * links and interfaces. See comments in getnameinfo.c.
1128 scopeid
= if_nametoindex(scope
);
1131 *scopeidp
= scopeid
;
1136 /* still unclear about literal, allow numeric only - placeholder */
1137 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1139 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1142 goto trynumeric
; /*%< global */
1143 /* try to convert to a numeric id as a last resort */
1146 lscopeid
= strtoul(scope
, &ep
, 10);
1147 scopeid
= lscopeid
& 0xffffffff;
1148 if (errno
== 0 && ep
&& *ep
== '\0' && scopeid
== lscopeid
) {
1149 *scopeidp
= scopeid
;
1156 hostent2addrinfo(hp
, pai
)
1158 const struct addrinfo
*pai
;
1160 int i
, af
, error
= 0;
1161 char **aplist
= NULL
, *ap
;
1162 struct addrinfo sentinel
, *cur
;
1163 const struct afd
*afd
;
1165 af
= hp
->h_addrtype
;
1166 if (pai
->ai_family
!= AF_UNSPEC
&& af
!= pai
->ai_family
)
1173 aplist
= hp
->h_addr_list
;
1175 memset(&sentinel
, 0, sizeof(sentinel
));
1178 for (i
= 0; (ap
= aplist
[i
]) != NULL
; i
++) {
1179 #if 0 /*%< the trick seems too much */
1180 af
= hp
->h_addr_list
;
1181 if (af
== AF_INET6
&&
1182 IN6_IS_ADDR_V4MAPPED((struct in6_addr
*)ap
)) {
1184 ap
= ap
+ sizeof(struct in6_addr
)
1185 - sizeof(struct in_addr
);
1192 GET_AI(cur
->ai_next
, afd
, ap
);
1194 /* GET_PORT(cur->ai_next, servname); */
1195 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
1197 * RFC2553 says that ai_canonname will be set only for
1198 * the first element. we do it for all the elements,
1199 * just for convenience.
1201 GET_CANONNAME(cur
->ai_next
, hp
->h_name
);
1203 while (cur
->ai_next
) /*%< no need to loop, actually. */
1209 freeaddrinfo(cur
->ai_next
);
1210 cur
->ai_next
= NULL
;
1211 /* continue, without tht pointer CUR advanced. */
1214 return(sentinel
.ai_next
);
1218 addr2addrinfo(pai
, cp
)
1219 const struct addrinfo
*pai
;
1222 const struct afd
*afd
;
1224 afd
= find_afd(pai
->ai_family
);
1228 return(get_ai(pai
, afd
, cp
));
1231 static struct net_data
*
1234 struct net_data
*net_data
;
1236 if (!(net_data
= net_data_init(NULL
)))
1238 if (!net_data
->ho
) {
1239 net_data
->ho
= (*net_data
->irs
->ho_map
)(net_data
->irs
);
1240 if (!net_data
->ho
|| !net_data
->res
) {
1243 if (net_data
&& net_data
->res
)
1244 RES_SET_H_ERRNO(net_data
->res
, NETDB_INTERNAL
);
1248 (*net_data
->ho
->res_set
)(net_data
->ho
, net_data
->res
, NULL
);