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 * Issues to be discussed:
35 * - 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 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
39 * invalid. current code - SEGV on freeaddrinfo(NULL)
42 * - The code filters out AFs that are not supported by the kernel,
43 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
44 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
46 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
47 * (1) what should we do against numeric hostname (2) what should we do
48 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
49 * non-loopback address configured? global address configured?
52 #include "namespace.h"
53 #include <sys/types.h>
54 #include <sys/param.h>
55 #include <sys/socket.h>
57 #include <netinet/in.h>
58 #include <sys/queue.h>
60 #include <net/if_var.h>
61 #include <sys/sysctl.h>
62 #include <sys/ioctl.h>
63 #include <netinet6/in6_var.h> /* XXX */
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
68 #include <rpcsvc/yp_prot.h>
69 #include <rpcsvc/ypclnt.h>
80 #include "res_config.h"
88 #include "un-namespace.h"
89 #include "libc_private.h"
99 static const char in_addrany
[] = { 0, 0, 0, 0 };
100 static const char in_loopback
[] = { 127, 0, 0, 1 };
102 static const char in6_addrany
[] = {
103 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
105 static const char in6_loopback
[] = {
106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
111 TAILQ_ENTRY(policyqueue
) pc_entry
;
113 struct in6_addrpolicy pc_policy
;
116 TAILQ_HEAD(policyhead
, policyqueue
);
118 static const struct afd
{
123 const char *a_addrany
;
124 const char *a_loopback
;
129 {PF_INET6
, sizeof(struct in6_addr
),
130 sizeof(struct sockaddr_in6
),
131 offsetof(struct sockaddr_in6
, sin6_addr
),
132 in6_addrany
, in6_loopback
, 1},
137 {PF_INET
, sizeof(struct in_addr
),
138 sizeof(struct sockaddr_in
),
139 offsetof(struct sockaddr_in
, sin_addr
),
140 in_addrany
, in_loopback
, 0},
141 {0, 0, 0, 0, NULL
, NULL
, 0},
148 const char *e_protostr
;
150 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
151 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
152 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
155 static const struct explore explore
[] = {
157 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
160 { PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
161 { PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
162 { PF_INET6
, SOCK_RAW
, ANY
, NULL
, 0x05 },
164 { PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
165 { PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
166 { PF_INET
, SOCK_RAW
, ANY
, NULL
, 0x05 },
167 { PF_UNSPEC
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
168 { PF_UNSPEC
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
169 { PF_UNSPEC
, SOCK_RAW
, ANY
, NULL
, 0x05 },
170 { -1, 0, 0, NULL
, 0 },
179 #define AIO_SRCFLAG_DEPRECATED 0x1
183 struct sockaddr_storage aiou_ss
;
184 struct sockaddr aiou_sa
;
186 #define aio_srcsa aio_src_un.aiou_sa
187 u_int32_t aio_srcflag
;
190 struct policyqueue
*aio_srcpolicy
;
191 struct policyqueue
*aio_dstpolicy
;
192 struct addrinfo
*aio_ai
;
196 static const ns_src default_dns_files
[] = {
197 { NSSRC_FILES
, NS_SUCCESS
},
198 { NSSRC_DNS
, NS_SUCCESS
},
203 struct res_target
*next
;
204 const char *name
; /* domain name */
205 int qclass
, qtype
; /* class and type of query */
206 u_char
*answer
; /* buffer to put answer */
207 int anslen
; /* size of answer buffer */
208 int n
; /* result length */
211 #define MAXPACKET (64*1024)
215 u_char buf
[MAXPACKET
];
218 static int str2number(const char *, int *);
219 static int explore_null(const struct addrinfo
*,
220 const char *, struct addrinfo
**);
221 static int explore_numeric(const struct addrinfo
*, const char *,
222 const char *, struct addrinfo
**, const char *);
223 static int explore_numeric_scope(const struct addrinfo
*, const char *,
224 const char *, struct addrinfo
**);
225 static int get_canonname(const struct addrinfo
*,
226 struct addrinfo
*, const char *);
227 static struct addrinfo
*get_ai(const struct addrinfo
*,
228 const struct afd
*, const char *);
229 static int get_portmatch(const struct addrinfo
*, const char *);
230 static int get_port(struct addrinfo
*, const char *, int);
231 static const struct afd
*find_afd(int);
232 static int addrconfig(struct addrinfo
*);
233 static void set_source(struct ai_order
*, struct policyhead
*);
234 static int comp_dst(const void *, const void *);
236 static int ip6_str2scopeid(char *, struct sockaddr_in6
*, u_int32_t
*);
238 static int gai_addr2scopetype(struct sockaddr
*);
240 static int explore_fqdn(const struct addrinfo
*, const char *,
241 const char *, struct addrinfo
**);
243 static int reorder(struct addrinfo
*);
244 static int get_addrselectpolicy(struct policyhead
*);
245 static void free_addrselectpolicy(struct policyhead
*);
246 static struct policyqueue
*match_addrselectpolicy(struct sockaddr
*,
247 struct policyhead
*);
248 static int matchlen(struct sockaddr
*, struct sockaddr
*);
250 static struct addrinfo
*getanswer(const querybuf
*, int, const char *, int,
251 const struct addrinfo
*, res_state
);
252 #if defined(RESOLVSORT)
253 static int addr4sort(struct addrinfo
*, res_state
);
255 static int _dns_getaddrinfo(void *, void *, va_list);
256 static void _sethtent(FILE **);
257 static void _endhtent(FILE **);
258 static struct addrinfo
*_gethtent(FILE **, const char *,
259 const struct addrinfo
*);
260 static int _files_getaddrinfo(void *, void *, va_list);
262 static struct addrinfo
*_yphostent(char *, const struct addrinfo
*);
263 static int _yp_getaddrinfo(void *, void *, va_list);
266 static int addrinfo_id_func(char *, size_t *, va_list, void *);
267 static int addrinfo_marshal_func(char *, size_t *, void *, va_list,
269 static int addrinfo_unmarshal_func(char *, size_t, void *, va_list,
273 static int res_queryN(const char *, struct res_target
*, res_state
);
274 static int res_searchN(const char *, struct res_target
*, res_state
);
275 static int res_querydomainN(const char *, const char *,
276 struct res_target
*, res_state
);
278 /* XXX macros that make external reference is BAD. */
280 #define GET_AI(ai, afd, addr) \
282 /* external reference: pai, error, and label free */ \
283 (ai) = get_ai(pai, (afd), (addr)); \
284 if ((ai) == NULL) { \
285 error = EAI_MEMORY; \
288 } while (/*CONSTCOND*/0)
290 #define GET_PORT(ai, serv) \
292 /* external reference: error and label free */ \
293 error = get_port((ai), (serv), 0); \
296 } while (/*CONSTCOND*/0)
298 #define GET_CANONNAME(ai, str) \
300 /* external reference: pai, error and label free */ \
301 error = get_canonname(pai, (ai), (str)); \
304 } while (/*CONSTCOND*/0)
308 /* external reference: error, and label bad */ \
312 } while (/*CONSTCOND*/0)
314 #define MATCH_FAMILY(x, y, w) \
315 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
316 #define MATCH(x, y, w) \
317 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
320 freeaddrinfo(struct addrinfo
*ai
)
322 struct addrinfo
*next
;
326 if (ai
->ai_canonname
)
327 free(ai
->ai_canonname
);
328 /* no need to free(ai->ai_addr) */
335 str2number(const char *p
, int *portp
)
344 v
= strtoul(p
, &ep
, 10);
345 if (errno
== 0 && ep
&& *ep
== '\0' && v
<= UINT_MAX
) {
353 getaddrinfo(const char * __restrict hostname
, const char * __restrict servname
,
354 const struct addrinfo
* __restrict hints
, struct addrinfo
** __restrict res
)
356 struct addrinfo sentinel
;
357 struct addrinfo
*cur
;
361 struct addrinfo
*pai
;
362 const struct explore
*ex
;
365 memset(&sentinel
, 0, sizeof(sentinel
));
369 pai
->ai_family
= PF_UNSPEC
;
370 pai
->ai_socktype
= ANY
;
371 pai
->ai_protocol
= ANY
;
373 pai
->ai_canonname
= NULL
;
377 if (hostname
== NULL
&& servname
== NULL
)
380 /* error check for hints */
381 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
382 hints
->ai_addr
|| hints
->ai_next
)
383 ERR(EAI_BADHINTS
); /* xxx */
384 if (hints
->ai_flags
& ~AI_MASK
)
386 switch (hints
->ai_family
) {
396 memcpy(pai
, hints
, sizeof(*pai
));
399 * if both socktype/protocol are specified, check if they
400 * are meaningful combination.
402 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
403 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
404 if (pai
->ai_family
!= ex
->e_af
)
406 if (ex
->e_socktype
== ANY
)
408 if (ex
->e_protocol
== ANY
)
410 if (pai
->ai_socktype
== ex
->e_socktype
&&
411 pai
->ai_protocol
!= ex
->e_protocol
) {
419 * check for special cases. (1) numeric servname is disallowed if
420 * socktype/protocol are left unspecified. (2) servname is disallowed
421 * for raw and other inet{,6} sockets.
423 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
425 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
428 ai0
= *pai
; /* backup *pai */
430 if (pai
->ai_family
== PF_UNSPEC
) {
432 pai
->ai_family
= PF_INET6
;
434 pai
->ai_family
= PF_INET
;
437 error
= get_portmatch(pai
, servname
);
446 /* NULL hostname, or numeric hostname */
447 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
450 /* PF_UNSPEC entries are prepared for DNS queries only */
451 if (ex
->e_af
== PF_UNSPEC
)
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
;
468 if (hostname
== NULL
)
469 error
= explore_null(pai
, servname
, &cur
->ai_next
);
471 error
= explore_numeric_scope(pai
, hostname
, servname
,
477 while (cur
&& cur
->ai_next
)
483 * If numreic representation of AF1 can be interpreted as FQDN
484 * representation of AF2, we need to think again about the code below.
486 if (sentinel
.ai_next
) {
491 if (hostname
== NULL
)
492 ERR(EAI_NONAME
); /* used to be EAI_NODATA */
493 if (pai
->ai_flags
& AI_NUMERICHOST
)
496 if ((pai
->ai_flags
& AI_ADDRCONFIG
) != 0 && !addrconfig(&ai0
))
500 * hostname as alphabetical name.
501 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
504 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
507 /* require exact match for family field */
508 if (pai
->ai_family
!= ex
->e_af
)
511 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
512 WILD_SOCKTYPE(ex
))) {
515 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
516 WILD_PROTOCOL(ex
))) {
520 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
521 pai
->ai_socktype
= ex
->e_socktype
;
522 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
523 pai
->ai_protocol
= ex
->e_protocol
;
525 error
= explore_fqdn(pai
, hostname
, servname
, &cur
->ai_next
);
527 while (cur
&& cur
->ai_next
)
531 /* XXX inhibit errors if we have the result */
532 if (sentinel
.ai_next
)
537 * ensure we return either:
538 * - error == 0, non-NULL *res
539 * - error != 0, NULL *res
542 if (sentinel
.ai_next
) {
544 * If the returned entry is for an active connection,
545 * and the given name is not numeric, reorder the
546 * list, so that the application would try the list
547 * in the most efficient order. Since the head entry
548 * of the original list may contain ai_canonname and
549 * that entry may be moved elsewhere in the new list,
550 * we keep the pointer and will restore it in the new
551 * head entry. (Note that RFC3493 requires the head
552 * entry store it when requested by the caller).
554 if (hints
== NULL
|| !(hints
->ai_flags
& AI_PASSIVE
)) {
559 sentinel
.ai_next
->ai_canonname
;
560 sentinel
.ai_next
->ai_canonname
= NULL
;
562 if (sentinel
.ai_next
->ai_canonname
==
564 sentinel
.ai_next
->ai_canonname
566 } else if (canonname
!= NULL
)
570 *res
= sentinel
.ai_next
;
577 if (sentinel
.ai_next
)
578 freeaddrinfo(sentinel
.ai_next
);
584 reorder(struct addrinfo
*sentinel
)
586 struct addrinfo
*ai
, **aip
;
587 struct ai_order
*aio
;
589 struct policyhead policyhead
;
591 /* count the number of addrinfo elements for sorting. */
592 for (n
= 0, ai
= sentinel
->ai_next
; ai
!= NULL
; ai
= ai
->ai_next
, n
++)
596 * If the number is small enough, we can skip the reordering process.
601 /* allocate a temporary array for sort and initialization of it. */
602 if ((aio
= malloc(sizeof(*aio
) * n
)) == NULL
)
603 return(n
); /* give up reordering */
604 memset(aio
, 0, sizeof(*aio
) * n
);
606 /* retrieve address selection policy from the kernel */
607 TAILQ_INIT(&policyhead
);
608 if (!get_addrselectpolicy(&policyhead
)) {
609 /* no policy is installed into kernel, we don't sort. */
614 for (i
= 0, ai
= sentinel
->ai_next
; i
< n
; ai
= ai
->ai_next
, i
++) {
616 aio
[i
].aio_dstscope
= gai_addr2scopetype(ai
->ai_addr
);
617 aio
[i
].aio_dstpolicy
= match_addrselectpolicy(ai
->ai_addr
,
619 set_source(&aio
[i
], &policyhead
);
622 /* perform sorting. */
623 qsort(aio
, n
, sizeof(*aio
), comp_dst
);
625 /* reorder the addrinfo chain. */
626 for (i
= 0, aip
= &sentinel
->ai_next
; i
< n
; i
++) {
627 *aip
= aio
[i
].aio_ai
;
628 aip
= &aio
[i
].aio_ai
->ai_next
;
632 /* cleanup and return */
634 free_addrselectpolicy(&policyhead
);
639 get_addrselectpolicy(struct policyhead
*head
)
642 int mib
[] = { CTL_NET
, PF_INET6
, IPPROTO_IPV6
, IPV6CTL_ADDRCTLPOLICY
};
645 struct in6_addrpolicy
*pol
, *ep
;
647 if (sysctl(mib
, NELEM(mib
), NULL
, &l
, NULL
, 0) < 0)
649 if ((buf
= malloc(l
)) == NULL
)
651 if (sysctl(mib
, NELEM(mib
), buf
, &l
, NULL
, 0) < 0) {
656 ep
= (struct in6_addrpolicy
*)(buf
+ l
);
657 for (pol
= (struct in6_addrpolicy
*)buf
; pol
+ 1 <= ep
; pol
++) {
658 struct policyqueue
*new;
660 if ((new = malloc(sizeof(*new))) == NULL
) {
661 free_addrselectpolicy(head
); /* make the list empty */
664 new->pc_policy
= *pol
;
665 TAILQ_INSERT_TAIL(head
, new, pc_entry
);
676 free_addrselectpolicy(struct policyhead
*head
)
678 struct policyqueue
*ent
, *nent
;
680 for (ent
= TAILQ_FIRST(head
); ent
; ent
= nent
) {
681 nent
= TAILQ_NEXT(ent
, pc_entry
);
682 TAILQ_REMOVE(head
, ent
, pc_entry
);
687 static struct policyqueue
*
688 match_addrselectpolicy(struct sockaddr
*addr
, struct policyhead
*head
)
691 struct policyqueue
*ent
, *bestent
= NULL
;
692 struct in6_addrpolicy
*pol
;
693 int matchlen
, bestmatchlen
= -1;
694 u_char
*mp
, *ep
, *k
, *p
, m
;
695 struct sockaddr_in6 key
;
697 switch(addr
->sa_family
) {
699 key
= *(struct sockaddr_in6
*)addr
;
702 /* convert the address into IPv4-mapped IPv6 address. */
703 memset(&key
, 0, sizeof(key
));
704 key
.sin6_family
= AF_INET6
;
705 key
.sin6_len
= sizeof(key
);
706 key
.sin6_addr
.s6_addr
[10] = 0xff;
707 key
.sin6_addr
.s6_addr
[11] = 0xff;
708 memcpy(&key
.sin6_addr
.s6_addr
[12],
709 &((struct sockaddr_in
*)addr
)->sin_addr
, 4);
715 for (ent
= TAILQ_FIRST(head
); ent
; ent
= TAILQ_NEXT(ent
, pc_entry
)) {
716 pol
= &ent
->pc_policy
;
719 mp
= (u_char
*)&pol
->addrmask
.sin6_addr
;
720 ep
= mp
+ 16; /* XXX: scope field? */
721 k
= (u_char
*)&key
.sin6_addr
;
722 p
= (u_char
*)&pol
->addr
.sin6_addr
;
723 for (; mp
< ep
&& *mp
; mp
++, k
++, p
++) {
726 goto next
; /* not match */
727 if (m
== 0xff) /* short cut for a typical case */
737 /* matched. check if this is better than the current best. */
738 if (matchlen
> bestmatchlen
) {
740 bestmatchlen
= matchlen
;
755 set_source(struct ai_order
*aio
, struct policyhead
*ph
)
757 struct addrinfo ai
= *aio
->aio_ai
;
758 struct sockaddr_storage ss
;
762 /* set unspec ("no source is available"), just in case */
763 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
764 aio
->aio_srcscope
= -1;
766 switch(ai
.ai_family
) {
772 default: /* ignore unsupported AFs explicitly */
776 /* XXX: make a dummy addrinfo to call connect() */
777 ai
.ai_socktype
= SOCK_DGRAM
;
778 ai
.ai_protocol
= IPPROTO_UDP
; /* is UDP too specific? */
780 memset(&ss
, 0, sizeof(ss
));
781 memcpy(&ss
, ai
.ai_addr
, ai
.ai_addrlen
);
782 ai
.ai_addr
= (struct sockaddr
*)&ss
;
783 get_port(&ai
, "1", 0);
785 /* open a socket to get the source address for the given dst */
786 if ((s
= _socket(ai
.ai_family
, ai
.ai_socktype
, ai
.ai_protocol
)) < 0)
787 return; /* give up */
788 if (_connect(s
, ai
.ai_addr
, ai
.ai_addrlen
) < 0)
790 srclen
= ai
.ai_addrlen
;
791 if (_getsockname(s
, &aio
->aio_srcsa
, &srclen
) < 0) {
792 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
795 aio
->aio_srcscope
= gai_addr2scopetype(&aio
->aio_srcsa
);
796 aio
->aio_srcpolicy
= match_addrselectpolicy(&aio
->aio_srcsa
, ph
);
797 aio
->aio_matchlen
= matchlen(&aio
->aio_srcsa
, aio
->aio_ai
->ai_addr
);
799 if (ai
.ai_family
== AF_INET6
) {
800 struct in6_ifreq ifr6
;
803 /* XXX: interface name should not be hardcoded */
804 strncpy(ifr6
.ifr_name
, "lo0", sizeof(ifr6
.ifr_name
));
805 memset(&ifr6
, 0, sizeof(ifr6
));
806 memcpy(&ifr6
.ifr_addr
, ai
.ai_addr
, ai
.ai_addrlen
);
807 if (_ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) == 0) {
808 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
809 if ((flags6
& IN6_IFF_DEPRECATED
))
810 aio
->aio_srcflag
|= AIO_SRCFLAG_DEPRECATED
;
821 matchlen(struct sockaddr
*src
, struct sockaddr
*dst
)
828 switch (src
->sa_family
) {
831 s
= (u_char
*)&((struct sockaddr_in6
*)src
)->sin6_addr
;
832 d
= (u_char
*)&((struct sockaddr_in6
*)dst
)->sin6_addr
;
833 addrlen
= sizeof(struct in6_addr
);
838 s
= (u_char
*)&((struct sockaddr_in
*)src
)->sin_addr
;
839 d
= (u_char
*)&((struct sockaddr_in
*)dst
)->sin_addr
;
840 addrlen
= sizeof(struct in_addr
);
848 if ((r
= (*d
++ ^ *s
++)) != 0) {
849 while (r
< addrlen
* 8) {
860 comp_dst(const void *arg1
, const void *arg2
)
862 const struct ai_order
*dst1
= arg1
, *dst2
= arg2
;
865 * Rule 1: Avoid unusable destinations.
866 * XXX: we currently do not consider if an appropriate route exists.
868 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
869 dst2
->aio_srcsa
.sa_family
== AF_UNSPEC
) {
872 if (dst1
->aio_srcsa
.sa_family
== AF_UNSPEC
&&
873 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
877 /* Rule 2: Prefer matching scope. */
878 if (dst1
->aio_dstscope
== dst1
->aio_srcscope
&&
879 dst2
->aio_dstscope
!= dst2
->aio_srcscope
) {
882 if (dst1
->aio_dstscope
!= dst1
->aio_srcscope
&&
883 dst2
->aio_dstscope
== dst2
->aio_srcscope
) {
887 /* Rule 3: Avoid deprecated addresses. */
888 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
889 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
890 if (!(dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
891 (dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
894 if ((dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
895 !(dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
900 /* Rule 4: Prefer home addresses. */
901 /* XXX: not implemented yet */
903 /* Rule 5: Prefer matching label. */
905 if (dst1
->aio_srcpolicy
&& dst1
->aio_dstpolicy
&&
906 dst1
->aio_srcpolicy
->pc_policy
.label
==
907 dst1
->aio_dstpolicy
->pc_policy
.label
&&
908 (dst2
->aio_srcpolicy
== NULL
|| dst2
->aio_dstpolicy
== NULL
||
909 dst2
->aio_srcpolicy
->pc_policy
.label
!=
910 dst2
->aio_dstpolicy
->pc_policy
.label
)) {
913 if (dst2
->aio_srcpolicy
&& dst2
->aio_dstpolicy
&&
914 dst2
->aio_srcpolicy
->pc_policy
.label
==
915 dst2
->aio_dstpolicy
->pc_policy
.label
&&
916 (dst1
->aio_srcpolicy
== NULL
|| dst1
->aio_dstpolicy
== NULL
||
917 dst1
->aio_srcpolicy
->pc_policy
.label
!=
918 dst1
->aio_dstpolicy
->pc_policy
.label
)) {
923 /* Rule 6: Prefer higher precedence. */
925 if (dst1
->aio_dstpolicy
&&
926 (dst2
->aio_dstpolicy
== NULL
||
927 dst1
->aio_dstpolicy
->pc_policy
.preced
>
928 dst2
->aio_dstpolicy
->pc_policy
.preced
)) {
931 if (dst2
->aio_dstpolicy
&&
932 (dst1
->aio_dstpolicy
== NULL
||
933 dst2
->aio_dstpolicy
->pc_policy
.preced
>
934 dst1
->aio_dstpolicy
->pc_policy
.preced
)) {
939 /* Rule 7: Prefer native transport. */
940 /* XXX: not implemented yet */
942 /* Rule 8: Prefer smaller scope. */
943 if (dst1
->aio_dstscope
>= 0 &&
944 dst1
->aio_dstscope
< dst2
->aio_dstscope
) {
947 if (dst2
->aio_dstscope
>= 0 &&
948 dst2
->aio_dstscope
< dst1
->aio_dstscope
) {
953 * Rule 9: Use longest matching prefix.
954 * We compare the match length in a same AF only.
956 if (dst1
->aio_ai
->ai_addr
->sa_family
==
957 dst2
->aio_ai
->ai_addr
->sa_family
) {
958 if (dst1
->aio_matchlen
> dst2
->aio_matchlen
) {
961 if (dst1
->aio_matchlen
< dst2
->aio_matchlen
) {
966 /* Rule 10: Otherwise, leave the order unchanged. */
972 * XXX: we should standardize the functions and link them as standard
976 gai_addr2scopetype(struct sockaddr
*sa
)
979 struct sockaddr_in6
*sa6
;
981 struct sockaddr_in
*sa4
;
983 switch(sa
->sa_family
) {
986 sa6
= (struct sockaddr_in6
*)sa
;
987 if (IN6_IS_ADDR_MULTICAST(&sa6
->sin6_addr
)) {
988 /* just use the scope field of the multicast address */
989 return(sa6
->sin6_addr
.s6_addr
[2] & 0x0f);
992 * Unicast addresses: map scope type to corresponding scope
993 * value defined for multcast addresses.
994 * XXX: hardcoded scope type values are bad...
996 if (IN6_IS_ADDR_LOOPBACK(&sa6
->sin6_addr
))
997 return(1); /* node local scope */
998 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
))
999 return(2); /* link-local scope */
1000 if (IN6_IS_ADDR_SITELOCAL(&sa6
->sin6_addr
))
1001 return(5); /* site-local scope */
1002 return(14); /* global scope */
1007 * IPv4 pseudo scoping according to RFC 3484.
1009 sa4
= (struct sockaddr_in
*)sa
;
1010 /* IPv4 autoconfiguration addresses have link-local scope. */
1011 if (((u_char
*)&sa4
->sin_addr
)[0] == 169 &&
1012 ((u_char
*)&sa4
->sin_addr
)[1] == 254)
1014 /* Private addresses have site-local scope. */
1015 if (((u_char
*)&sa4
->sin_addr
)[0] == 10 ||
1016 (((u_char
*)&sa4
->sin_addr
)[0] == 172 &&
1017 (((u_char
*)&sa4
->sin_addr
)[1] & 0xf0) == 16) ||
1018 (((u_char
*)&sa4
->sin_addr
)[0] == 192 &&
1019 ((u_char
*)&sa4
->sin_addr
)[1] == 168))
1020 return(14); /* XXX: It should be 5 unless NAT */
1021 /* Loopback addresses have link-local scope. */
1022 if (((u_char
*)&sa4
->sin_addr
)[0] == 127)
1027 errno
= EAFNOSUPPORT
; /* is this a good error? */
1034 * passive socket -> anyaddr (0.0.0.0 or ::)
1035 * non-passive socket -> localhost (127.0.0.1 or ::1)
1038 explore_null(const struct addrinfo
*pai
, const char *servname
,
1039 struct addrinfo
**res
)
1042 const struct afd
*afd
;
1043 struct addrinfo
*ai
;
1050 * filter out AFs that are not supported by the kernel
1053 s
= _socket(pai
->ai_family
, SOCK_DGRAM
, 0);
1055 if (errno
!= EMFILE
)
1061 * if the servname does not match socktype/protocol, ignore it.
1063 if (get_portmatch(pai
, servname
) != 0)
1066 afd
= find_afd(pai
->ai_family
);
1070 if (pai
->ai_flags
& AI_PASSIVE
) {
1071 GET_AI(ai
, afd
, afd
->a_addrany
);
1072 GET_PORT(ai
, servname
);
1074 GET_AI(ai
, afd
, afd
->a_loopback
);
1075 GET_PORT(ai
, servname
);
1091 explore_numeric(const struct addrinfo
*pai
, const char *hostname
,
1092 const char *servname
, struct addrinfo
**res
,
1093 const char *canonname
)
1095 const struct afd
*afd
;
1096 struct addrinfo
*ai
;
1098 char pton
[PTON_MAX
];
1104 * if the servname does not match socktype/protocol, ignore it.
1106 if (get_portmatch(pai
, servname
) != 0)
1109 afd
= find_afd(pai
->ai_family
);
1113 switch (afd
->a_af
) {
1116 * RFC3493 requires getaddrinfo() to accept AF_INET formats
1117 * that are accepted by inet_addr() and its family. The
1118 * accepted forms includes the "classful" one, which inet_pton
1119 * does not accept. So we need to separate the case for
1122 if (inet_aton(hostname
, (struct in_addr
*)pton
) != 1)
1126 if (inet_pton(afd
->a_af
, hostname
, pton
) != 1)
1131 if (pai
->ai_family
== afd
->a_af
) {
1132 GET_AI(ai
, afd
, pton
);
1133 GET_PORT(ai
, servname
);
1134 if ((pai
->ai_flags
& AI_CANONNAME
)) {
1136 * Set the numeric address itself as the canonical
1137 * name, based on a clarification in RFC3493.
1139 GET_CANONNAME(ai
, canonname
);
1143 * XXX: This should not happen since we already matched the AF
1160 * numeric hostname with scope
1163 explore_numeric_scope(const struct addrinfo
*pai
, const char *hostname
,
1164 const char *servname
, struct addrinfo
**res
)
1166 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
1167 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1169 const struct afd
*afd
;
1170 struct addrinfo
*cur
;
1172 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
1173 struct sockaddr_in6
*sin6
;
1176 * if the servname does not match socktype/protocol, ignore it.
1178 if (get_portmatch(pai
, servname
) != 0)
1181 afd
= find_afd(pai
->ai_family
);
1186 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1188 cp
= strchr(hostname
, SCOPE_DELIMITER
);
1190 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1193 * Handle special case of <scoped_address><delimiter><scope id>
1195 hostname2
= strdup(hostname
);
1196 if (hostname2
== NULL
)
1198 /* terminate at the delimiter */
1199 hostname2
[cp
- hostname
] = '\0';
1203 error
= explore_numeric(pai
, addr
, servname
, res
, hostname
);
1207 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
1208 if (cur
->ai_family
!= AF_INET6
)
1210 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
1211 if (ip6_str2scopeid(scope
, sin6
, &scopeid
) == -1) {
1213 return(EAI_NONAME
); /* XXX: is return OK? */
1215 sin6
->sin6_scope_id
= scopeid
;
1226 get_canonname(const struct addrinfo
*pai
, struct addrinfo
*ai
, const char *str
)
1228 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
1229 ai
->ai_canonname
= strdup(str
);
1230 if (ai
->ai_canonname
== NULL
)
1236 static struct addrinfo
*
1237 get_ai(const struct addrinfo
*pai
, const struct afd
*afd
, const char *addr
)
1240 struct addrinfo
*ai
;
1242 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
1243 + (afd
->a_socklen
));
1247 memcpy(ai
, pai
, sizeof(struct addrinfo
));
1248 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
1249 memset(ai
->ai_addr
, 0, (size_t)afd
->a_socklen
);
1250 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
1251 ai
->ai_addrlen
= afd
->a_socklen
;
1252 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
1253 p
= (char *)(void *)(ai
->ai_addr
);
1254 memcpy(p
+ afd
->a_off
, addr
, (size_t)afd
->a_addrlen
);
1259 get_portmatch(const struct addrinfo
*ai
, const char *servname
)
1262 /* get_port does not touch first argument when matchonly == 1. */
1263 /* LINTED const cast */
1264 return get_port((struct addrinfo
*)ai
, servname
, 1);
1268 get_port(struct addrinfo
*ai
, const char *servname
, int matchonly
)
1275 if (servname
== NULL
)
1277 switch (ai
->ai_family
) {
1287 switch (ai
->ai_socktype
) {
1298 return EAI_SOCKTYPE
;
1301 error
= str2number(servname
, &port
);
1305 if (port
< 0 || port
> 65535)
1309 if (ai
->ai_flags
& AI_NUMERICSERV
)
1311 switch (ai
->ai_socktype
) {
1323 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1329 switch (ai
->ai_family
) {
1331 ((struct sockaddr_in
*)(void *)
1332 ai
->ai_addr
)->sin_port
= port
;
1336 ((struct sockaddr_in6
*)(void *)
1337 ai
->ai_addr
)->sin6_port
= port
;
1346 static const struct afd
*
1349 const struct afd
*afd
;
1351 if (af
== PF_UNSPEC
)
1353 for (afd
= afdl
; afd
->a_af
; afd
++) {
1354 if (afd
->a_af
== af
)
1361 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1362 * will take care of it.
1363 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1364 * if the code is right or not.
1366 * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
1370 addrconfig(struct addrinfo
*pai
)
1376 * Note that implementation dependent test for address
1377 * configuration should be done everytime called
1378 * (or apropriate interval),
1379 * because addresses will be dynamically assigned or deleted.
1381 af
= pai
->ai_family
;
1382 if (af
== AF_UNSPEC
) {
1383 if ((s
= _socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0)
1387 if ((s
= _socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
1393 if (af
!= AF_UNSPEC
) {
1394 if ((s
= _socket(af
, SOCK_DGRAM
, 0)) < 0)
1398 pai
->ai_family
= af
;
1403 /* convert a string to a scope identifier. XXX: IPv6 specific */
1405 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
, u_int32_t
*scopeid
)
1408 struct in6_addr
*a6
;
1411 a6
= &sin6
->sin6_addr
;
1413 /* empty scopeid portion is invalid */
1417 if (IN6_IS_ADDR_LINKLOCAL(a6
) || IN6_IS_ADDR_MC_LINKLOCAL(a6
)) {
1419 * We currently assume a one-to-one mapping between links
1420 * and interfaces, so we simply use interface indices for
1421 * like-local scopes.
1423 *scopeid
= if_nametoindex(scope
);
1429 /* still unclear about literal, allow numeric only - placeholder */
1430 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1432 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1435 goto trynumeric
; /* global */
1437 /* try to convert to a numeric id as a last resort */
1440 lscopeid
= strtoul(scope
, &ep
, 10);
1441 *scopeid
= (u_int32_t
)(lscopeid
& 0xffffffffUL
);
1442 if (errno
== 0 && ep
&& *ep
== '\0' && *scopeid
== lscopeid
)
1452 addrinfo_id_func(char *buffer
, size_t *buffer_size
, va_list ap
,
1453 void *cache_mdata __unused
)
1458 const int op_id
= 0; /* identifies the getaddrinfo for the cache */
1460 struct addrinfo
*hints
;
1463 int ai_flags
, ai_family
, ai_socktype
, ai_protocol
;
1464 size_t desired_size
, size
;
1466 statp
= __res_state();
1467 res_options
= statp
->options
& (RES_RECURSE
| RES_DEFNAMES
|
1468 RES_DNSRCH
| RES_NOALIASES
| RES_USE_INET6
);
1470 hostname
= va_arg(ap
, char *);
1471 hints
= va_arg(ap
, struct addrinfo
*);
1473 desired_size
= sizeof(res_options
) + sizeof(int) + sizeof(int) * 4;
1474 if (hostname
!= NULL
) {
1475 size
= strlen(hostname
);
1476 desired_size
+= size
+ 1;
1480 if (desired_size
> *buffer_size
) {
1481 *buffer_size
= desired_size
;
1486 ai_flags
= ai_family
= ai_socktype
= ai_protocol
= 0;
1488 ai_flags
= hints
->ai_flags
;
1489 ai_family
= hints
->ai_family
;
1490 ai_socktype
= hints
->ai_socktype
;
1491 ai_protocol
= hints
->ai_protocol
;
1495 memcpy(p
, &res_options
, sizeof(res_options
));
1496 p
+= sizeof(res_options
);
1498 memcpy(p
, &op_id
, sizeof(int));
1501 memcpy(p
, &ai_flags
, sizeof(int));
1504 memcpy(p
, &ai_family
, sizeof(int));
1507 memcpy(p
, &ai_socktype
, sizeof(int));
1510 memcpy(p
, &ai_protocol
, sizeof(int));
1513 if (hostname
!= NULL
)
1514 memcpy(p
, hostname
, size
);
1516 *buffer_size
= desired_size
;
1517 return (NS_SUCCESS
);
1521 addrinfo_marshal_func(char *buffer
, size_t *buffer_size
, void *retval
,
1522 va_list ap __unused
, void *cache_mdata __unused
)
1524 struct addrinfo
*ai
, *cai
;
1526 size_t desired_size
, size
, ai_size
;
1528 ai
= *((struct addrinfo
**)retval
);
1530 desired_size
= sizeof(size_t);
1532 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1533 desired_size
+= sizeof(struct addrinfo
) + cai
->ai_addrlen
;
1534 if (cai
->ai_canonname
!= NULL
)
1535 desired_size
+= sizeof(size_t) +
1536 strlen(cai
->ai_canonname
);
1540 if (desired_size
> *buffer_size
) {
1541 /* this assignment is here for future use */
1543 *buffer_size
= desired_size
;
1547 memset(buffer
, 0, desired_size
);
1550 memcpy(p
, &ai_size
, sizeof(size_t));
1551 p
+= sizeof(size_t);
1552 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1553 memcpy(p
, cai
, sizeof(struct addrinfo
));
1554 p
+= sizeof(struct addrinfo
);
1556 memcpy(p
, cai
->ai_addr
, cai
->ai_addrlen
);
1557 p
+= cai
->ai_addrlen
;
1559 if (cai
->ai_canonname
!= NULL
) {
1560 size
= strlen(cai
->ai_canonname
);
1561 memcpy(p
, &size
, sizeof(size_t));
1562 p
+= sizeof(size_t);
1564 memcpy(p
, cai
->ai_canonname
, size
);
1569 return (NS_SUCCESS
);
1573 addrinfo_unmarshal_func(char *buffer
, size_t buffer_size __unused
, void *retval
,
1574 va_list ap __unused
, void *cache_mdata __unused
)
1576 struct addrinfo new_ai
, *result
, *sentinel
, *lasts
;
1579 size_t ai_size
, ai_i
, size
;
1582 memcpy(&ai_size
, p
, sizeof(size_t));
1583 p
+= sizeof(size_t);
1587 for (ai_i
= 0; ai_i
< ai_size
; ++ai_i
) {
1588 memcpy(&new_ai
, p
, sizeof(struct addrinfo
));
1589 p
+= sizeof(struct addrinfo
);
1590 size
= new_ai
.ai_addrlen
+ sizeof(struct addrinfo
) +
1593 sentinel
= (struct addrinfo
*)malloc(size
);
1594 memset(sentinel
, 0, size
);
1596 memcpy(sentinel
, &new_ai
, sizeof(struct addrinfo
));
1597 sentinel
->ai_addr
= (struct sockaddr
*)_ALIGN((char *)sentinel
+
1598 sizeof(struct addrinfo
));
1600 memcpy(sentinel
->ai_addr
, p
, new_ai
.ai_addrlen
);
1601 p
+= new_ai
.ai_addrlen
;
1603 if (new_ai
.ai_canonname
!= NULL
) {
1604 memcpy(&size
, p
, sizeof(size_t));
1605 p
+= sizeof(size_t);
1607 sentinel
->ai_canonname
= (char *)malloc(size
+ 1);
1608 memset(sentinel
->ai_canonname
, 0, size
+ 1);
1610 memcpy(sentinel
->ai_canonname
, p
, size
);
1614 if (result
== NULL
) {
1618 lasts
->ai_next
= sentinel
;
1623 *((struct addrinfo
**)retval
) = result
;
1624 return (NS_SUCCESS
);
1626 #endif /* NS_CACHING */
1629 * FQDN hostname, DNS lookup
1632 explore_fqdn(const struct addrinfo
*pai
, const char *hostname
,
1633 const char *servname
, struct addrinfo
**res
)
1635 struct addrinfo
*result
;
1636 struct addrinfo
*cur
;
1640 static const nss_cache_info cache_info
=
1641 NS_COMMON_CACHE_INFO_INITIALIZER(
1642 hosts
, NULL
, addrinfo_id_func
, addrinfo_marshal_func
,
1643 addrinfo_unmarshal_func
);
1645 static const ns_dtab dtab
[] = {
1646 NS_FILES_CB(_files_getaddrinfo
, NULL
)
1647 { NSSRC_DNS
, _dns_getaddrinfo
, NULL
}, /* force -DHESIOD */
1648 NS_NIS_CB(_yp_getaddrinfo
, NULL
)
1650 NS_CACHE_CB(&cache_info
)
1658 * if the servname does not match socktype/protocol, ignore it.
1660 if (get_portmatch(pai
, servname
) != 0)
1663 switch (_nsdispatch(&result
, dtab
, NSDB_HOSTS
, "getaddrinfo",
1664 default_dns_files
, hostname
, pai
)) {
1676 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
1677 GET_PORT(cur
, servname
);
1678 /* canonname should be filled already */
1689 freeaddrinfo(result
);
1694 static const char AskedForGot
[] =
1695 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1698 static struct addrinfo
*
1699 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
1700 const struct addrinfo
*pai
, res_state res
)
1702 struct addrinfo sentinel
, *cur
;
1704 const struct afd
*afd
;
1711 int type
, class, ancount
, qdcount
;
1712 int haveanswer
, had_error
;
1713 char tbuf
[MAXDNAME
];
1714 int (*name_ok
)(const char *);
1715 char hostbuf
[8*1024];
1717 memset(&sentinel
, 0, sizeof(sentinel
));
1721 eom
= answer
->buf
+ anslen
;
1725 case T_ANY
: /*use T_ANY only for T_A/T_AAAA lookup*/
1729 return (NULL
); /* XXX should be abort(); */
1732 * find first satisfactory answer
1735 ancount
= ntohs(hp
->ancount
);
1736 qdcount
= ntohs(hp
->qdcount
);
1738 ep
= hostbuf
+ sizeof hostbuf
;
1739 cp
= answer
->buf
+ HFIXEDSZ
;
1741 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1744 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1745 if ((n
< 0) || !(*name_ok
)(bp
)) {
1746 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1750 if (qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) {
1751 /* res_send() has already verified that the query name is the
1752 * same as the one we sent; this just gets the expanded name
1753 * (i.e., with the succeeding search-domain tacked on).
1755 n
= strlen(bp
) + 1; /* for the \0 */
1756 if (n
>= MAXHOSTNAMELEN
) {
1757 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1762 /* The qname can be abbreviated, but h_name is now absolute. */
1767 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
1768 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1769 if ((n
< 0) || !(*name_ok
)(bp
)) {
1774 type
= _getshort(cp
);
1775 cp
+= INT16SZ
; /* type */
1776 class = _getshort(cp
);
1777 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
1779 cp
+= INT16SZ
; /* len */
1780 if (class != C_IN
) {
1781 /* XXX - debug? syslog? */
1783 continue; /* XXX - had_error++ ? */
1785 if ((qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) &&
1787 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
1788 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
1793 /* Get canonical name. */
1794 n
= strlen(tbuf
) + 1; /* for the \0 */
1795 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
1799 strlcpy(bp
, tbuf
, ep
- bp
);
1804 if (qtype
== T_ANY
) {
1805 if (!(type
== T_A
|| type
== T_AAAA
)) {
1809 } else if (type
!= qtype
) {
1811 if (type
!= T_KEY
&& type
!= T_SIG
)
1812 syslog(LOG_NOTICE
|LOG_AUTH
,
1813 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1814 qname
, p_class(C_IN
), p_type(qtype
),
1818 continue; /* XXX - had_error++ ? */
1823 if (strcasecmp(canonname
, bp
) != 0) {
1825 syslog(LOG_NOTICE
|LOG_AUTH
,
1826 AskedForGot
, canonname
, bp
);
1829 continue; /* XXX - had_error++ ? */
1831 if (type
== T_A
&& n
!= INADDRSZ
) {
1835 if (type
== T_AAAA
&& n
!= IN6ADDRSZ
) {
1839 #ifdef FILTER_V4MAPPED
1840 if (type
== T_AAAA
) {
1841 struct in6_addr in6
;
1842 memcpy(&in6
, cp
, sizeof(in6
));
1843 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
1853 nn
= strlen(bp
) + 1; /* for the \0 */
1857 /* don't overwrite pai */
1859 ai
.ai_family
= (type
== T_A
) ? AF_INET
: AF_INET6
;
1860 afd
= find_afd(ai
.ai_family
);
1865 cur
->ai_next
= get_ai(&ai
, afd
, (const char *)cp
);
1866 if (cur
->ai_next
== NULL
)
1868 while (cur
&& cur
->ai_next
)
1879 #if defined(RESOLVSORT)
1881 * We support only IPv4 address for backward
1882 * compatibility against gethostbyname(3).
1884 if (res
->nsort
&& qtype
== T_A
) {
1885 if (addr4sort(&sentinel
, res
) < 0) {
1886 freeaddrinfo(sentinel
.ai_next
);
1887 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1891 #endif /*RESOLVSORT*/
1893 get_canonname(pai
, sentinel
.ai_next
, qname
);
1895 get_canonname(pai
, sentinel
.ai_next
, canonname
);
1896 RES_SET_H_ERRNO(res
, NETDB_SUCCESS
);
1897 return sentinel
.ai_next
;
1900 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1906 struct addrinfo
*ai
;
1911 addr4sort(struct addrinfo
*sentinel
, res_state res
)
1913 struct addrinfo
*ai
;
1914 struct addr_ptr
*addrs
, addr
;
1915 struct sockaddr_in
*sin
;
1922 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
)
1925 return 0; /* We don't need sorting. */
1926 if ((addrs
= malloc(sizeof(struct addr_ptr
) * naddrs
)) == NULL
)
1929 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
) {
1930 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1931 for (j
= 0; (unsigned)j
< res
->nsort
; j
++) {
1932 if (res
->sort_list
[j
].addr
.s_addr
==
1933 (sin
->sin_addr
.s_addr
& res
->sort_list
[j
].mask
))
1938 if (needsort
== 0 && i
> 0 && j
< addrs
[i
- 1].aval
)
1947 while (needsort
< naddrs
) {
1948 for (j
= needsort
- 1; j
>= 0; j
--) {
1949 if (addrs
[j
].aval
> addrs
[j
+1].aval
) {
1951 addrs
[j
] = addrs
[j
+ 1];
1952 addrs
[j
+ 1] = addr
;
1960 for (i
= 0; i
< naddrs
; ++i
) {
1961 ai
->ai_next
= addrs
[i
].ai
;
1968 #endif /*RESOLVSORT*/
1972 _dns_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
1974 struct addrinfo
*ai
;
1975 querybuf
*buf
, *buf2
;
1976 const char *hostname
;
1977 const struct addrinfo
*pai
;
1978 struct addrinfo sentinel
, *cur
;
1979 struct res_target q
, q2
;
1982 hostname
= va_arg(ap
, char *);
1983 pai
= va_arg(ap
, const struct addrinfo
*);
1985 memset(&q
, 0, sizeof(q
));
1986 memset(&q2
, 0, sizeof(q2
));
1987 memset(&sentinel
, 0, sizeof(sentinel
));
1990 buf
= malloc(sizeof(*buf
));
1992 h_errno
= NETDB_INTERNAL
;
1995 buf2
= malloc(sizeof(*buf2
));
1998 h_errno
= NETDB_INTERNAL
;
2002 switch (pai
->ai_family
) {
2007 q
.answer
= buf
->buf
;
2008 q
.anslen
= sizeof(buf
->buf
);
2013 q2
.answer
= buf2
->buf
;
2014 q2
.anslen
= sizeof(buf2
->buf
);
2020 q
.answer
= buf
->buf
;
2021 q
.anslen
= sizeof(buf
->buf
);
2027 q
.answer
= buf
->buf
;
2028 q
.anslen
= sizeof(buf
->buf
);
2036 res
= __res_state();
2037 if ((res
->options
& RES_INIT
) == 0 && res_ninit(res
) == -1) {
2038 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2044 if (res_searchN(hostname
, &q
, res
) < 0) {
2051 ai
= getanswer(buf2
, q2
.n
, q2
.name
, q2
.qtype
, pai
, res
);
2054 while (cur
&& cur
->ai_next
)
2058 ai
= getanswer(buf
, q
.n
, q
.name
, q
.qtype
, pai
, res
);
2063 if (sentinel
.ai_next
== NULL
)
2064 switch (res
->res_h_errno
) {
2065 case HOST_NOT_FOUND
:
2072 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2077 _sethtent(FILE **hostf
)
2080 *hostf
= fopen(_PATH_HOSTS
, "r");
2086 _endhtent(FILE **hostf
)
2094 static struct addrinfo
*
2095 _gethtent(FILE **hostf
, const char *name
, const struct addrinfo
*pai
)
2098 char *cp
, *tname
, *cname
;
2099 struct addrinfo hints
, *res0
, *res
;
2102 char hostbuf
[8*1024];
2104 if (!*hostf
&& !(*hostf
= fopen(_PATH_HOSTS
, "r")))
2107 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, *hostf
)))
2111 cp
= strpbrk(p
, "#\n");
2114 if (!(cp
= strpbrk(p
, " \t")))
2119 /* if this is not something we're looking for, skip it. */
2121 if (*cp
== ' ' || *cp
== '\t') {
2128 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2130 if (strcasecmp(name
, tname
) == 0)
2136 /* we should not glob socktype/protocol here */
2137 memset(&hints
, 0, sizeof(hints
));
2138 hints
.ai_family
= pai
->ai_family
;
2139 hints
.ai_socktype
= SOCK_DGRAM
;
2140 hints
.ai_protocol
= 0;
2141 hints
.ai_flags
= AI_NUMERICHOST
;
2142 error
= getaddrinfo(addr
, "0", &hints
, &res0
);
2145 #ifdef FILTER_V4MAPPED
2146 /* XXX should check all items in the chain */
2147 if (res0
->ai_family
== AF_INET6
&&
2148 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)res0
->ai_addr
)->sin6_addr
)) {
2153 for (res
= res0
; res
; res
= res
->ai_next
) {
2155 res
->ai_flags
= pai
->ai_flags
;
2156 res
->ai_socktype
= pai
->ai_socktype
;
2157 res
->ai_protocol
= pai
->ai_protocol
;
2159 if (pai
->ai_flags
& AI_CANONNAME
) {
2160 if (get_canonname(pai
, res
, cname
) != 0) {
2171 _files_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
2174 const struct addrinfo
*pai
;
2175 struct addrinfo sentinel
, *cur
;
2179 name
= va_arg(ap
, char *);
2180 pai
= va_arg(ap
, struct addrinfo
*);
2182 memset(&sentinel
, 0, sizeof(sentinel
));
2186 while ((p
= _gethtent(&hostf
, name
, pai
)) != NULL
) {
2188 while (cur
&& cur
->ai_next
)
2193 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2194 if (sentinel
.ai_next
== NULL
)
2201 static struct addrinfo
*
2202 _yphostent(char *line
, const struct addrinfo
*pai
)
2204 struct addrinfo sentinel
, *cur
;
2205 struct addrinfo hints
, *res
, *res0
;
2208 const char *addr
, *canonname
;
2212 addr
= canonname
= NULL
;
2214 memset(&sentinel
, 0, sizeof(sentinel
));
2218 /* terminate line */
2219 cp
= strchr(p
, '\n');
2226 cp
= strpbrk(p
, " \t");
2228 if (canonname
== NULL
)
2238 if (*cp
== ' ' || *cp
== '\t') {
2244 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2249 hints
.ai_flags
= AI_NUMERICHOST
;
2250 error
= getaddrinfo(addr
, NULL
, &hints
, &res0
);
2252 for (res
= res0
; res
; res
= res
->ai_next
) {
2254 res
->ai_flags
= pai
->ai_flags
;
2256 if (pai
->ai_flags
& AI_CANONNAME
)
2257 get_canonname(pai
, res
, canonname
);
2262 cur
->ai_next
= res0
;
2263 while (cur
&& cur
->ai_next
)
2273 return sentinel
.ai_next
;
2278 _yp_getaddrinfo(void *rv
, void *cb_data __unused
, va_list ap
)
2280 struct addrinfo sentinel
, *cur
;
2281 struct addrinfo
*ai
= NULL
;
2285 const struct addrinfo
*pai
;
2288 if (_yp_check(&ypdomain
) == 0)
2291 name
= va_arg(ap
, char *);
2292 pai
= va_arg(ap
, const struct addrinfo
*);
2294 memset(&sentinel
, 0, sizeof(sentinel
));
2297 /* hosts.byname is only for IPv4 (Solaris8) */
2298 if (pai
->ai_family
== PF_UNSPEC
|| pai
->ai_family
== PF_INET
) {
2299 r
= yp_match(ypdomain
, "hosts.byname", name
,
2300 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2302 struct addrinfo ai4
;
2305 ai4
.ai_family
= AF_INET
;
2306 ai
= _yphostent(ypbuf
, &ai4
);
2309 while (cur
&& cur
->ai_next
)
2316 /* ipnodes.byname can hold both IPv4/v6 */
2317 r
= yp_match(ypdomain
, "ipnodes.byname", name
,
2318 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2320 ai
= _yphostent(ypbuf
, pai
);
2326 if (sentinel
.ai_next
== NULL
) {
2327 RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND
);
2330 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2335 /* resolver logic */
2338 * Formulate a normal query, send, and await answer.
2339 * Returned answer is placed in supplied buffer "answer".
2340 * Perform preliminary check of answer, returning success only
2341 * if no error is indicated and the answer count is nonzero.
2342 * Return the size of the response on success, -1 on error.
2343 * Error number is left in h_errno.
2345 * Caller must parse answer and determine whether it answers the question.
2348 res_queryN(const char *name
, struct res_target
*target
, res_state res
)
2354 struct res_target
*t
;
2361 buf
= malloc(MAXPACKET
);
2363 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2367 for (t
= target
; t
; t
= t
->next
) {
2372 hp
= (HEADER
*)(void *)t
->answer
;
2374 /* make it easier... */
2380 oflags
= res
->_flags
;
2383 hp
->rcode
= NOERROR
; /* default */
2386 if (res
->options
& RES_DEBUG
)
2387 printf(";; res_query(%s, %d, %d)\n", name
, class, type
);
2390 n
= res_nmkquery(res
, QUERY
, name
, class, type
, NULL
, 0, NULL
,
2392 if (n
> 0 && (res
->_flags
& RES_F_EDNS0ERR
) == 0 &&
2393 (res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
)) != 0U)
2394 n
= res_nopt(res
, n
, buf
, MAXPACKET
, anslen
);
2397 if (res
->options
& RES_DEBUG
)
2398 printf(";; res_query: mkquery failed\n");
2401 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2404 n
= res_nsend(res
, buf
, n
, answer
, anslen
);
2407 * if the query choked with EDNS0, retry
2410 if ((res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
))
2412 ((oflags
^ res
->_flags
) & RES_F_EDNS0ERR
) != 0) {
2413 res
->_flags
|= RES_F_EDNS0ERR
;
2414 if (res
->options
& RES_DEBUG
)
2415 printf(";; res_nquery: retry without EDNS0\n");
2418 rcode
= hp
->rcode
; /* record most recent error */
2420 if (res
->options
& RES_DEBUG
)
2421 printf(";; res_query: send error\n");
2427 hp
->rcode
= FORMERR
; /* XXX not very informative */
2428 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
2429 rcode
= hp
->rcode
; /* record most recent error */
2431 if (res
->options
& RES_DEBUG
)
2432 printf(";; rcode = %u, ancount=%u\n", hp
->rcode
,
2433 ntohs(hp
->ancount
));
2438 ancount
+= ntohs(hp
->ancount
);
2448 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
);
2451 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2454 RES_SET_H_ERRNO(res
, NO_DATA
);
2460 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2469 * Formulate a normal query, send, and retrieve answer in supplied buffer.
2470 * Return the size of the response on success, -1 on error.
2471 * If enabled, implement search rules until answer or unrecoverable failure
2472 * is detected. Error code, if any, is left in h_errno.
2475 res_searchN(const char *name
, struct res_target
*target
, res_state res
)
2477 const char *cp
, * const *domain
;
2478 HEADER
*hp
= (HEADER
*)(void *)target
->answer
; /*XXX*/
2480 int trailing_dot
, ret
, saved_herrno
;
2481 int got_nodata
= 0, got_servfail
= 0, root_on_list
= 0;
2482 int tried_as_is
= 0;
2484 char abuf
[MAXDNAME
];
2487 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
); /* default, if we never query */
2489 for (cp
= name
; *cp
; cp
++)
2490 dots
+= (*cp
== '.');
2492 if (cp
> name
&& *--cp
== '.')
2496 * if there aren't any dots, it could be a user-level alias
2499 (cp
= res_hostalias(res
, name
, abuf
, sizeof(abuf
))) != NULL
)
2500 return (res_queryN(cp
, target
, res
));
2503 * If there are enough dots in the name, let's just give it a
2504 * try 'as is'. The threshold can be set with the "ndots" option.
2505 * Also, query 'as is', if there is a trailing dot in the name.
2508 if (dots
>= res
->ndots
|| trailing_dot
) {
2509 ret
= res_querydomainN(name
, NULL
, target
, res
);
2510 if (ret
> 0 || trailing_dot
)
2512 if (errno
== ECONNREFUSED
) {
2513 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2516 switch (res
->res_h_errno
) {
2518 case HOST_NOT_FOUND
:
2521 if (hp
->rcode
== SERVFAIL
)
2527 saved_herrno
= res
->res_h_errno
;
2532 * We do at least one level of search if
2533 * - there is no dot and RES_DEFNAME is set, or
2534 * - there is at least one dot, there is no trailing dot,
2535 * and RES_DNSRCH is set.
2537 if ((!dots
&& (res
->options
& RES_DEFNAMES
)) ||
2538 (dots
&& !trailing_dot
&& (res
->options
& RES_DNSRCH
))) {
2541 for (domain
= (const char * const *)res
->dnsrch
;
2546 if (domain
[0][0] == '\0' ||
2547 (domain
[0][0] == '.' && domain
[0][1] == '\0'))
2550 if (root_on_list
&& tried_as_is
)
2553 ret
= res_querydomainN(name
, *domain
, target
, res
);
2558 * If no server present, give up.
2559 * If name isn't found in this domain,
2560 * keep trying higher domains in the search list
2561 * (if that's enabled).
2562 * On a NO_DATA error, keep trying, otherwise
2563 * a wildcard entry of another type could keep us
2564 * from finding this entry higher in the domain.
2565 * If we get some other error (negative answer or
2566 * server failure), then stop searching up,
2567 * but try the input name below in case it's
2570 if (errno
== ECONNREFUSED
) {
2571 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2575 switch (res
->res_h_errno
) {
2579 case HOST_NOT_FOUND
:
2584 if (hp
->rcode
== SERVFAIL
) {
2585 /* try next search element, if any */
2590 /* anything else implies that we're done */
2594 * if we got here for some reason other than DNSRCH,
2595 * we only wanted one iteration of the loop, so stop.
2597 if (!(res
->options
& RES_DNSRCH
))
2602 switch (res
->res_h_errno
) {
2604 case HOST_NOT_FOUND
:
2607 if (hp
->rcode
== SERVFAIL
)
2615 * If the query has not already been tried as is then try it
2616 * unless RES_NOTLDQUERY is set and there were no dots.
2618 if ((dots
|| !searched
|| !(res
->options
& RES_NOTLDQUERY
)) &&
2619 !(tried_as_is
|| root_on_list
)) {
2620 ret
= res_querydomainN(name
, NULL
, target
, res
);
2626 * if we got here, we didn't satisfy the search.
2627 * if we did an initial full query, return that query's h_errno
2628 * (note that we wouldn't be here if that query had succeeded).
2629 * else if we ever got a nodata, send that back as the reason.
2630 * else send back meaningless h_errno, that being the one from
2631 * the last DNSRCH we did.
2634 if (saved_herrno
!= -1)
2635 RES_SET_H_ERRNO(res
, saved_herrno
);
2636 else if (got_nodata
)
2637 RES_SET_H_ERRNO(res
, NO_DATA
);
2638 else if (got_servfail
)
2639 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2644 * Perform a call on res_query on the concatenation of name and domain,
2645 * removing a trailing dot from name if domain is NULL.
2648 res_querydomainN(const char *name
, const char *domain
,
2649 struct res_target
*target
, res_state res
)
2651 char nbuf
[MAXDNAME
];
2652 const char *longname
= nbuf
;
2656 if (res
->options
& RES_DEBUG
)
2657 printf(";; res_querydomain(%s, %s)\n",
2658 name
, domain
?domain
:"<Nil>");
2660 if (domain
== NULL
) {
2662 * Check for trailing '.';
2663 * copy without '.' if present.
2666 if (n
>= MAXDNAME
) {
2667 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2670 if (n
> 0 && name
[--n
] == '.') {
2671 strncpy(nbuf
, name
, n
);
2678 if (n
+ d
+ 1 >= MAXDNAME
) {
2679 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2682 snprintf(nbuf
, sizeof(nbuf
), "%s.%s", name
, domain
);
2684 return (res_queryN(longname
, target
, res
));