1 /* $FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.87 2008/02/03 19:07:55 ume Exp $ */
2 /* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
36 * Issues to be discussed:
37 * - Return values. There are nonstandard return values defined and used
38 * in the source code. This is because RFC2553 is silent about which error
39 * code must be returned for which situation.
40 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
41 * invalid. current code - SEGV on freeaddrinfo(NULL)
44 * - The code filters out AFs that are not supported by the kernel,
45 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
46 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
48 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
49 * (1) what should we do against numeric hostname (2) what should we do
50 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
51 * non-loopback address configured? global address configured?
53 * OS specific notes for freebsd4:
54 * - FreeBSD supported $GAI. The code does not.
57 #include "namespace.h"
58 #include <sys/types.h>
59 #include <sys/param.h>
60 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <sys/queue.h>
65 #include <net/if_var.h>
66 #include <sys/sysctl.h>
67 #include <sys/ioctl.h>
68 #include <netinet6/in6_var.h> /* XXX */
70 #include <arpa/inet.h>
71 #include <arpa/nameser.h>
73 #include <rpcsvc/yp_prot.h>
74 #include <rpcsvc/ypclnt.h>
85 #include "res_config.h"
93 #include "un-namespace.h"
94 #include "libc_private.h"
99 #if defined(__KAME__) && defined(INET6)
108 static const char in_addrany
[] = { 0, 0, 0, 0 };
109 static const char in_loopback
[] = { 127, 0, 0, 1 };
111 static const char in6_addrany
[] = {
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
114 static const char in6_loopback
[] = {
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
120 TAILQ_ENTRY(policyqueue
) pc_entry
;
122 struct in6_addrpolicy pc_policy
;
125 TAILQ_HEAD(policyhead
, policyqueue
);
127 static const struct afd
{
132 const char *a_addrany
;
133 const char *a_loopback
;
138 {PF_INET6
, sizeof(struct in6_addr
),
139 sizeof(struct sockaddr_in6
),
140 offsetof(struct sockaddr_in6
, sin6_addr
),
141 in6_addrany
, in6_loopback
, 1},
146 {PF_INET
, sizeof(struct in_addr
),
147 sizeof(struct sockaddr_in
),
148 offsetof(struct sockaddr_in
, sin_addr
),
149 in_addrany
, in_loopback
, 0},
150 {0, 0, 0, 0, NULL
, NULL
, 0},
157 const char *e_protostr
;
159 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
160 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
161 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
164 static const struct explore explore
[] = {
166 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
169 { PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
170 { PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
171 { PF_INET6
, SOCK_RAW
, ANY
, NULL
, 0x05 },
173 { PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
174 { PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
175 { PF_INET
, SOCK_RAW
, ANY
, NULL
, 0x05 },
176 { PF_UNSPEC
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
177 { PF_UNSPEC
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
178 { PF_UNSPEC
, SOCK_RAW
, ANY
, NULL
, 0x05 },
179 { -1, 0, 0, NULL
, 0 },
188 #define AIO_SRCFLAG_DEPRECATED 0x1
192 struct sockaddr_storage aiou_ss
;
193 struct sockaddr aiou_sa
;
195 #define aio_srcsa aio_src_un.aiou_sa
196 u_int32_t aio_srcflag
;
199 struct policyqueue
*aio_srcpolicy
;
200 struct policyqueue
*aio_dstpolicy
;
201 struct addrinfo
*aio_ai
;
205 static const ns_src default_dns_files
[] = {
206 { NSSRC_FILES
, NS_SUCCESS
},
207 { NSSRC_DNS
, NS_SUCCESS
},
212 struct res_target
*next
;
213 const char *name
; /* domain name */
214 int qclass
, qtype
; /* class and type of query */
215 u_char
*answer
; /* buffer to put answer */
216 int anslen
; /* size of answer buffer */
217 int n
; /* result length */
220 #define MAXPACKET (64*1024)
224 u_char buf
[MAXPACKET
];
227 static int str2number(const char *, int *);
228 static int explore_null(const struct addrinfo
*,
229 const char *, struct addrinfo
**);
230 static int explore_numeric(const struct addrinfo
*, const char *,
231 const char *, struct addrinfo
**, const char *);
232 static int explore_numeric_scope(const struct addrinfo
*, const char *,
233 const char *, struct addrinfo
**);
234 static int get_canonname(const struct addrinfo
*,
235 struct addrinfo
*, const char *);
236 static struct addrinfo
*get_ai(const struct addrinfo
*,
237 const struct afd
*, const char *);
238 static int get_portmatch(const struct addrinfo
*, const char *);
239 static int get_port(struct addrinfo
*, const char *, int);
240 static const struct afd
*find_afd(int);
241 static int addrconfig(struct addrinfo
*);
242 static void set_source(struct ai_order
*, struct policyhead
*);
243 static int comp_dst(const void *, const void *);
245 static int ip6_str2scopeid(char *, struct sockaddr_in6
*, u_int32_t
*);
247 static int gai_addr2scopetype(struct sockaddr
*);
249 static int explore_fqdn(const struct addrinfo
*, const char *,
250 const char *, struct addrinfo
**);
252 static int reorder(struct addrinfo
*);
253 static int get_addrselectpolicy(struct policyhead
*);
254 static void free_addrselectpolicy(struct policyhead
*);
255 static struct policyqueue
*match_addrselectpolicy(struct sockaddr
*,
256 struct policyhead
*);
257 static int matchlen(struct sockaddr
*, struct sockaddr
*);
259 static struct addrinfo
*getanswer(const querybuf
*, int, const char *, int,
260 const struct addrinfo
*, res_state
);
261 #if defined(RESOLVSORT)
262 static int addr4sort(struct addrinfo
*, res_state
);
264 static int _dns_getaddrinfo(void *, void *, va_list);
265 static void _sethtent(FILE **);
266 static void _endhtent(FILE **);
267 static struct addrinfo
*_gethtent(FILE **, const char *,
268 const struct addrinfo
*);
269 static int _files_getaddrinfo(void *, void *, va_list);
271 static struct addrinfo
*_yphostent(char *, const struct addrinfo
*);
272 static int _yp_getaddrinfo(void *, void *, va_list);
275 static int addrinfo_id_func(char *, size_t *, va_list, void *);
276 static int addrinfo_marshal_func(char *, size_t *, void *, va_list,
278 static int addrinfo_unmarshal_func(char *, size_t, void *, va_list,
282 static int res_queryN(const char *, struct res_target
*, res_state
);
283 static int res_searchN(const char *, struct res_target
*, res_state
);
284 static int res_querydomainN(const char *, const char *,
285 struct res_target
*, res_state
);
287 /* XXX macros that make external reference is BAD. */
289 #define GET_AI(ai, afd, addr) \
291 /* external reference: pai, error, and label free */ \
292 (ai) = get_ai(pai, (afd), (addr)); \
293 if ((ai) == NULL) { \
294 error = EAI_MEMORY; \
297 } while (/*CONSTCOND*/0)
299 #define GET_PORT(ai, serv) \
301 /* external reference: error and label free */ \
302 error = get_port((ai), (serv), 0); \
305 } while (/*CONSTCOND*/0)
307 #define GET_CANONNAME(ai, str) \
309 /* external reference: pai, error and label free */ \
310 error = get_canonname(pai, (ai), (str)); \
313 } while (/*CONSTCOND*/0)
317 /* external reference: error, and label bad */ \
321 } while (/*CONSTCOND*/0)
323 #define MATCH_FAMILY(x, y, w) \
324 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
325 #define MATCH(x, y, w) \
326 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
329 freeaddrinfo(struct addrinfo
*ai
)
331 struct addrinfo
*next
;
335 if (ai
->ai_canonname
)
336 free(ai
->ai_canonname
);
337 /* no need to free(ai->ai_addr) */
344 str2number(const char *p
, int *portp
)
353 v
= strtoul(p
, &ep
, 10);
354 if (errno
== 0 && ep
&& *ep
== '\0' && v
<= UINT_MAX
) {
362 getaddrinfo(const char *hostname
, const char *servname
,
363 const struct addrinfo
*hints
, struct addrinfo
**res
)
365 struct addrinfo sentinel
;
366 struct addrinfo
*cur
;
370 struct addrinfo
*pai
;
371 const struct explore
*ex
;
374 memset(&sentinel
, 0, sizeof(sentinel
));
378 pai
->ai_family
= PF_UNSPEC
;
379 pai
->ai_socktype
= ANY
;
380 pai
->ai_protocol
= ANY
;
382 pai
->ai_canonname
= NULL
;
386 if (hostname
== NULL
&& servname
== NULL
)
389 /* error check for hints */
390 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
391 hints
->ai_addr
|| hints
->ai_next
)
392 ERR(EAI_BADHINTS
); /* xxx */
393 if (hints
->ai_flags
& ~AI_MASK
)
395 switch (hints
->ai_family
) {
405 memcpy(pai
, hints
, sizeof(*pai
));
408 * if both socktype/protocol are specified, check if they
409 * are meaningful combination.
411 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
412 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
413 if (pai
->ai_family
!= ex
->e_af
)
415 if (ex
->e_socktype
== ANY
)
417 if (ex
->e_protocol
== ANY
)
419 if (pai
->ai_socktype
== ex
->e_socktype
&&
420 pai
->ai_protocol
!= ex
->e_protocol
) {
428 * check for special cases. (1) numeric servname is disallowed if
429 * socktype/protocol are left unspecified. (2) servname is disallowed
430 * for raw and other inet{,6} sockets.
432 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
434 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
437 ai0
= *pai
; /* backup *pai */
439 if (pai
->ai_family
== PF_UNSPEC
) {
441 pai
->ai_family
= PF_INET6
;
443 pai
->ai_family
= PF_INET
;
446 error
= get_portmatch(pai
, servname
);
455 /* NULL hostname, or numeric hostname */
456 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
459 /* PF_UNSPEC entries are prepared for DNS queries only */
460 if (ex
->e_af
== PF_UNSPEC
)
463 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
465 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
467 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
470 if (pai
->ai_family
== PF_UNSPEC
)
471 pai
->ai_family
= ex
->e_af
;
472 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
473 pai
->ai_socktype
= ex
->e_socktype
;
474 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
475 pai
->ai_protocol
= ex
->e_protocol
;
477 if (hostname
== NULL
)
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
) {
500 if (hostname
== NULL
)
501 ERR(EAI_NONAME
); /* used to be EAI_NODATA */
502 if (pai
->ai_flags
& AI_NUMERICHOST
)
505 if ((pai
->ai_flags
& AI_ADDRCONFIG
) != 0 && !addrconfig(&ai0
))
509 * hostname as alphabetical name.
510 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
513 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
516 /* require exact match for family field */
517 if (pai
->ai_family
!= ex
->e_af
)
520 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
521 WILD_SOCKTYPE(ex
))) {
524 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
525 WILD_PROTOCOL(ex
))) {
529 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
530 pai
->ai_socktype
= ex
->e_socktype
;
531 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
532 pai
->ai_protocol
= ex
->e_protocol
;
534 error
= explore_fqdn(pai
, hostname
, servname
, &cur
->ai_next
);
536 while (cur
&& cur
->ai_next
)
540 /* XXX inhibit errors if we have the result */
541 if (sentinel
.ai_next
)
546 * ensure we return either:
547 * - error == 0, non-NULL *res
548 * - error != 0, NULL *res
551 if (sentinel
.ai_next
) {
553 * If the returned entry is for an active connection,
554 * and the given name is not numeric, reorder the
555 * list, so that the application would try the list
556 * in the most efficient order. Since the head entry
557 * of the original list may contain ai_canonname and
558 * that entry may be moved elsewhere in the new list,
559 * we keep the pointer and will restore it in the new
560 * head entry. (Note that RFC3493 requires the head
561 * entry store it when requested by the caller).
563 if (hints
== NULL
|| !(hints
->ai_flags
& AI_PASSIVE
)) {
568 sentinel
.ai_next
->ai_canonname
;
569 sentinel
.ai_next
->ai_canonname
= NULL
;
571 if (sentinel
.ai_next
->ai_canonname
==
573 sentinel
.ai_next
->ai_canonname
575 } else if (canonname
!= NULL
)
579 *res
= sentinel
.ai_next
;
586 if (sentinel
.ai_next
)
587 freeaddrinfo(sentinel
.ai_next
);
593 reorder(struct addrinfo
*sentinel
)
595 struct addrinfo
*ai
, **aip
;
596 struct ai_order
*aio
;
598 struct policyhead policyhead
;
600 /* count the number of addrinfo elements for sorting. */
601 for (n
= 0, ai
= sentinel
->ai_next
; ai
!= NULL
; ai
= ai
->ai_next
, n
++)
605 * If the number is small enough, we can skip the reordering process.
610 /* allocate a temporary array for sort and initialization of it. */
611 if ((aio
= malloc(sizeof(*aio
) * n
)) == NULL
)
612 return(n
); /* give up reordering */
613 memset(aio
, 0, sizeof(*aio
) * n
);
615 /* retrieve address selection policy from the kernel */
616 TAILQ_INIT(&policyhead
);
617 if (!get_addrselectpolicy(&policyhead
)) {
618 /* no policy is installed into kernel, we don't sort. */
623 for (i
= 0, ai
= sentinel
->ai_next
; i
< n
; ai
= ai
->ai_next
, i
++) {
625 aio
[i
].aio_dstscope
= gai_addr2scopetype(ai
->ai_addr
);
626 aio
[i
].aio_dstpolicy
= match_addrselectpolicy(ai
->ai_addr
,
628 set_source(&aio
[i
], &policyhead
);
631 /* perform sorting. */
632 qsort(aio
, n
, sizeof(*aio
), comp_dst
);
634 /* reorder the addrinfo chain. */
635 for (i
= 0, aip
= &sentinel
->ai_next
; i
< n
; i
++) {
636 *aip
= aio
[i
].aio_ai
;
637 aip
= &aio
[i
].aio_ai
->ai_next
;
641 /* cleanup and return */
643 free_addrselectpolicy(&policyhead
);
648 get_addrselectpolicy(struct policyhead
*head
)
651 int mib
[] = { CTL_NET
, PF_INET6
, IPPROTO_IPV6
, IPV6CTL_ADDRCTLPOLICY
};
654 struct in6_addrpolicy
*pol
, *ep
;
656 if (sysctl(mib
, NELEM(mib
), NULL
, &l
, NULL
, 0) < 0)
658 if ((buf
= malloc(l
)) == NULL
)
660 if (sysctl(mib
, NELEM(mib
), buf
, &l
, NULL
, 0) < 0) {
665 ep
= (struct in6_addrpolicy
*)(buf
+ l
);
666 for (pol
= (struct in6_addrpolicy
*)buf
; pol
+ 1 <= ep
; pol
++) {
667 struct policyqueue
*new;
669 if ((new = malloc(sizeof(*new))) == NULL
) {
670 free_addrselectpolicy(head
); /* make the list empty */
673 new->pc_policy
= *pol
;
674 TAILQ_INSERT_TAIL(head
, new, pc_entry
);
685 free_addrselectpolicy(struct policyhead
*head
)
687 struct policyqueue
*ent
, *nent
;
689 for (ent
= TAILQ_FIRST(head
); ent
; ent
= nent
) {
690 nent
= TAILQ_NEXT(ent
, pc_entry
);
691 TAILQ_REMOVE(head
, ent
, pc_entry
);
696 static struct policyqueue
*
697 match_addrselectpolicy(struct sockaddr
*addr
, struct policyhead
*head
)
700 struct policyqueue
*ent
, *bestent
= NULL
;
701 struct in6_addrpolicy
*pol
;
702 int matchlen
, bestmatchlen
= -1;
703 u_char
*mp
, *ep
, *k
, *p
, m
;
704 struct sockaddr_in6 key
;
706 switch(addr
->sa_family
) {
708 key
= *(struct sockaddr_in6
*)addr
;
711 /* convert the address into IPv4-mapped IPv6 address. */
712 memset(&key
, 0, sizeof(key
));
713 key
.sin6_family
= AF_INET6
;
714 key
.sin6_len
= sizeof(key
);
715 key
.sin6_addr
.s6_addr
[10] = 0xff;
716 key
.sin6_addr
.s6_addr
[11] = 0xff;
717 memcpy(&key
.sin6_addr
.s6_addr
[12],
718 &((struct sockaddr_in
*)addr
)->sin_addr
, 4);
724 for (ent
= TAILQ_FIRST(head
); ent
; ent
= TAILQ_NEXT(ent
, pc_entry
)) {
725 pol
= &ent
->pc_policy
;
728 mp
= (u_char
*)&pol
->addrmask
.sin6_addr
;
729 ep
= mp
+ 16; /* XXX: scope field? */
730 k
= (u_char
*)&key
.sin6_addr
;
731 p
= (u_char
*)&pol
->addr
.sin6_addr
;
732 for (; mp
< ep
&& *mp
; mp
++, k
++, p
++) {
735 goto next
; /* not match */
736 if (m
== 0xff) /* short cut for a typical case */
746 /* matched. check if this is better than the current best. */
747 if (matchlen
> bestmatchlen
) {
749 bestmatchlen
= matchlen
;
764 set_source(struct ai_order
*aio
, struct policyhead
*ph
)
766 struct addrinfo ai
= *aio
->aio_ai
;
767 struct sockaddr_storage ss
;
771 /* set unspec ("no source is available"), just in case */
772 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
773 aio
->aio_srcscope
= -1;
775 switch(ai
.ai_family
) {
781 default: /* ignore unsupported AFs explicitly */
785 /* XXX: make a dummy addrinfo to call connect() */
786 ai
.ai_socktype
= SOCK_DGRAM
;
787 ai
.ai_protocol
= IPPROTO_UDP
; /* is UDP too specific? */
789 memset(&ss
, 0, sizeof(ss
));
790 memcpy(&ss
, ai
.ai_addr
, ai
.ai_addrlen
);
791 ai
.ai_addr
= (struct sockaddr
*)&ss
;
792 get_port(&ai
, "1", 0);
794 /* open a socket to get the source address for the given dst */
795 if ((s
= _socket(ai
.ai_family
, ai
.ai_socktype
, ai
.ai_protocol
)) < 0)
796 return; /* give up */
797 if (_connect(s
, ai
.ai_addr
, ai
.ai_addrlen
) < 0)
799 srclen
= ai
.ai_addrlen
;
800 if (_getsockname(s
, &aio
->aio_srcsa
, &srclen
) < 0) {
801 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
804 aio
->aio_srcscope
= gai_addr2scopetype(&aio
->aio_srcsa
);
805 aio
->aio_srcpolicy
= match_addrselectpolicy(&aio
->aio_srcsa
, ph
);
806 aio
->aio_matchlen
= matchlen(&aio
->aio_srcsa
, aio
->aio_ai
->ai_addr
);
808 if (ai
.ai_family
== AF_INET6
) {
809 struct in6_ifreq ifr6
;
812 /* XXX: interface name should not be hardcoded */
813 strncpy(ifr6
.ifr_name
, "lo0", sizeof(ifr6
.ifr_name
));
814 memset(&ifr6
, 0, sizeof(ifr6
));
815 memcpy(&ifr6
.ifr_addr
, ai
.ai_addr
, ai
.ai_addrlen
);
816 if (_ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) == 0) {
817 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
818 if ((flags6
& IN6_IFF_DEPRECATED
))
819 aio
->aio_srcflag
|= AIO_SRCFLAG_DEPRECATED
;
830 matchlen(struct sockaddr
*src
, struct sockaddr
*dst
)
837 switch (src
->sa_family
) {
840 s
= (u_char
*)&((struct sockaddr_in6
*)src
)->sin6_addr
;
841 d
= (u_char
*)&((struct sockaddr_in6
*)dst
)->sin6_addr
;
842 addrlen
= sizeof(struct in6_addr
);
847 s
= (u_char
*)&((struct sockaddr_in
*)src
)->sin_addr
;
848 d
= (u_char
*)&((struct sockaddr_in
*)dst
)->sin_addr
;
849 addrlen
= sizeof(struct in_addr
);
857 if ((r
= (*d
++ ^ *s
++)) != 0) {
858 while (r
< addrlen
* 8) {
869 comp_dst(const void *arg1
, const void *arg2
)
871 const struct ai_order
*dst1
= arg1
, *dst2
= arg2
;
874 * Rule 1: Avoid unusable destinations.
875 * XXX: we currently do not consider if an appropriate route exists.
877 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
878 dst2
->aio_srcsa
.sa_family
== AF_UNSPEC
) {
881 if (dst1
->aio_srcsa
.sa_family
== AF_UNSPEC
&&
882 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
886 /* Rule 2: Prefer matching scope. */
887 if (dst1
->aio_dstscope
== dst1
->aio_srcscope
&&
888 dst2
->aio_dstscope
!= dst2
->aio_srcscope
) {
891 if (dst1
->aio_dstscope
!= dst1
->aio_srcscope
&&
892 dst2
->aio_dstscope
== dst2
->aio_srcscope
) {
896 /* Rule 3: Avoid deprecated addresses. */
897 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
898 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
899 if (!(dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
900 (dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
903 if ((dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
904 !(dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
909 /* Rule 4: Prefer home addresses. */
910 /* XXX: not implemented yet */
912 /* Rule 5: Prefer matching label. */
914 if (dst1
->aio_srcpolicy
&& dst1
->aio_dstpolicy
&&
915 dst1
->aio_srcpolicy
->pc_policy
.label
==
916 dst1
->aio_dstpolicy
->pc_policy
.label
&&
917 (dst2
->aio_srcpolicy
== NULL
|| dst2
->aio_dstpolicy
== NULL
||
918 dst2
->aio_srcpolicy
->pc_policy
.label
!=
919 dst2
->aio_dstpolicy
->pc_policy
.label
)) {
922 if (dst2
->aio_srcpolicy
&& dst2
->aio_dstpolicy
&&
923 dst2
->aio_srcpolicy
->pc_policy
.label
==
924 dst2
->aio_dstpolicy
->pc_policy
.label
&&
925 (dst1
->aio_srcpolicy
== NULL
|| dst1
->aio_dstpolicy
== NULL
||
926 dst1
->aio_srcpolicy
->pc_policy
.label
!=
927 dst1
->aio_dstpolicy
->pc_policy
.label
)) {
932 /* Rule 6: Prefer higher precedence. */
934 if (dst1
->aio_dstpolicy
&&
935 (dst2
->aio_dstpolicy
== NULL
||
936 dst1
->aio_dstpolicy
->pc_policy
.preced
>
937 dst2
->aio_dstpolicy
->pc_policy
.preced
)) {
940 if (dst2
->aio_dstpolicy
&&
941 (dst1
->aio_dstpolicy
== NULL
||
942 dst2
->aio_dstpolicy
->pc_policy
.preced
>
943 dst1
->aio_dstpolicy
->pc_policy
.preced
)) {
948 /* Rule 7: Prefer native transport. */
949 /* XXX: not implemented yet */
951 /* Rule 8: Prefer smaller scope. */
952 if (dst1
->aio_dstscope
>= 0 &&
953 dst1
->aio_dstscope
< dst2
->aio_dstscope
) {
956 if (dst2
->aio_dstscope
>= 0 &&
957 dst2
->aio_dstscope
< dst1
->aio_dstscope
) {
962 * Rule 9: Use longest matching prefix.
963 * We compare the match length in a same AF only.
965 if (dst1
->aio_ai
->ai_addr
->sa_family
==
966 dst2
->aio_ai
->ai_addr
->sa_family
) {
967 if (dst1
->aio_matchlen
> dst2
->aio_matchlen
) {
970 if (dst1
->aio_matchlen
< dst2
->aio_matchlen
) {
975 /* Rule 10: Otherwise, leave the order unchanged. */
981 * XXX: we should standardize the functions and link them as standard
985 gai_addr2scopetype(struct sockaddr
*sa
)
988 struct sockaddr_in6
*sa6
;
990 struct sockaddr_in
*sa4
;
992 switch(sa
->sa_family
) {
995 sa6
= (struct sockaddr_in6
*)sa
;
996 if (IN6_IS_ADDR_MULTICAST(&sa6
->sin6_addr
)) {
997 /* just use the scope field of the multicast address */
998 return(sa6
->sin6_addr
.s6_addr
[2] & 0x0f);
1001 * Unicast addresses: map scope type to corresponding scope
1002 * value defined for multcast addresses.
1003 * XXX: hardcoded scope type values are bad...
1005 if (IN6_IS_ADDR_LOOPBACK(&sa6
->sin6_addr
))
1006 return(1); /* node local scope */
1007 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
))
1008 return(2); /* link-local scope */
1009 if (IN6_IS_ADDR_SITELOCAL(&sa6
->sin6_addr
))
1010 return(5); /* site-local scope */
1011 return(14); /* global scope */
1016 * IPv4 pseudo scoping according to RFC 3484.
1018 sa4
= (struct sockaddr_in
*)sa
;
1019 /* IPv4 autoconfiguration addresses have link-local scope. */
1020 if (((u_char
*)&sa4
->sin_addr
)[0] == 169 &&
1021 ((u_char
*)&sa4
->sin_addr
)[1] == 254)
1023 /* Private addresses have site-local scope. */
1024 if (((u_char
*)&sa4
->sin_addr
)[0] == 10 ||
1025 (((u_char
*)&sa4
->sin_addr
)[0] == 172 &&
1026 (((u_char
*)&sa4
->sin_addr
)[1] & 0xf0) == 16) ||
1027 (((u_char
*)&sa4
->sin_addr
)[0] == 192 &&
1028 ((u_char
*)&sa4
->sin_addr
)[1] == 168))
1029 return(14); /* XXX: It should be 5 unless NAT */
1030 /* Loopback addresses have link-local scope. */
1031 if (((u_char
*)&sa4
->sin_addr
)[0] == 127)
1036 errno
= EAFNOSUPPORT
; /* is this a good error? */
1043 * passive socket -> anyaddr (0.0.0.0 or ::)
1044 * non-passive socket -> localhost (127.0.0.1 or ::1)
1047 explore_null(const struct addrinfo
*pai
, const char *servname
,
1048 struct addrinfo
**res
)
1051 const struct afd
*afd
;
1052 struct addrinfo
*ai
;
1059 * filter out AFs that are not supported by the kernel
1062 s
= _socket(pai
->ai_family
, SOCK_DGRAM
, 0);
1064 if (errno
!= EMFILE
)
1070 * if the servname does not match socktype/protocol, ignore it.
1072 if (get_portmatch(pai
, servname
) != 0)
1075 afd
= find_afd(pai
->ai_family
);
1079 if (pai
->ai_flags
& AI_PASSIVE
) {
1080 GET_AI(ai
, afd
, afd
->a_addrany
);
1081 GET_PORT(ai
, servname
);
1083 GET_AI(ai
, afd
, afd
->a_loopback
);
1084 GET_PORT(ai
, servname
);
1100 explore_numeric(const struct addrinfo
*pai
, const char *hostname
,
1101 const char *servname
, struct addrinfo
**res
,
1102 const char *canonname
)
1104 const struct afd
*afd
;
1105 struct addrinfo
*ai
;
1107 char pton
[PTON_MAX
];
1113 * if the servname does not match socktype/protocol, ignore it.
1115 if (get_portmatch(pai
, servname
) != 0)
1118 afd
= find_afd(pai
->ai_family
);
1122 switch (afd
->a_af
) {
1125 * RFC3493 requires getaddrinfo() to accept AF_INET formats
1126 * that are accepted by inet_addr() and its family. The
1127 * accepted forms includes the "classful" one, which inet_pton
1128 * does not accept. So we need to separate the case for
1131 if (inet_aton(hostname
, (struct in_addr
*)pton
) != 1)
1135 if (inet_pton(afd
->a_af
, hostname
, pton
) != 1)
1140 if (pai
->ai_family
== afd
->a_af
) {
1141 GET_AI(ai
, afd
, pton
);
1142 GET_PORT(ai
, servname
);
1143 if ((pai
->ai_flags
& AI_CANONNAME
)) {
1145 * Set the numeric address itself as the canonical
1146 * name, based on a clarification in RFC3493.
1148 GET_CANONNAME(ai
, canonname
);
1152 * XXX: This should not happen since we already matched the AF
1169 * numeric hostname with scope
1172 explore_numeric_scope(const struct addrinfo
*pai
, const char *hostname
,
1173 const char *servname
, struct addrinfo
**res
)
1175 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
1176 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1178 const struct afd
*afd
;
1179 struct addrinfo
*cur
;
1181 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
1182 struct sockaddr_in6
*sin6
;
1185 * if the servname does not match socktype/protocol, ignore it.
1187 if (get_portmatch(pai
, servname
) != 0)
1190 afd
= find_afd(pai
->ai_family
);
1195 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1197 cp
= strchr(hostname
, SCOPE_DELIMITER
);
1199 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1202 * Handle special case of <scoped_address><delimiter><scope id>
1204 hostname2
= strdup(hostname
);
1205 if (hostname2
== NULL
)
1207 /* terminate at the delimiter */
1208 hostname2
[cp
- hostname
] = '\0';
1212 error
= explore_numeric(pai
, addr
, servname
, res
, hostname
);
1216 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
1217 if (cur
->ai_family
!= AF_INET6
)
1219 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
1220 if (ip6_str2scopeid(scope
, sin6
, &scopeid
) == -1) {
1222 return(EAI_NONAME
); /* XXX: is return OK? */
1224 sin6
->sin6_scope_id
= scopeid
;
1235 get_canonname(const struct addrinfo
*pai
, struct addrinfo
*ai
, const char *str
)
1237 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
1238 ai
->ai_canonname
= strdup(str
);
1239 if (ai
->ai_canonname
== NULL
)
1245 static struct addrinfo
*
1246 get_ai(const struct addrinfo
*pai
, const struct afd
*afd
, const char *addr
)
1249 struct addrinfo
*ai
;
1251 struct in6_addr faith_prefix
;
1258 * Transfrom an IPv4 addr into a special IPv6 addr format for
1259 * IPv6->IPv4 translation gateway. (only TCP is supported now)
1261 * +-----------------------------------+------------+
1262 * | faith prefix part (12 bytes) | embedded |
1263 * | | IPv4 addr part (4 bytes)
1264 * +-----------------------------------+------------+
1266 * faith prefix part is specified as ascii IPv6 addr format
1267 * in environmental variable GAI.
1268 * For FAITH to work correctly, routing to faith prefix must be
1269 * setup toward a machine where a FAITH daemon operates.
1270 * Also, the machine must enable some mechanizm
1271 * (e.g. faith interface hack) to divert those packet with
1272 * faith prefixed destination addr to user-land FAITH daemon.
1274 fp_str
= getenv("GAI");
1275 if (fp_str
&& inet_pton(AF_INET6
, fp_str
, &faith_prefix
) == 1 &&
1276 afd
->a_af
== AF_INET
&& pai
->ai_socktype
== SOCK_STREAM
) {
1280 memcpy(&v4a
, addr
, sizeof v4a
);
1281 v4a_top
= v4a
>> IN_CLASSA_NSHIFT
;
1282 if (!IN_MULTICAST(v4a
) && !IN_EXPERIMENTAL(v4a
) &&
1283 v4a_top
!= 0 && v4a
!= IN_LOOPBACKNET
) {
1284 afd
= &afdl
[N_INET6
];
1285 memcpy(&faith_prefix
.s6_addr
[12], addr
,
1286 sizeof(struct in_addr
));
1292 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
1293 + (afd
->a_socklen
));
1297 memcpy(ai
, pai
, sizeof(struct addrinfo
));
1298 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
1299 memset(ai
->ai_addr
, 0, (size_t)afd
->a_socklen
);
1300 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
1301 ai
->ai_addrlen
= afd
->a_socklen
;
1302 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
1303 p
= (char *)(void *)(ai
->ai_addr
);
1306 memcpy(p
+ afd
->a_off
, &faith_prefix
, (size_t)afd
->a_addrlen
);
1309 memcpy(p
+ afd
->a_off
, addr
, (size_t)afd
->a_addrlen
);
1314 get_portmatch(const struct addrinfo
*ai
, const char *servname
)
1317 /* get_port does not touch first argument when matchonly == 1. */
1318 /* LINTED const cast */
1319 return get_port((struct addrinfo
*)ai
, servname
, 1);
1323 get_port(struct addrinfo
*ai
, const char *servname
, int matchonly
)
1330 if (servname
== NULL
)
1332 switch (ai
->ai_family
) {
1342 switch (ai
->ai_socktype
) {
1353 return EAI_SOCKTYPE
;
1356 error
= str2number(servname
, &port
);
1360 if (port
< 0 || port
> 65535)
1364 if (ai
->ai_flags
& AI_NUMERICSERV
)
1366 switch (ai
->ai_socktype
) {
1378 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1384 switch (ai
->ai_family
) {
1386 ((struct sockaddr_in
*)(void *)
1387 ai
->ai_addr
)->sin_port
= port
;
1391 ((struct sockaddr_in6
*)(void *)
1392 ai
->ai_addr
)->sin6_port
= port
;
1401 static const struct afd
*
1404 const struct afd
*afd
;
1406 if (af
== PF_UNSPEC
)
1408 for (afd
= afdl
; afd
->a_af
; afd
++) {
1409 if (afd
->a_af
== af
)
1416 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1417 * will take care of it.
1418 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1419 * if the code is right or not.
1421 * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
1425 addrconfig(struct addrinfo
*pai
)
1431 * Note that implementation dependent test for address
1432 * configuration should be done everytime called
1433 * (or apropriate interval),
1434 * because addresses will be dynamically assigned or deleted.
1436 af
= pai
->ai_family
;
1437 if (af
== AF_UNSPEC
) {
1438 if ((s
= _socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0)
1442 if ((s
= _socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
1448 if (af
!= AF_UNSPEC
) {
1449 if ((s
= _socket(af
, SOCK_DGRAM
, 0)) < 0)
1453 pai
->ai_family
= af
;
1458 /* convert a string to a scope identifier. XXX: IPv6 specific */
1460 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
, u_int32_t
*scopeid
)
1463 struct in6_addr
*a6
;
1466 a6
= &sin6
->sin6_addr
;
1468 /* empty scopeid portion is invalid */
1472 if (IN6_IS_ADDR_LINKLOCAL(a6
) || IN6_IS_ADDR_MC_LINKLOCAL(a6
)) {
1474 * We currently assume a one-to-one mapping between links
1475 * and interfaces, so we simply use interface indices for
1476 * like-local scopes.
1478 *scopeid
= if_nametoindex(scope
);
1484 /* still unclear about literal, allow numeric only - placeholder */
1485 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1487 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1490 goto trynumeric
; /* global */
1492 /* try to convert to a numeric id as a last resort */
1495 lscopeid
= strtoul(scope
, &ep
, 10);
1496 *scopeid
= (u_int32_t
)(lscopeid
& 0xffffffffUL
);
1497 if (errno
== 0 && ep
&& *ep
== '\0' && *scopeid
== lscopeid
)
1507 addrinfo_id_func(char *buffer
, size_t *buffer_size
, va_list ap
,
1508 void *cache_mdata __unused
)
1513 const int op_id
= 0; /* identifies the getaddrinfo for the cache */
1515 struct addrinfo
*hints
;
1518 int ai_flags
, ai_family
, ai_socktype
, ai_protocol
;
1519 size_t desired_size
, size
;
1521 statp
= __res_state();
1522 res_options
= statp
->options
& (RES_RECURSE
| RES_DEFNAMES
|
1523 RES_DNSRCH
| RES_NOALIASES
| RES_USE_INET6
);
1525 hostname
= va_arg(ap
, char *);
1526 hints
= va_arg(ap
, struct addrinfo
*);
1528 desired_size
= sizeof(res_options
) + sizeof(int) + sizeof(int) * 4;
1529 if (hostname
!= NULL
) {
1530 size
= strlen(hostname
);
1531 desired_size
+= size
+ 1;
1535 if (desired_size
> *buffer_size
) {
1536 *buffer_size
= desired_size
;
1541 ai_flags
= ai_family
= ai_socktype
= ai_protocol
= 0;
1543 ai_flags
= hints
->ai_flags
;
1544 ai_family
= hints
->ai_family
;
1545 ai_socktype
= hints
->ai_socktype
;
1546 ai_protocol
= hints
->ai_protocol
;
1550 memcpy(p
, &res_options
, sizeof(res_options
));
1551 p
+= sizeof(res_options
);
1553 memcpy(p
, &op_id
, sizeof(int));
1556 memcpy(p
, &ai_flags
, sizeof(int));
1559 memcpy(p
, &ai_family
, sizeof(int));
1562 memcpy(p
, &ai_socktype
, sizeof(int));
1565 memcpy(p
, &ai_protocol
, sizeof(int));
1568 if (hostname
!= NULL
)
1569 memcpy(p
, hostname
, size
);
1571 *buffer_size
= desired_size
;
1572 return (NS_SUCCESS
);
1576 addrinfo_marshal_func(char *buffer
, size_t *buffer_size
, void *retval
,
1577 va_list ap __unused
, void *cache_mdata __unused
)
1579 struct addrinfo
*ai
, *cai
;
1581 size_t desired_size
, size
, ai_size
;
1583 ai
= *((struct addrinfo
**)retval
);
1585 desired_size
= sizeof(size_t);
1587 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1588 desired_size
+= sizeof(struct addrinfo
) + cai
->ai_addrlen
;
1589 if (cai
->ai_canonname
!= NULL
)
1590 desired_size
+= sizeof(size_t) +
1591 strlen(cai
->ai_canonname
);
1595 if (desired_size
> *buffer_size
) {
1596 /* this assignment is here for future use */
1598 *buffer_size
= desired_size
;
1602 memset(buffer
, 0, desired_size
);
1605 memcpy(p
, &ai_size
, sizeof(size_t));
1606 p
+= sizeof(size_t);
1607 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1608 memcpy(p
, cai
, sizeof(struct addrinfo
));
1609 p
+= sizeof(struct addrinfo
);
1611 memcpy(p
, cai
->ai_addr
, cai
->ai_addrlen
);
1612 p
+= cai
->ai_addrlen
;
1614 if (cai
->ai_canonname
!= NULL
) {
1615 size
= strlen(cai
->ai_canonname
);
1616 memcpy(p
, &size
, sizeof(size_t));
1617 p
+= sizeof(size_t);
1619 memcpy(p
, cai
->ai_canonname
, size
);
1624 return (NS_SUCCESS
);
1628 addrinfo_unmarshal_func(char *buffer
, size_t buffer_size __unused
, void *retval
,
1629 va_list ap __unused
, void *cache_mdata __unused
)
1631 struct addrinfo new_ai
, *result
, *sentinel
, *lasts
;
1634 size_t ai_size
, ai_i
, size
;
1637 memcpy(&ai_size
, p
, sizeof(size_t));
1638 p
+= sizeof(size_t);
1642 for (ai_i
= 0; ai_i
< ai_size
; ++ai_i
) {
1643 memcpy(&new_ai
, p
, sizeof(struct addrinfo
));
1644 p
+= sizeof(struct addrinfo
);
1645 size
= new_ai
.ai_addrlen
+ sizeof(struct addrinfo
) +
1648 sentinel
= (struct addrinfo
*)malloc(size
);
1649 memset(sentinel
, 0, size
);
1651 memcpy(sentinel
, &new_ai
, sizeof(struct addrinfo
));
1652 sentinel
->ai_addr
= (struct sockaddr
*)_ALIGN((char *)sentinel
+
1653 sizeof(struct addrinfo
));
1655 memcpy(sentinel
->ai_addr
, p
, new_ai
.ai_addrlen
);
1656 p
+= new_ai
.ai_addrlen
;
1658 if (new_ai
.ai_canonname
!= NULL
) {
1659 memcpy(&size
, p
, sizeof(size_t));
1660 p
+= sizeof(size_t);
1662 sentinel
->ai_canonname
= (char *)malloc(size
+ 1);
1663 memset(sentinel
->ai_canonname
, 0, size
+ 1);
1665 memcpy(sentinel
->ai_canonname
, p
, size
);
1669 if (result
== NULL
) {
1673 lasts
->ai_next
= sentinel
;
1678 *((struct addrinfo
**)retval
) = result
;
1679 return (NS_SUCCESS
);
1681 #endif /* NS_CACHING */
1684 * FQDN hostname, DNS lookup
1687 explore_fqdn(const struct addrinfo
*pai
, const char *hostname
,
1688 const char *servname
, struct addrinfo
**res
)
1690 struct addrinfo
*result
;
1691 struct addrinfo
*cur
;
1695 static const nss_cache_info cache_info
=
1696 NS_COMMON_CACHE_INFO_INITIALIZER(
1697 hosts
, NULL
, addrinfo_id_func
, addrinfo_marshal_func
,
1698 addrinfo_unmarshal_func
);
1700 static const ns_dtab dtab
[] = {
1701 NS_FILES_CB(_files_getaddrinfo
, NULL
)
1702 { NSSRC_DNS
, _dns_getaddrinfo
, NULL
}, /* force -DHESIOD */
1703 NS_NIS_CB(_yp_getaddrinfo
, NULL
)
1705 NS_CACHE_CB(&cache_info
)
1713 * if the servname does not match socktype/protocol, ignore it.
1715 if (get_portmatch(pai
, servname
) != 0)
1718 switch (_nsdispatch(&result
, dtab
, NSDB_HOSTS
, "getaddrinfo",
1719 default_dns_files
, hostname
, pai
)) {
1731 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
1732 GET_PORT(cur
, servname
);
1733 /* canonname should be filled already */
1744 freeaddrinfo(result
);
1749 static const char AskedForGot
[] =
1750 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1753 static struct addrinfo
*
1754 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
1755 const struct addrinfo
*pai
, res_state res
)
1757 struct addrinfo sentinel
, *cur
;
1759 const struct afd
*afd
;
1766 int type
, class, ancount
, qdcount
;
1767 int haveanswer
, had_error
;
1768 char tbuf
[MAXDNAME
];
1769 int (*name_ok
)(const char *);
1770 char hostbuf
[8*1024];
1772 memset(&sentinel
, 0, sizeof(sentinel
));
1776 eom
= answer
->buf
+ anslen
;
1780 case T_ANY
: /*use T_ANY only for T_A/T_AAAA lookup*/
1784 return (NULL
); /* XXX should be abort(); */
1787 * find first satisfactory answer
1790 ancount
= ntohs(hp
->ancount
);
1791 qdcount
= ntohs(hp
->qdcount
);
1793 ep
= hostbuf
+ sizeof hostbuf
;
1794 cp
= answer
->buf
+ HFIXEDSZ
;
1796 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1799 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1800 if ((n
< 0) || !(*name_ok
)(bp
)) {
1801 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1805 if (qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) {
1806 /* res_send() has already verified that the query name is the
1807 * same as the one we sent; this just gets the expanded name
1808 * (i.e., with the succeeding search-domain tacked on).
1810 n
= strlen(bp
) + 1; /* for the \0 */
1811 if (n
>= MAXHOSTNAMELEN
) {
1812 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1817 /* The qname can be abbreviated, but h_name is now absolute. */
1822 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
1823 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1824 if ((n
< 0) || !(*name_ok
)(bp
)) {
1829 type
= _getshort(cp
);
1830 cp
+= INT16SZ
; /* type */
1831 class = _getshort(cp
);
1832 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
1834 cp
+= INT16SZ
; /* len */
1835 if (class != C_IN
) {
1836 /* XXX - debug? syslog? */
1838 continue; /* XXX - had_error++ ? */
1840 if ((qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) &&
1842 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
1843 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
1848 /* Get canonical name. */
1849 n
= strlen(tbuf
) + 1; /* for the \0 */
1850 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
1854 strlcpy(bp
, tbuf
, ep
- bp
);
1859 if (qtype
== T_ANY
) {
1860 if (!(type
== T_A
|| type
== T_AAAA
)) {
1864 } else if (type
!= qtype
) {
1866 if (type
!= T_KEY
&& type
!= T_SIG
)
1867 syslog(LOG_NOTICE
|LOG_AUTH
,
1868 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1869 qname
, p_class(C_IN
), p_type(qtype
),
1873 continue; /* XXX - had_error++ ? */
1878 if (strcasecmp(canonname
, bp
) != 0) {
1880 syslog(LOG_NOTICE
|LOG_AUTH
,
1881 AskedForGot
, canonname
, bp
);
1884 continue; /* XXX - had_error++ ? */
1886 if (type
== T_A
&& n
!= INADDRSZ
) {
1890 if (type
== T_AAAA
&& n
!= IN6ADDRSZ
) {
1894 #ifdef FILTER_V4MAPPED
1895 if (type
== T_AAAA
) {
1896 struct in6_addr in6
;
1897 memcpy(&in6
, cp
, sizeof(in6
));
1898 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
1908 nn
= strlen(bp
) + 1; /* for the \0 */
1912 /* don't overwrite pai */
1914 ai
.ai_family
= (type
== T_A
) ? AF_INET
: AF_INET6
;
1915 afd
= find_afd(ai
.ai_family
);
1920 cur
->ai_next
= get_ai(&ai
, afd
, (const char *)cp
);
1921 if (cur
->ai_next
== NULL
)
1923 while (cur
&& cur
->ai_next
)
1934 #if defined(RESOLVSORT)
1936 * We support only IPv4 address for backward
1937 * compatibility against gethostbyname(3).
1939 if (res
->nsort
&& qtype
== T_A
) {
1940 if (addr4sort(&sentinel
, res
) < 0) {
1941 freeaddrinfo(sentinel
.ai_next
);
1942 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1946 #endif /*RESOLVSORT*/
1948 get_canonname(pai
, sentinel
.ai_next
, qname
);
1950 get_canonname(pai
, sentinel
.ai_next
, canonname
);
1951 RES_SET_H_ERRNO(res
, NETDB_SUCCESS
);
1952 return sentinel
.ai_next
;
1955 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1961 struct addrinfo
*ai
;
1966 addr4sort(struct addrinfo
*sentinel
, res_state res
)
1968 struct addrinfo
*ai
;
1969 struct addr_ptr
*addrs
, addr
;
1970 struct sockaddr_in
*sin
;
1977 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
)
1980 return 0; /* We don't need sorting. */
1981 if ((addrs
= malloc(sizeof(struct addr_ptr
) * naddrs
)) == NULL
)
1984 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
) {
1985 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1986 for (j
= 0; (unsigned)j
< res
->nsort
; j
++) {
1987 if (res
->sort_list
[j
].addr
.s_addr
==
1988 (sin
->sin_addr
.s_addr
& res
->sort_list
[j
].mask
))
1993 if (needsort
== 0 && i
> 0 && j
< addrs
[i
- 1].aval
)
2002 while (needsort
< naddrs
) {
2003 for (j
= needsort
- 1; j
>= 0; j
--) {
2004 if (addrs
[j
].aval
> addrs
[j
+1].aval
) {
2006 addrs
[j
] = addrs
[j
+ 1];
2007 addrs
[j
+ 1] = addr
;
2015 for (i
= 0; i
< naddrs
; ++i
) {
2016 ai
->ai_next
= addrs
[i
].ai
;
2023 #endif /*RESOLVSORT*/
2027 _dns_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
2029 struct addrinfo
*ai
;
2030 querybuf
*buf
, *buf2
;
2031 const char *hostname
;
2032 const struct addrinfo
*pai
;
2033 struct addrinfo sentinel
, *cur
;
2034 struct res_target q
, q2
;
2037 hostname
= va_arg(ap
, char *);
2038 pai
= va_arg(ap
, const struct addrinfo
*);
2040 memset(&q
, 0, sizeof(q
));
2041 memset(&q2
, 0, sizeof(q2
));
2042 memset(&sentinel
, 0, sizeof(sentinel
));
2045 buf
= malloc(sizeof(*buf
));
2047 h_errno
= NETDB_INTERNAL
;
2050 buf2
= malloc(sizeof(*buf2
));
2053 h_errno
= NETDB_INTERNAL
;
2057 switch (pai
->ai_family
) {
2062 q
.answer
= buf
->buf
;
2063 q
.anslen
= sizeof(buf
->buf
);
2068 q2
.answer
= buf2
->buf
;
2069 q2
.anslen
= sizeof(buf2
->buf
);
2075 q
.answer
= buf
->buf
;
2076 q
.anslen
= sizeof(buf
->buf
);
2082 q
.answer
= buf
->buf
;
2083 q
.anslen
= sizeof(buf
->buf
);
2091 res
= __res_state();
2092 if ((res
->options
& RES_INIT
) == 0 && res_ninit(res
) == -1) {
2093 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2099 if (res_searchN(hostname
, &q
, res
) < 0) {
2106 ai
= getanswer(buf2
, q2
.n
, q2
.name
, q2
.qtype
, pai
, res
);
2109 while (cur
&& cur
->ai_next
)
2113 ai
= getanswer(buf
, q
.n
, q
.name
, q
.qtype
, pai
, res
);
2118 if (sentinel
.ai_next
== NULL
)
2119 switch (res
->res_h_errno
) {
2120 case HOST_NOT_FOUND
:
2127 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2132 _sethtent(FILE **hostf
)
2135 *hostf
= fopen(_PATH_HOSTS
, "r");
2141 _endhtent(FILE **hostf
)
2149 static struct addrinfo
*
2150 _gethtent(FILE **hostf
, const char *name
, const struct addrinfo
*pai
)
2153 char *cp
, *tname
, *cname
;
2154 struct addrinfo hints
, *res0
, *res
;
2157 char hostbuf
[8*1024];
2159 if (!*hostf
&& !(*hostf
= fopen(_PATH_HOSTS
, "r")))
2162 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, *hostf
)))
2166 cp
= strpbrk(p
, "#\n");
2169 if (!(cp
= strpbrk(p
, " \t")))
2174 /* if this is not something we're looking for, skip it. */
2176 if (*cp
== ' ' || *cp
== '\t') {
2183 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2185 if (strcasecmp(name
, tname
) == 0)
2191 /* we should not glob socktype/protocol here */
2192 memset(&hints
, 0, sizeof(hints
));
2193 hints
.ai_family
= pai
->ai_family
;
2194 hints
.ai_socktype
= SOCK_DGRAM
;
2195 hints
.ai_protocol
= 0;
2196 hints
.ai_flags
= AI_NUMERICHOST
;
2197 error
= getaddrinfo(addr
, "0", &hints
, &res0
);
2200 #ifdef FILTER_V4MAPPED
2201 /* XXX should check all items in the chain */
2202 if (res0
->ai_family
== AF_INET6
&&
2203 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)res0
->ai_addr
)->sin6_addr
)) {
2208 for (res
= res0
; res
; res
= res
->ai_next
) {
2210 res
->ai_flags
= pai
->ai_flags
;
2211 res
->ai_socktype
= pai
->ai_socktype
;
2212 res
->ai_protocol
= pai
->ai_protocol
;
2214 if (pai
->ai_flags
& AI_CANONNAME
) {
2215 if (get_canonname(pai
, res
, cname
) != 0) {
2226 _files_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
2229 const struct addrinfo
*pai
;
2230 struct addrinfo sentinel
, *cur
;
2234 name
= va_arg(ap
, char *);
2235 pai
= va_arg(ap
, struct addrinfo
*);
2237 memset(&sentinel
, 0, sizeof(sentinel
));
2241 while ((p
= _gethtent(&hostf
, name
, pai
)) != NULL
) {
2243 while (cur
&& cur
->ai_next
)
2248 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2249 if (sentinel
.ai_next
== NULL
)
2256 static struct addrinfo
*
2257 _yphostent(char *line
, const struct addrinfo
*pai
)
2259 struct addrinfo sentinel
, *cur
;
2260 struct addrinfo hints
, *res
, *res0
;
2263 const char *addr
, *canonname
;
2267 addr
= canonname
= NULL
;
2269 memset(&sentinel
, 0, sizeof(sentinel
));
2273 /* terminate line */
2274 cp
= strchr(p
, '\n');
2281 cp
= strpbrk(p
, " \t");
2283 if (canonname
== NULL
)
2293 if (*cp
== ' ' || *cp
== '\t') {
2299 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2304 hints
.ai_flags
= AI_NUMERICHOST
;
2305 error
= getaddrinfo(addr
, NULL
, &hints
, &res0
);
2307 for (res
= res0
; res
; res
= res
->ai_next
) {
2309 res
->ai_flags
= pai
->ai_flags
;
2311 if (pai
->ai_flags
& AI_CANONNAME
)
2312 get_canonname(pai
, res
, canonname
);
2317 cur
->ai_next
= res0
;
2318 while (cur
&& cur
->ai_next
)
2328 return sentinel
.ai_next
;
2333 _yp_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
2335 struct addrinfo sentinel
, *cur
;
2336 struct addrinfo
*ai
= NULL
;
2340 const struct addrinfo
*pai
;
2343 if (_yp_check(&ypdomain
) == 0)
2346 name
= va_arg(ap
, char *);
2347 pai
= va_arg(ap
, const struct addrinfo
*);
2349 memset(&sentinel
, 0, sizeof(sentinel
));
2352 /* hosts.byname is only for IPv4 (Solaris8) */
2353 if (pai
->ai_family
== PF_UNSPEC
|| pai
->ai_family
== PF_INET
) {
2354 r
= yp_match(ypdomain
, "hosts.byname", name
,
2355 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2357 struct addrinfo ai4
;
2360 ai4
.ai_family
= AF_INET
;
2361 ai
= _yphostent(ypbuf
, &ai4
);
2364 while (cur
&& cur
->ai_next
)
2371 /* ipnodes.byname can hold both IPv4/v6 */
2372 r
= yp_match(ypdomain
, "ipnodes.byname", name
,
2373 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2375 ai
= _yphostent(ypbuf
, pai
);
2381 if (sentinel
.ai_next
== NULL
) {
2382 RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND
);
2385 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2390 /* resolver logic */
2393 * Formulate a normal query, send, and await answer.
2394 * Returned answer is placed in supplied buffer "answer".
2395 * Perform preliminary check of answer, returning success only
2396 * if no error is indicated and the answer count is nonzero.
2397 * Return the size of the response on success, -1 on error.
2398 * Error number is left in h_errno.
2400 * Caller must parse answer and determine whether it answers the question.
2403 res_queryN(const char *name
, struct res_target
*target
, res_state res
)
2409 struct res_target
*t
;
2416 buf
= malloc(MAXPACKET
);
2418 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2422 for (t
= target
; t
; t
= t
->next
) {
2427 hp
= (HEADER
*)(void *)t
->answer
;
2429 /* make it easier... */
2435 oflags
= res
->_flags
;
2438 hp
->rcode
= NOERROR
; /* default */
2441 if (res
->options
& RES_DEBUG
)
2442 printf(";; res_query(%s, %d, %d)\n", name
, class, type
);
2445 n
= res_nmkquery(res
, QUERY
, name
, class, type
, NULL
, 0, NULL
,
2447 if (n
> 0 && (res
->_flags
& RES_F_EDNS0ERR
) == 0 &&
2448 (res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
)) != 0U)
2449 n
= res_nopt(res
, n
, buf
, MAXPACKET
, anslen
);
2452 if (res
->options
& RES_DEBUG
)
2453 printf(";; res_query: mkquery failed\n");
2456 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2459 n
= res_nsend(res
, buf
, n
, answer
, anslen
);
2462 * if the query choked with EDNS0, retry
2465 if ((res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
))
2467 ((oflags
^ res
->_flags
) & RES_F_EDNS0ERR
) != 0) {
2468 res
->_flags
|= RES_F_EDNS0ERR
;
2469 if (res
->options
& RES_DEBUG
)
2470 printf(";; res_nquery: retry without EDNS0\n");
2473 rcode
= hp
->rcode
; /* record most recent error */
2475 if (res
->options
& RES_DEBUG
)
2476 printf(";; res_query: send error\n");
2482 hp
->rcode
= FORMERR
; /* XXX not very informative */
2483 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
2484 rcode
= hp
->rcode
; /* record most recent error */
2486 if (res
->options
& RES_DEBUG
)
2487 printf(";; rcode = %u, ancount=%u\n", hp
->rcode
,
2488 ntohs(hp
->ancount
));
2493 ancount
+= ntohs(hp
->ancount
);
2503 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
);
2506 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2509 RES_SET_H_ERRNO(res
, NO_DATA
);
2515 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2524 * Formulate a normal query, send, and retrieve answer in supplied buffer.
2525 * Return the size of the response on success, -1 on error.
2526 * If enabled, implement search rules until answer or unrecoverable failure
2527 * is detected. Error code, if any, is left in h_errno.
2530 res_searchN(const char *name
, struct res_target
*target
, res_state res
)
2532 const char *cp
, * const *domain
;
2533 HEADER
*hp
= (HEADER
*)(void *)target
->answer
; /*XXX*/
2535 int trailing_dot
, ret
, saved_herrno
;
2536 int got_nodata
= 0, got_servfail
= 0, root_on_list
= 0;
2537 int tried_as_is
= 0;
2539 char abuf
[MAXDNAME
];
2542 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
); /* default, if we never query */
2544 for (cp
= name
; *cp
; cp
++)
2545 dots
+= (*cp
== '.');
2547 if (cp
> name
&& *--cp
== '.')
2551 * if there aren't any dots, it could be a user-level alias
2554 (cp
= res_hostalias(res
, name
, abuf
, sizeof(abuf
))) != NULL
)
2555 return (res_queryN(cp
, target
, res
));
2558 * If there are enough dots in the name, let's just give it a
2559 * try 'as is'. The threshold can be set with the "ndots" option.
2560 * Also, query 'as is', if there is a trailing dot in the name.
2563 if (dots
>= res
->ndots
|| trailing_dot
) {
2564 ret
= res_querydomainN(name
, NULL
, target
, res
);
2565 if (ret
> 0 || trailing_dot
)
2567 if (errno
== ECONNREFUSED
) {
2568 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2571 switch (res
->res_h_errno
) {
2573 case HOST_NOT_FOUND
:
2576 if (hp
->rcode
== SERVFAIL
)
2582 saved_herrno
= res
->res_h_errno
;
2587 * We do at least one level of search if
2588 * - there is no dot and RES_DEFNAME is set, or
2589 * - there is at least one dot, there is no trailing dot,
2590 * and RES_DNSRCH is set.
2592 if ((!dots
&& (res
->options
& RES_DEFNAMES
)) ||
2593 (dots
&& !trailing_dot
&& (res
->options
& RES_DNSRCH
))) {
2596 for (domain
= (const char * const *)res
->dnsrch
;
2601 if (domain
[0][0] == '\0' ||
2602 (domain
[0][0] == '.' && domain
[0][1] == '\0'))
2605 if (root_on_list
&& tried_as_is
)
2608 ret
= res_querydomainN(name
, *domain
, target
, res
);
2613 * If no server present, give up.
2614 * If name isn't found in this domain,
2615 * keep trying higher domains in the search list
2616 * (if that's enabled).
2617 * On a NO_DATA error, keep trying, otherwise
2618 * a wildcard entry of another type could keep us
2619 * from finding this entry higher in the domain.
2620 * If we get some other error (negative answer or
2621 * server failure), then stop searching up,
2622 * but try the input name below in case it's
2625 if (errno
== ECONNREFUSED
) {
2626 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2630 switch (res
->res_h_errno
) {
2634 case HOST_NOT_FOUND
:
2639 if (hp
->rcode
== SERVFAIL
) {
2640 /* try next search element, if any */
2645 /* anything else implies that we're done */
2649 * if we got here for some reason other than DNSRCH,
2650 * we only wanted one iteration of the loop, so stop.
2652 if (!(res
->options
& RES_DNSRCH
))
2657 switch (res
->res_h_errno
) {
2659 case HOST_NOT_FOUND
:
2662 if (hp
->rcode
== SERVFAIL
)
2670 * If the query has not already been tried as is then try it
2671 * unless RES_NOTLDQUERY is set and there were no dots.
2673 if ((dots
|| !searched
|| !(res
->options
& RES_NOTLDQUERY
)) &&
2674 !(tried_as_is
|| root_on_list
)) {
2675 ret
= res_querydomainN(name
, NULL
, target
, res
);
2681 * if we got here, we didn't satisfy the search.
2682 * if we did an initial full query, return that query's h_errno
2683 * (note that we wouldn't be here if that query had succeeded).
2684 * else if we ever got a nodata, send that back as the reason.
2685 * else send back meaningless h_errno, that being the one from
2686 * the last DNSRCH we did.
2689 if (saved_herrno
!= -1)
2690 RES_SET_H_ERRNO(res
, saved_herrno
);
2691 else if (got_nodata
)
2692 RES_SET_H_ERRNO(res
, NO_DATA
);
2693 else if (got_servfail
)
2694 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2699 * Perform a call on res_query on the concatenation of name and domain,
2700 * removing a trailing dot from name if domain is NULL.
2703 res_querydomainN(const char *name
, const char *domain
,
2704 struct res_target
*target
, res_state res
)
2706 char nbuf
[MAXDNAME
];
2707 const char *longname
= nbuf
;
2711 if (res
->options
& RES_DEBUG
)
2712 printf(";; res_querydomain(%s, %s)\n",
2713 name
, domain
?domain
:"<Nil>");
2715 if (domain
== NULL
) {
2717 * Check for trailing '.';
2718 * copy without '.' if present.
2721 if (n
>= MAXDNAME
) {
2722 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2725 if (n
> 0 && name
[--n
] == '.') {
2726 strncpy(nbuf
, name
, n
);
2733 if (n
+ d
+ 1 >= MAXDNAME
) {
2734 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2737 snprintf(nbuf
, sizeof(nbuf
), "%s.%s", name
, domain
);
2739 return (res_queryN(longname
, target
, res
));