1 /* $FreeBSD: src/lib/libc/net/getaddrinfo.c,v 1.87 2008/02/03 19:07:55 ume Exp $ */
2 /* $DragonFly: src/lib/libc/net/getaddrinfo.c,v 1.9 2008/10/04 22:38:42 swildner Exp $ */
3 /* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
37 * Issues to be discussed:
38 * - Return values. There are nonstandard return values defined and used
39 * in the source code. This is because RFC2553 is silent about which error
40 * code must be returned for which situation.
41 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
42 * invalid. current code - SEGV on freeaddrinfo(NULL)
45 * - The code filters out AFs that are not supported by the kernel,
46 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
47 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
49 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
50 * (1) what should we do against numeric hostname (2) what should we do
51 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
52 * non-loopback address configured? global address configured?
54 * OS specific notes for freebsd4:
55 * - FreeBSD supported $GAI. The code does not.
58 #include "namespace.h"
59 #include <sys/types.h>
60 #include <sys/param.h>
61 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <sys/queue.h>
66 #include <net/if_var.h>
67 #include <sys/sysctl.h>
68 #include <sys/ioctl.h>
69 #include <netinet6/in6_var.h> /* XXX */
71 #include <arpa/inet.h>
72 #include <arpa/nameser.h>
74 #include <rpcsvc/yp_prot.h>
75 #include <rpcsvc/ypclnt.h>
86 #include "res_config.h"
94 #include "un-namespace.h"
95 #include "libc_private.h"
100 #if defined(__KAME__) && defined(INET6)
109 static const char in_addrany
[] = { 0, 0, 0, 0 };
110 static const char in_loopback
[] = { 127, 0, 0, 1 };
112 static const char in6_addrany
[] = {
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
115 static const char in6_loopback
[] = {
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
121 TAILQ_ENTRY(policyqueue
) pc_entry
;
123 struct in6_addrpolicy pc_policy
;
126 TAILQ_HEAD(policyhead
, policyqueue
);
128 static const struct afd
{
133 const char *a_addrany
;
134 const char *a_loopback
;
139 {PF_INET6
, sizeof(struct in6_addr
),
140 sizeof(struct sockaddr_in6
),
141 offsetof(struct sockaddr_in6
, sin6_addr
),
142 in6_addrany
, in6_loopback
, 1},
147 {PF_INET
, sizeof(struct in_addr
),
148 sizeof(struct sockaddr_in
),
149 offsetof(struct sockaddr_in
, sin_addr
),
150 in_addrany
, in_loopback
, 0},
151 {0, 0, 0, 0, NULL
, NULL
, 0},
158 const char *e_protostr
;
160 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
161 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
162 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
165 static const struct explore explore
[] = {
167 { PF_LOCAL
, 0, ANY
, ANY
, NULL
, 0x01 },
170 { PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
171 { PF_INET6
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
172 { PF_INET6
, SOCK_RAW
, ANY
, NULL
, 0x05 },
174 { PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
175 { PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
176 { PF_INET
, SOCK_RAW
, ANY
, NULL
, 0x05 },
177 { PF_UNSPEC
, SOCK_DGRAM
, IPPROTO_UDP
, "udp", 0x07 },
178 { PF_UNSPEC
, SOCK_STREAM
, IPPROTO_TCP
, "tcp", 0x07 },
179 { PF_UNSPEC
, SOCK_RAW
, ANY
, NULL
, 0x05 },
180 { -1, 0, 0, NULL
, 0 },
189 #define AIO_SRCFLAG_DEPRECATED 0x1
193 struct sockaddr_storage aiou_ss
;
194 struct sockaddr aiou_sa
;
196 #define aio_srcsa aio_src_un.aiou_sa
197 u_int32_t aio_srcflag
;
200 struct policyqueue
*aio_srcpolicy
;
201 struct policyqueue
*aio_dstpolicy
;
202 struct addrinfo
*aio_ai
;
206 static const ns_src default_dns_files
[] = {
207 { NSSRC_FILES
, NS_SUCCESS
},
208 { NSSRC_DNS
, NS_SUCCESS
},
213 struct res_target
*next
;
214 const char *name
; /* domain name */
215 int qclass
, qtype
; /* class and type of query */
216 u_char
*answer
; /* buffer to put answer */
217 int anslen
; /* size of answer buffer */
218 int n
; /* result length */
221 #define MAXPACKET (64*1024)
225 u_char buf
[MAXPACKET
];
228 static int str2number(const char *, int *);
229 static int explore_null(const struct addrinfo
*,
230 const char *, struct addrinfo
**);
231 static int explore_numeric(const struct addrinfo
*, const char *,
232 const char *, struct addrinfo
**, const char *);
233 static int explore_numeric_scope(const struct addrinfo
*, const char *,
234 const char *, struct addrinfo
**);
235 static int get_canonname(const struct addrinfo
*,
236 struct addrinfo
*, const char *);
237 static struct addrinfo
*get_ai(const struct addrinfo
*,
238 const struct afd
*, const char *);
239 static int get_portmatch(const struct addrinfo
*, const char *);
240 static int get_port(struct addrinfo
*, const char *, int);
241 static const struct afd
*find_afd(int);
242 static int addrconfig(struct addrinfo
*);
243 static void set_source(struct ai_order
*, struct policyhead
*);
244 static int comp_dst(const void *, const void *);
246 static int ip6_str2scopeid(char *, struct sockaddr_in6
*, u_int32_t
*);
248 static int gai_addr2scopetype(struct sockaddr
*);
250 static int explore_fqdn(const struct addrinfo
*, const char *,
251 const char *, struct addrinfo
**);
253 static int reorder(struct addrinfo
*);
254 static int get_addrselectpolicy(struct policyhead
*);
255 static void free_addrselectpolicy(struct policyhead
*);
256 static struct policyqueue
*match_addrselectpolicy(struct sockaddr
*,
257 struct policyhead
*);
258 static int matchlen(struct sockaddr
*, struct sockaddr
*);
260 static struct addrinfo
*getanswer(const querybuf
*, int, const char *, int,
261 const struct addrinfo
*, res_state
);
262 #if defined(RESOLVSORT)
263 static int addr4sort(struct addrinfo
*, res_state
);
265 static int _dns_getaddrinfo(void *, void *, va_list);
266 static void _sethtent(FILE **);
267 static void _endhtent(FILE **);
268 static struct addrinfo
*_gethtent(FILE **, const char *,
269 const struct addrinfo
*);
270 static int _files_getaddrinfo(void *, void *, va_list);
272 static struct addrinfo
*_yphostent(char *, const struct addrinfo
*);
273 static int _yp_getaddrinfo(void *, void *, va_list);
276 static int addrinfo_id_func(char *, size_t *, va_list, void *);
277 static int addrinfo_marshal_func(char *, size_t *, void *, va_list,
279 static int addrinfo_unmarshal_func(char *, size_t, void *, va_list,
283 static int res_queryN(const char *, struct res_target
*, res_state
);
284 static int res_searchN(const char *, struct res_target
*, res_state
);
285 static int res_querydomainN(const char *, const char *,
286 struct res_target
*, res_state
);
288 /* XXX macros that make external reference is BAD. */
290 #define GET_AI(ai, afd, addr) \
292 /* external reference: pai, error, and label free */ \
293 (ai) = get_ai(pai, (afd), (addr)); \
294 if ((ai) == NULL) { \
295 error = EAI_MEMORY; \
298 } while (/*CONSTCOND*/0)
300 #define GET_PORT(ai, serv) \
302 /* external reference: error and label free */ \
303 error = get_port((ai), (serv), 0); \
306 } while (/*CONSTCOND*/0)
308 #define GET_CANONNAME(ai, str) \
310 /* external reference: pai, error and label free */ \
311 error = get_canonname(pai, (ai), (str)); \
314 } while (/*CONSTCOND*/0)
318 /* external reference: error, and label bad */ \
322 } while (/*CONSTCOND*/0)
324 #define MATCH_FAMILY(x, y, w) \
325 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
326 #define MATCH(x, y, w) \
327 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
330 freeaddrinfo(struct addrinfo
*ai
)
332 struct addrinfo
*next
;
336 if (ai
->ai_canonname
)
337 free(ai
->ai_canonname
);
338 /* no need to free(ai->ai_addr) */
345 str2number(const char *p
, int *portp
)
354 v
= strtoul(p
, &ep
, 10);
355 if (errno
== 0 && ep
&& *ep
== '\0' && v
<= UINT_MAX
) {
363 getaddrinfo(const char *hostname
, const char *servname
,
364 const struct addrinfo
*hints
, struct addrinfo
**res
)
366 struct addrinfo sentinel
;
367 struct addrinfo
*cur
;
371 struct addrinfo
*pai
;
372 const struct explore
*ex
;
375 memset(&sentinel
, 0, sizeof(sentinel
));
379 pai
->ai_family
= PF_UNSPEC
;
380 pai
->ai_socktype
= ANY
;
381 pai
->ai_protocol
= ANY
;
383 pai
->ai_canonname
= NULL
;
387 if (hostname
== NULL
&& servname
== NULL
)
390 /* error check for hints */
391 if (hints
->ai_addrlen
|| hints
->ai_canonname
||
392 hints
->ai_addr
|| hints
->ai_next
)
393 ERR(EAI_BADHINTS
); /* xxx */
394 if (hints
->ai_flags
& ~AI_MASK
)
396 switch (hints
->ai_family
) {
406 memcpy(pai
, hints
, sizeof(*pai
));
409 * if both socktype/protocol are specified, check if they
410 * are meaningful combination.
412 if (pai
->ai_socktype
!= ANY
&& pai
->ai_protocol
!= ANY
) {
413 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
414 if (pai
->ai_family
!= ex
->e_af
)
416 if (ex
->e_socktype
== ANY
)
418 if (ex
->e_protocol
== ANY
)
420 if (pai
->ai_socktype
== ex
->e_socktype
&&
421 pai
->ai_protocol
!= ex
->e_protocol
) {
429 * check for special cases. (1) numeric servname is disallowed if
430 * socktype/protocol are left unspecified. (2) servname is disallowed
431 * for raw and other inet{,6} sockets.
433 if (MATCH_FAMILY(pai
->ai_family
, PF_INET
, 1)
435 || MATCH_FAMILY(pai
->ai_family
, PF_INET6
, 1)
438 ai0
= *pai
; /* backup *pai */
440 if (pai
->ai_family
== PF_UNSPEC
) {
442 pai
->ai_family
= PF_INET6
;
444 pai
->ai_family
= PF_INET
;
447 error
= get_portmatch(pai
, servname
);
456 /* NULL hostname, or numeric hostname */
457 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
460 /* PF_UNSPEC entries are prepared for DNS queries only */
461 if (ex
->e_af
== PF_UNSPEC
)
464 if (!MATCH_FAMILY(pai
->ai_family
, ex
->e_af
, WILD_AF(ex
)))
466 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
, WILD_SOCKTYPE(ex
)))
468 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
, WILD_PROTOCOL(ex
)))
471 if (pai
->ai_family
== PF_UNSPEC
)
472 pai
->ai_family
= ex
->e_af
;
473 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
474 pai
->ai_socktype
= ex
->e_socktype
;
475 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
476 pai
->ai_protocol
= ex
->e_protocol
;
478 if (hostname
== NULL
)
479 error
= explore_null(pai
, servname
, &cur
->ai_next
);
481 error
= explore_numeric_scope(pai
, hostname
, servname
,
487 while (cur
&& cur
->ai_next
)
493 * If numreic representation of AF1 can be interpreted as FQDN
494 * representation of AF2, we need to think again about the code below.
496 if (sentinel
.ai_next
) {
501 if (hostname
== NULL
)
502 ERR(EAI_NONAME
); /* used to be EAI_NODATA */
503 if (pai
->ai_flags
& AI_NUMERICHOST
)
506 if ((pai
->ai_flags
& AI_ADDRCONFIG
) != 0 && !addrconfig(&ai0
))
510 * hostname as alphabetical name.
511 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
514 for (ex
= explore
; ex
->e_af
>= 0; ex
++) {
517 /* require exact match for family field */
518 if (pai
->ai_family
!= ex
->e_af
)
521 if (!MATCH(pai
->ai_socktype
, ex
->e_socktype
,
522 WILD_SOCKTYPE(ex
))) {
525 if (!MATCH(pai
->ai_protocol
, ex
->e_protocol
,
526 WILD_PROTOCOL(ex
))) {
530 if (pai
->ai_socktype
== ANY
&& ex
->e_socktype
!= ANY
)
531 pai
->ai_socktype
= ex
->e_socktype
;
532 if (pai
->ai_protocol
== ANY
&& ex
->e_protocol
!= ANY
)
533 pai
->ai_protocol
= ex
->e_protocol
;
535 error
= explore_fqdn(pai
, hostname
, servname
, &cur
->ai_next
);
537 while (cur
&& cur
->ai_next
)
541 /* XXX inhibit errors if we have the result */
542 if (sentinel
.ai_next
)
547 * ensure we return either:
548 * - error == 0, non-NULL *res
549 * - error != 0, NULL *res
552 if (sentinel
.ai_next
) {
554 * If the returned entry is for an active connection,
555 * and the given name is not numeric, reorder the
556 * list, so that the application would try the list
557 * in the most efficient order. Since the head entry
558 * of the original list may contain ai_canonname and
559 * that entry may be moved elsewhere in the new list,
560 * we keep the pointer and will restore it in the new
561 * head entry. (Note that RFC3493 requires the head
562 * entry store it when requested by the caller).
564 if (hints
== NULL
|| !(hints
->ai_flags
& AI_PASSIVE
)) {
569 sentinel
.ai_next
->ai_canonname
;
570 sentinel
.ai_next
->ai_canonname
= NULL
;
572 if (sentinel
.ai_next
->ai_canonname
==
574 sentinel
.ai_next
->ai_canonname
576 } else if (canonname
!= NULL
)
580 *res
= sentinel
.ai_next
;
587 if (sentinel
.ai_next
)
588 freeaddrinfo(sentinel
.ai_next
);
594 reorder(struct addrinfo
*sentinel
)
596 struct addrinfo
*ai
, **aip
;
597 struct ai_order
*aio
;
599 struct policyhead policyhead
;
601 /* count the number of addrinfo elements for sorting. */
602 for (n
= 0, ai
= sentinel
->ai_next
; ai
!= NULL
; ai
= ai
->ai_next
, n
++)
606 * If the number is small enough, we can skip the reordering process.
611 /* allocate a temporary array for sort and initialization of it. */
612 if ((aio
= malloc(sizeof(*aio
) * n
)) == NULL
)
613 return(n
); /* give up reordering */
614 memset(aio
, 0, sizeof(*aio
) * n
);
616 /* retrieve address selection policy from the kernel */
617 TAILQ_INIT(&policyhead
);
618 if (!get_addrselectpolicy(&policyhead
)) {
619 /* no policy is installed into kernel, we don't sort. */
624 for (i
= 0, ai
= sentinel
->ai_next
; i
< n
; ai
= ai
->ai_next
, i
++) {
626 aio
[i
].aio_dstscope
= gai_addr2scopetype(ai
->ai_addr
);
627 aio
[i
].aio_dstpolicy
= match_addrselectpolicy(ai
->ai_addr
,
629 set_source(&aio
[i
], &policyhead
);
632 /* perform sorting. */
633 qsort(aio
, n
, sizeof(*aio
), comp_dst
);
635 /* reorder the addrinfo chain. */
636 for (i
= 0, aip
= &sentinel
->ai_next
; i
< n
; i
++) {
637 *aip
= aio
[i
].aio_ai
;
638 aip
= &aio
[i
].aio_ai
->ai_next
;
642 /* cleanup and return */
644 free_addrselectpolicy(&policyhead
);
649 get_addrselectpolicy(struct policyhead
*head
)
652 int mib
[] = { CTL_NET
, PF_INET6
, IPPROTO_IPV6
, IPV6CTL_ADDRCTLPOLICY
};
655 struct in6_addrpolicy
*pol
, *ep
;
657 if (sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), NULL
, &l
, NULL
, 0) < 0)
659 if ((buf
= malloc(l
)) == NULL
)
661 if (sysctl(mib
, sizeof(mib
) / sizeof(mib
[0]), buf
, &l
, NULL
, 0) < 0) {
666 ep
= (struct in6_addrpolicy
*)(buf
+ l
);
667 for (pol
= (struct in6_addrpolicy
*)buf
; pol
+ 1 <= ep
; pol
++) {
668 struct policyqueue
*new;
670 if ((new = malloc(sizeof(*new))) == NULL
) {
671 free_addrselectpolicy(head
); /* make the list empty */
674 new->pc_policy
= *pol
;
675 TAILQ_INSERT_TAIL(head
, new, pc_entry
);
686 free_addrselectpolicy(struct policyhead
*head
)
688 struct policyqueue
*ent
, *nent
;
690 for (ent
= TAILQ_FIRST(head
); ent
; ent
= nent
) {
691 nent
= TAILQ_NEXT(ent
, pc_entry
);
692 TAILQ_REMOVE(head
, ent
, pc_entry
);
697 static struct policyqueue
*
698 match_addrselectpolicy(struct sockaddr
*addr
, struct policyhead
*head
)
701 struct policyqueue
*ent
, *bestent
= NULL
;
702 struct in6_addrpolicy
*pol
;
703 int matchlen
, bestmatchlen
= -1;
704 u_char
*mp
, *ep
, *k
, *p
, m
;
705 struct sockaddr_in6 key
;
707 switch(addr
->sa_family
) {
709 key
= *(struct sockaddr_in6
*)addr
;
712 /* convert the address into IPv4-mapped IPv6 address. */
713 memset(&key
, 0, sizeof(key
));
714 key
.sin6_family
= AF_INET6
;
715 key
.sin6_len
= sizeof(key
);
716 key
.sin6_addr
.s6_addr
[10] = 0xff;
717 key
.sin6_addr
.s6_addr
[11] = 0xff;
718 memcpy(&key
.sin6_addr
.s6_addr
[12],
719 &((struct sockaddr_in
*)addr
)->sin_addr
, 4);
725 for (ent
= TAILQ_FIRST(head
); ent
; ent
= TAILQ_NEXT(ent
, pc_entry
)) {
726 pol
= &ent
->pc_policy
;
729 mp
= (u_char
*)&pol
->addrmask
.sin6_addr
;
730 ep
= mp
+ 16; /* XXX: scope field? */
731 k
= (u_char
*)&key
.sin6_addr
;
732 p
= (u_char
*)&pol
->addr
.sin6_addr
;
733 for (; mp
< ep
&& *mp
; mp
++, k
++, p
++) {
736 goto next
; /* not match */
737 if (m
== 0xff) /* short cut for a typical case */
747 /* matched. check if this is better than the current best. */
748 if (matchlen
> bestmatchlen
) {
750 bestmatchlen
= matchlen
;
765 set_source(struct ai_order
*aio
, struct policyhead
*ph
)
767 struct addrinfo ai
= *aio
->aio_ai
;
768 struct sockaddr_storage ss
;
772 /* set unspec ("no source is available"), just in case */
773 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
774 aio
->aio_srcscope
= -1;
776 switch(ai
.ai_family
) {
782 default: /* ignore unsupported AFs explicitly */
786 /* XXX: make a dummy addrinfo to call connect() */
787 ai
.ai_socktype
= SOCK_DGRAM
;
788 ai
.ai_protocol
= IPPROTO_UDP
; /* is UDP too specific? */
790 memset(&ss
, 0, sizeof(ss
));
791 memcpy(&ss
, ai
.ai_addr
, ai
.ai_addrlen
);
792 ai
.ai_addr
= (struct sockaddr
*)&ss
;
793 get_port(&ai
, "1", 0);
795 /* open a socket to get the source address for the given dst */
796 if ((s
= _socket(ai
.ai_family
, ai
.ai_socktype
, ai
.ai_protocol
)) < 0)
797 return; /* give up */
798 if (_connect(s
, ai
.ai_addr
, ai
.ai_addrlen
) < 0)
800 srclen
= ai
.ai_addrlen
;
801 if (_getsockname(s
, &aio
->aio_srcsa
, &srclen
) < 0) {
802 aio
->aio_srcsa
.sa_family
= AF_UNSPEC
;
805 aio
->aio_srcscope
= gai_addr2scopetype(&aio
->aio_srcsa
);
806 aio
->aio_srcpolicy
= match_addrselectpolicy(&aio
->aio_srcsa
, ph
);
807 aio
->aio_matchlen
= matchlen(&aio
->aio_srcsa
, aio
->aio_ai
->ai_addr
);
809 if (ai
.ai_family
== AF_INET6
) {
810 struct in6_ifreq ifr6
;
813 /* XXX: interface name should not be hardcoded */
814 strncpy(ifr6
.ifr_name
, "lo0", sizeof(ifr6
.ifr_name
));
815 memset(&ifr6
, 0, sizeof(ifr6
));
816 memcpy(&ifr6
.ifr_addr
, ai
.ai_addr
, ai
.ai_addrlen
);
817 if (_ioctl(s
, SIOCGIFAFLAG_IN6
, &ifr6
) == 0) {
818 flags6
= ifr6
.ifr_ifru
.ifru_flags6
;
819 if ((flags6
& IN6_IFF_DEPRECATED
))
820 aio
->aio_srcflag
|= AIO_SRCFLAG_DEPRECATED
;
831 matchlen(struct sockaddr
*src
, struct sockaddr
*dst
)
838 switch (src
->sa_family
) {
841 s
= (u_char
*)&((struct sockaddr_in6
*)src
)->sin6_addr
;
842 d
= (u_char
*)&((struct sockaddr_in6
*)dst
)->sin6_addr
;
843 addrlen
= sizeof(struct in6_addr
);
848 s
= (u_char
*)&((struct sockaddr_in
*)src
)->sin_addr
;
849 d
= (u_char
*)&((struct sockaddr_in
*)dst
)->sin_addr
;
850 addrlen
= sizeof(struct in_addr
);
858 if ((r
= (*d
++ ^ *s
++)) != 0) {
859 while (r
< addrlen
* 8) {
870 comp_dst(const void *arg1
, const void *arg2
)
872 const struct ai_order
*dst1
= arg1
, *dst2
= arg2
;
875 * Rule 1: Avoid unusable destinations.
876 * XXX: we currently do not consider if an appropriate route exists.
878 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
879 dst2
->aio_srcsa
.sa_family
== AF_UNSPEC
) {
882 if (dst1
->aio_srcsa
.sa_family
== AF_UNSPEC
&&
883 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
887 /* Rule 2: Prefer matching scope. */
888 if (dst1
->aio_dstscope
== dst1
->aio_srcscope
&&
889 dst2
->aio_dstscope
!= dst2
->aio_srcscope
) {
892 if (dst1
->aio_dstscope
!= dst1
->aio_srcscope
&&
893 dst2
->aio_dstscope
== dst2
->aio_srcscope
) {
897 /* Rule 3: Avoid deprecated addresses. */
898 if (dst1
->aio_srcsa
.sa_family
!= AF_UNSPEC
&&
899 dst2
->aio_srcsa
.sa_family
!= AF_UNSPEC
) {
900 if (!(dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
901 (dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
904 if ((dst1
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
) &&
905 !(dst2
->aio_srcflag
& AIO_SRCFLAG_DEPRECATED
)) {
910 /* Rule 4: Prefer home addresses. */
911 /* XXX: not implemented yet */
913 /* Rule 5: Prefer matching label. */
915 if (dst1
->aio_srcpolicy
&& dst1
->aio_dstpolicy
&&
916 dst1
->aio_srcpolicy
->pc_policy
.label
==
917 dst1
->aio_dstpolicy
->pc_policy
.label
&&
918 (dst2
->aio_srcpolicy
== NULL
|| dst2
->aio_dstpolicy
== NULL
||
919 dst2
->aio_srcpolicy
->pc_policy
.label
!=
920 dst2
->aio_dstpolicy
->pc_policy
.label
)) {
923 if (dst2
->aio_srcpolicy
&& dst2
->aio_dstpolicy
&&
924 dst2
->aio_srcpolicy
->pc_policy
.label
==
925 dst2
->aio_dstpolicy
->pc_policy
.label
&&
926 (dst1
->aio_srcpolicy
== NULL
|| dst1
->aio_dstpolicy
== NULL
||
927 dst1
->aio_srcpolicy
->pc_policy
.label
!=
928 dst1
->aio_dstpolicy
->pc_policy
.label
)) {
933 /* Rule 6: Prefer higher precedence. */
935 if (dst1
->aio_dstpolicy
&&
936 (dst2
->aio_dstpolicy
== NULL
||
937 dst1
->aio_dstpolicy
->pc_policy
.preced
>
938 dst2
->aio_dstpolicy
->pc_policy
.preced
)) {
941 if (dst2
->aio_dstpolicy
&&
942 (dst1
->aio_dstpolicy
== NULL
||
943 dst2
->aio_dstpolicy
->pc_policy
.preced
>
944 dst1
->aio_dstpolicy
->pc_policy
.preced
)) {
949 /* Rule 7: Prefer native transport. */
950 /* XXX: not implemented yet */
952 /* Rule 8: Prefer smaller scope. */
953 if (dst1
->aio_dstscope
>= 0 &&
954 dst1
->aio_dstscope
< dst2
->aio_dstscope
) {
957 if (dst2
->aio_dstscope
>= 0 &&
958 dst2
->aio_dstscope
< dst1
->aio_dstscope
) {
963 * Rule 9: Use longest matching prefix.
964 * We compare the match length in a same AF only.
966 if (dst1
->aio_ai
->ai_addr
->sa_family
==
967 dst2
->aio_ai
->ai_addr
->sa_family
) {
968 if (dst1
->aio_matchlen
> dst2
->aio_matchlen
) {
971 if (dst1
->aio_matchlen
< dst2
->aio_matchlen
) {
976 /* Rule 10: Otherwise, leave the order unchanged. */
982 * XXX: we should standardize the functions and link them as standard
986 gai_addr2scopetype(struct sockaddr
*sa
)
989 struct sockaddr_in6
*sa6
;
991 struct sockaddr_in
*sa4
;
993 switch(sa
->sa_family
) {
996 sa6
= (struct sockaddr_in6
*)sa
;
997 if (IN6_IS_ADDR_MULTICAST(&sa6
->sin6_addr
)) {
998 /* just use the scope field of the multicast address */
999 return(sa6
->sin6_addr
.s6_addr
[2] & 0x0f);
1002 * Unicast addresses: map scope type to corresponding scope
1003 * value defined for multcast addresses.
1004 * XXX: hardcoded scope type values are bad...
1006 if (IN6_IS_ADDR_LOOPBACK(&sa6
->sin6_addr
))
1007 return(1); /* node local scope */
1008 if (IN6_IS_ADDR_LINKLOCAL(&sa6
->sin6_addr
))
1009 return(2); /* link-local scope */
1010 if (IN6_IS_ADDR_SITELOCAL(&sa6
->sin6_addr
))
1011 return(5); /* site-local scope */
1012 return(14); /* global scope */
1017 * IPv4 pseudo scoping according to RFC 3484.
1019 sa4
= (struct sockaddr_in
*)sa
;
1020 /* IPv4 autoconfiguration addresses have link-local scope. */
1021 if (((u_char
*)&sa4
->sin_addr
)[0] == 169 &&
1022 ((u_char
*)&sa4
->sin_addr
)[1] == 254)
1024 /* Private addresses have site-local scope. */
1025 if (((u_char
*)&sa4
->sin_addr
)[0] == 10 ||
1026 (((u_char
*)&sa4
->sin_addr
)[0] == 172 &&
1027 (((u_char
*)&sa4
->sin_addr
)[1] & 0xf0) == 16) ||
1028 (((u_char
*)&sa4
->sin_addr
)[0] == 192 &&
1029 ((u_char
*)&sa4
->sin_addr
)[1] == 168))
1030 return(14); /* XXX: It should be 5 unless NAT */
1031 /* Loopback addresses have link-local scope. */
1032 if (((u_char
*)&sa4
->sin_addr
)[0] == 127)
1037 errno
= EAFNOSUPPORT
; /* is this a good error? */
1044 * passive socket -> anyaddr (0.0.0.0 or ::)
1045 * non-passive socket -> localhost (127.0.0.1 or ::1)
1048 explore_null(const struct addrinfo
*pai
, const char *servname
,
1049 struct addrinfo
**res
)
1052 const struct afd
*afd
;
1053 struct addrinfo
*ai
;
1060 * filter out AFs that are not supported by the kernel
1063 s
= _socket(pai
->ai_family
, SOCK_DGRAM
, 0);
1065 if (errno
!= EMFILE
)
1071 * if the servname does not match socktype/protocol, ignore it.
1073 if (get_portmatch(pai
, servname
) != 0)
1076 afd
= find_afd(pai
->ai_family
);
1080 if (pai
->ai_flags
& AI_PASSIVE
) {
1081 GET_AI(ai
, afd
, afd
->a_addrany
);
1082 GET_PORT(ai
, servname
);
1084 GET_AI(ai
, afd
, afd
->a_loopback
);
1085 GET_PORT(ai
, servname
);
1101 explore_numeric(const struct addrinfo
*pai
, const char *hostname
,
1102 const char *servname
, struct addrinfo
**res
,
1103 const char *canonname
)
1105 const struct afd
*afd
;
1106 struct addrinfo
*ai
;
1108 char pton
[PTON_MAX
];
1114 * if the servname does not match socktype/protocol, ignore it.
1116 if (get_portmatch(pai
, servname
) != 0)
1119 afd
= find_afd(pai
->ai_family
);
1123 switch (afd
->a_af
) {
1126 * RFC3493 requires getaddrinfo() to accept AF_INET formats
1127 * that are accepted by inet_addr() and its family. The
1128 * accepted forms includes the "classful" one, which inet_pton
1129 * does not accept. So we need to separate the case for
1132 if (inet_aton(hostname
, (struct in_addr
*)pton
) != 1)
1136 if (inet_pton(afd
->a_af
, hostname
, pton
) != 1)
1141 if (pai
->ai_family
== afd
->a_af
) {
1142 GET_AI(ai
, afd
, pton
);
1143 GET_PORT(ai
, servname
);
1144 if ((pai
->ai_flags
& AI_CANONNAME
)) {
1146 * Set the numeric address itself as the canonical
1147 * name, based on a clarification in RFC3493.
1149 GET_CANONNAME(ai
, canonname
);
1153 * XXX: This should not happen since we already matched the AF
1170 * numeric hostname with scope
1173 explore_numeric_scope(const struct addrinfo
*pai
, const char *hostname
,
1174 const char *servname
, struct addrinfo
**res
)
1176 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
1177 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1179 const struct afd
*afd
;
1180 struct addrinfo
*cur
;
1182 char *cp
, *hostname2
= NULL
, *scope
, *addr
;
1183 struct sockaddr_in6
*sin6
;
1186 * if the servname does not match socktype/protocol, ignore it.
1188 if (get_portmatch(pai
, servname
) != 0)
1191 afd
= find_afd(pai
->ai_family
);
1196 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1198 cp
= strchr(hostname
, SCOPE_DELIMITER
);
1200 return explore_numeric(pai
, hostname
, servname
, res
, hostname
);
1203 * Handle special case of <scoped_address><delimiter><scope id>
1205 hostname2
= strdup(hostname
);
1206 if (hostname2
== NULL
)
1208 /* terminate at the delimiter */
1209 hostname2
[cp
- hostname
] = '\0';
1213 error
= explore_numeric(pai
, addr
, servname
, res
, hostname
);
1217 for (cur
= *res
; cur
; cur
= cur
->ai_next
) {
1218 if (cur
->ai_family
!= AF_INET6
)
1220 sin6
= (struct sockaddr_in6
*)(void *)cur
->ai_addr
;
1221 if (ip6_str2scopeid(scope
, sin6
, &scopeid
) == -1) {
1223 return(EAI_NONAME
); /* XXX: is return OK? */
1225 sin6
->sin6_scope_id
= scopeid
;
1236 get_canonname(const struct addrinfo
*pai
, struct addrinfo
*ai
, const char *str
)
1238 if ((pai
->ai_flags
& AI_CANONNAME
) != 0) {
1239 ai
->ai_canonname
= strdup(str
);
1240 if (ai
->ai_canonname
== NULL
)
1246 static struct addrinfo
*
1247 get_ai(const struct addrinfo
*pai
, const struct afd
*afd
, const char *addr
)
1250 struct addrinfo
*ai
;
1252 struct in6_addr faith_prefix
;
1259 * Transfrom an IPv4 addr into a special IPv6 addr format for
1260 * IPv6->IPv4 translation gateway. (only TCP is supported now)
1262 * +-----------------------------------+------------+
1263 * | faith prefix part (12 bytes) | embedded |
1264 * | | IPv4 addr part (4 bytes)
1265 * +-----------------------------------+------------+
1267 * faith prefix part is specified as ascii IPv6 addr format
1268 * in environmental variable GAI.
1269 * For FAITH to work correctly, routing to faith prefix must be
1270 * setup toward a machine where a FAITH daemon operates.
1271 * Also, the machine must enable some mechanizm
1272 * (e.g. faith interface hack) to divert those packet with
1273 * faith prefixed destination addr to user-land FAITH daemon.
1275 fp_str
= getenv("GAI");
1276 if (fp_str
&& inet_pton(AF_INET6
, fp_str
, &faith_prefix
) == 1 &&
1277 afd
->a_af
== AF_INET
&& pai
->ai_socktype
== SOCK_STREAM
) {
1281 memcpy(&v4a
, addr
, sizeof v4a
);
1282 v4a_top
= v4a
>> IN_CLASSA_NSHIFT
;
1283 if (!IN_MULTICAST(v4a
) && !IN_EXPERIMENTAL(v4a
) &&
1284 v4a_top
!= 0 && v4a
!= IN_LOOPBACKNET
) {
1285 afd
= &afdl
[N_INET6
];
1286 memcpy(&faith_prefix
.s6_addr
[12], addr
,
1287 sizeof(struct in_addr
));
1293 ai
= (struct addrinfo
*)malloc(sizeof(struct addrinfo
)
1294 + (afd
->a_socklen
));
1298 memcpy(ai
, pai
, sizeof(struct addrinfo
));
1299 ai
->ai_addr
= (struct sockaddr
*)(void *)(ai
+ 1);
1300 memset(ai
->ai_addr
, 0, (size_t)afd
->a_socklen
);
1301 ai
->ai_addr
->sa_len
= afd
->a_socklen
;
1302 ai
->ai_addrlen
= afd
->a_socklen
;
1303 ai
->ai_addr
->sa_family
= ai
->ai_family
= afd
->a_af
;
1304 p
= (char *)(void *)(ai
->ai_addr
);
1307 memcpy(p
+ afd
->a_off
, &faith_prefix
, (size_t)afd
->a_addrlen
);
1310 memcpy(p
+ afd
->a_off
, addr
, (size_t)afd
->a_addrlen
);
1315 get_portmatch(const struct addrinfo
*ai
, const char *servname
)
1318 /* get_port does not touch first argument when matchonly == 1. */
1319 /* LINTED const cast */
1320 return get_port((struct addrinfo
*)ai
, servname
, 1);
1324 get_port(struct addrinfo
*ai
, const char *servname
, int matchonly
)
1331 if (servname
== NULL
)
1333 switch (ai
->ai_family
) {
1343 switch (ai
->ai_socktype
) {
1354 return EAI_SOCKTYPE
;
1357 error
= str2number(servname
, &port
);
1361 if (port
< 0 || port
> 65535)
1365 if (ai
->ai_flags
& AI_NUMERICSERV
)
1367 switch (ai
->ai_socktype
) {
1379 if ((sp
= getservbyname(servname
, proto
)) == NULL
)
1385 switch (ai
->ai_family
) {
1387 ((struct sockaddr_in
*)(void *)
1388 ai
->ai_addr
)->sin_port
= port
;
1392 ((struct sockaddr_in6
*)(void *)
1393 ai
->ai_addr
)->sin6_port
= port
;
1402 static const struct afd
*
1405 const struct afd
*afd
;
1407 if (af
== PF_UNSPEC
)
1409 for (afd
= afdl
; afd
->a_af
; afd
++) {
1410 if (afd
->a_af
== af
)
1417 * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
1418 * will take care of it.
1419 * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
1420 * if the code is right or not.
1422 * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
1426 addrconfig(struct addrinfo
*pai
)
1432 * Note that implementation dependent test for address
1433 * configuration should be done everytime called
1434 * (or apropriate interval),
1435 * because addresses will be dynamically assigned or deleted.
1437 af
= pai
->ai_family
;
1438 if (af
== AF_UNSPEC
) {
1439 if ((s
= _socket(AF_INET6
, SOCK_DGRAM
, 0)) < 0)
1443 if ((s
= _socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
1449 if (af
!= AF_UNSPEC
) {
1450 if ((s
= _socket(af
, SOCK_DGRAM
, 0)) < 0)
1454 pai
->ai_family
= af
;
1459 /* convert a string to a scope identifier. XXX: IPv6 specific */
1461 ip6_str2scopeid(char *scope
, struct sockaddr_in6
*sin6
, u_int32_t
*scopeid
)
1464 struct in6_addr
*a6
;
1467 a6
= &sin6
->sin6_addr
;
1469 /* empty scopeid portion is invalid */
1473 if (IN6_IS_ADDR_LINKLOCAL(a6
) || IN6_IS_ADDR_MC_LINKLOCAL(a6
)) {
1475 * We currently assume a one-to-one mapping between links
1476 * and interfaces, so we simply use interface indices for
1477 * like-local scopes.
1479 *scopeid
= if_nametoindex(scope
);
1485 /* still unclear about literal, allow numeric only - placeholder */
1486 if (IN6_IS_ADDR_SITELOCAL(a6
) || IN6_IS_ADDR_MC_SITELOCAL(a6
))
1488 if (IN6_IS_ADDR_MC_ORGLOCAL(a6
))
1491 goto trynumeric
; /* global */
1493 /* try to convert to a numeric id as a last resort */
1496 lscopeid
= strtoul(scope
, &ep
, 10);
1497 *scopeid
= (u_int32_t
)(lscopeid
& 0xffffffffUL
);
1498 if (errno
== 0 && ep
&& *ep
== '\0' && *scopeid
== lscopeid
)
1508 addrinfo_id_func(char *buffer
, size_t *buffer_size
, va_list ap
,
1514 const int op_id
= 0; /* identifies the getaddrinfo for the cache */
1516 struct addrinfo
*hints
;
1519 int ai_flags
, ai_family
, ai_socktype
, ai_protocol
;
1520 size_t desired_size
, size
;
1522 statp
= __res_state();
1523 res_options
= statp
->options
& (RES_RECURSE
| RES_DEFNAMES
|
1524 RES_DNSRCH
| RES_NOALIASES
| RES_USE_INET6
);
1526 hostname
= va_arg(ap
, char *);
1527 hints
= va_arg(ap
, struct addrinfo
*);
1529 desired_size
= sizeof(res_options
) + sizeof(int) + sizeof(int) * 4;
1530 if (hostname
!= NULL
) {
1531 size
= strlen(hostname
);
1532 desired_size
+= size
+ 1;
1536 if (desired_size
> *buffer_size
) {
1537 *buffer_size
= desired_size
;
1542 ai_flags
= ai_family
= ai_socktype
= ai_protocol
= 0;
1544 ai_flags
= hints
->ai_flags
;
1545 ai_family
= hints
->ai_family
;
1546 ai_socktype
= hints
->ai_socktype
;
1547 ai_protocol
= hints
->ai_protocol
;
1551 memcpy(p
, &res_options
, sizeof(res_options
));
1552 p
+= sizeof(res_options
);
1554 memcpy(p
, &op_id
, sizeof(int));
1557 memcpy(p
, &ai_flags
, sizeof(int));
1560 memcpy(p
, &ai_family
, sizeof(int));
1563 memcpy(p
, &ai_socktype
, sizeof(int));
1566 memcpy(p
, &ai_protocol
, sizeof(int));
1569 if (hostname
!= NULL
)
1570 memcpy(p
, hostname
, size
);
1572 *buffer_size
= desired_size
;
1573 return (NS_SUCCESS
);
1577 addrinfo_marshal_func(char *buffer
, size_t *buffer_size
, void *retval
,
1578 va_list ap
, void *cache_mdata
)
1580 struct addrinfo
*ai
, *cai
;
1582 size_t desired_size
, size
, ai_size
;
1584 ai
= *((struct addrinfo
**)retval
);
1586 desired_size
= sizeof(size_t);
1588 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1589 desired_size
+= sizeof(struct addrinfo
) + cai
->ai_addrlen
;
1590 if (cai
->ai_canonname
!= NULL
)
1591 desired_size
+= sizeof(size_t) +
1592 strlen(cai
->ai_canonname
);
1596 if (desired_size
> *buffer_size
) {
1597 /* this assignment is here for future use */
1599 *buffer_size
= desired_size
;
1603 memset(buffer
, 0, desired_size
);
1606 memcpy(p
, &ai_size
, sizeof(size_t));
1607 p
+= sizeof(size_t);
1608 for (cai
= ai
; cai
!= NULL
; cai
= cai
->ai_next
) {
1609 memcpy(p
, cai
, sizeof(struct addrinfo
));
1610 p
+= sizeof(struct addrinfo
);
1612 memcpy(p
, cai
->ai_addr
, cai
->ai_addrlen
);
1613 p
+= cai
->ai_addrlen
;
1615 if (cai
->ai_canonname
!= NULL
) {
1616 size
= strlen(cai
->ai_canonname
);
1617 memcpy(p
, &size
, sizeof(size_t));
1618 p
+= sizeof(size_t);
1620 memcpy(p
, cai
->ai_canonname
, size
);
1625 return (NS_SUCCESS
);
1629 addrinfo_unmarshal_func(char *buffer
, size_t buffer_size
, void *retval
,
1630 va_list ap
, void *cache_mdata
)
1632 struct addrinfo new_ai
, *result
, *sentinel
, *lasts
;
1635 size_t ai_size
, ai_i
, size
;
1638 memcpy(&ai_size
, p
, sizeof(size_t));
1639 p
+= sizeof(size_t);
1643 for (ai_i
= 0; ai_i
< ai_size
; ++ai_i
) {
1644 memcpy(&new_ai
, p
, sizeof(struct addrinfo
));
1645 p
+= sizeof(struct addrinfo
);
1646 size
= new_ai
.ai_addrlen
+ sizeof(struct addrinfo
) +
1649 sentinel
= (struct addrinfo
*)malloc(size
);
1650 memset(sentinel
, 0, size
);
1652 memcpy(sentinel
, &new_ai
, sizeof(struct addrinfo
));
1653 sentinel
->ai_addr
= (struct sockaddr
*)_ALIGN((char *)sentinel
+
1654 sizeof(struct addrinfo
));
1656 memcpy(sentinel
->ai_addr
, p
, new_ai
.ai_addrlen
);
1657 p
+= new_ai
.ai_addrlen
;
1659 if (new_ai
.ai_canonname
!= NULL
) {
1660 memcpy(&size
, p
, sizeof(size_t));
1661 p
+= sizeof(size_t);
1663 sentinel
->ai_canonname
= (char *)malloc(size
+ 1);
1664 memset(sentinel
->ai_canonname
, 0, size
+ 1);
1666 memcpy(sentinel
->ai_canonname
, p
, size
);
1670 if (result
== NULL
) {
1674 lasts
->ai_next
= sentinel
;
1679 *((struct addrinfo
**)retval
) = result
;
1680 return (NS_SUCCESS
);
1682 #endif /* NS_CACHING */
1685 * FQDN hostname, DNS lookup
1688 explore_fqdn(const struct addrinfo
*pai
, const char *hostname
,
1689 const char *servname
, struct addrinfo
**res
)
1691 struct addrinfo
*result
;
1692 struct addrinfo
*cur
;
1696 static const nss_cache_info cache_info
=
1697 NS_COMMON_CACHE_INFO_INITIALIZER(
1698 hosts
, NULL
, addrinfo_id_func
, addrinfo_marshal_func
,
1699 addrinfo_unmarshal_func
);
1701 static const ns_dtab dtab
[] = {
1702 NS_FILES_CB(_files_getaddrinfo
, NULL
)
1703 { NSSRC_DNS
, _dns_getaddrinfo
, NULL
}, /* force -DHESIOD */
1704 NS_NIS_CB(_yp_getaddrinfo
, NULL
)
1706 NS_CACHE_CB(&cache_info
)
1714 * if the servname does not match socktype/protocol, ignore it.
1716 if (get_portmatch(pai
, servname
) != 0)
1719 switch (_nsdispatch(&result
, dtab
, NSDB_HOSTS
, "getaddrinfo",
1720 default_dns_files
, hostname
, pai
)) {
1732 for (cur
= result
; cur
; cur
= cur
->ai_next
) {
1733 GET_PORT(cur
, servname
);
1734 /* canonname should be filled already */
1745 freeaddrinfo(result
);
1750 static const char AskedForGot
[] =
1751 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1754 static struct addrinfo
*
1755 getanswer(const querybuf
*answer
, int anslen
, const char *qname
, int qtype
,
1756 const struct addrinfo
*pai
, res_state res
)
1758 struct addrinfo sentinel
, *cur
;
1760 const struct afd
*afd
;
1767 int type
, class, ancount
, qdcount
;
1768 int haveanswer
, had_error
;
1769 char tbuf
[MAXDNAME
];
1770 int (*name_ok
)(const char *);
1771 char hostbuf
[8*1024];
1773 memset(&sentinel
, 0, sizeof(sentinel
));
1777 eom
= answer
->buf
+ anslen
;
1781 case T_ANY
: /*use T_ANY only for T_A/T_AAAA lookup*/
1785 return (NULL
); /* XXX should be abort(); */
1788 * find first satisfactory answer
1791 ancount
= ntohs(hp
->ancount
);
1792 qdcount
= ntohs(hp
->qdcount
);
1794 ep
= hostbuf
+ sizeof hostbuf
;
1795 cp
= answer
->buf
+ HFIXEDSZ
;
1797 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1800 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1801 if ((n
< 0) || !(*name_ok
)(bp
)) {
1802 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1806 if (qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) {
1807 /* res_send() has already verified that the query name is the
1808 * same as the one we sent; this just gets the expanded name
1809 * (i.e., with the succeeding search-domain tacked on).
1811 n
= strlen(bp
) + 1; /* for the \0 */
1812 if (n
>= MAXHOSTNAMELEN
) {
1813 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1818 /* The qname can be abbreviated, but h_name is now absolute. */
1823 while (ancount
-- > 0 && cp
< eom
&& !had_error
) {
1824 n
= dn_expand(answer
->buf
, eom
, cp
, bp
, ep
- bp
);
1825 if ((n
< 0) || !(*name_ok
)(bp
)) {
1830 type
= _getshort(cp
);
1831 cp
+= INT16SZ
; /* type */
1832 class = _getshort(cp
);
1833 cp
+= INT16SZ
+ INT32SZ
; /* class, TTL */
1835 cp
+= INT16SZ
; /* len */
1836 if (class != C_IN
) {
1837 /* XXX - debug? syslog? */
1839 continue; /* XXX - had_error++ ? */
1841 if ((qtype
== T_A
|| qtype
== T_AAAA
|| qtype
== T_ANY
) &&
1843 n
= dn_expand(answer
->buf
, eom
, cp
, tbuf
, sizeof tbuf
);
1844 if ((n
< 0) || !(*name_ok
)(tbuf
)) {
1849 /* Get canonical name. */
1850 n
= strlen(tbuf
) + 1; /* for the \0 */
1851 if (n
> ep
- bp
|| n
>= MAXHOSTNAMELEN
) {
1855 strlcpy(bp
, tbuf
, ep
- bp
);
1860 if (qtype
== T_ANY
) {
1861 if (!(type
== T_A
|| type
== T_AAAA
)) {
1865 } else if (type
!= qtype
) {
1867 if (type
!= T_KEY
&& type
!= T_SIG
)
1868 syslog(LOG_NOTICE
|LOG_AUTH
,
1869 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1870 qname
, p_class(C_IN
), p_type(qtype
),
1874 continue; /* XXX - had_error++ ? */
1879 if (strcasecmp(canonname
, bp
) != 0) {
1881 syslog(LOG_NOTICE
|LOG_AUTH
,
1882 AskedForGot
, canonname
, bp
);
1885 continue; /* XXX - had_error++ ? */
1887 if (type
== T_A
&& n
!= INADDRSZ
) {
1891 if (type
== T_AAAA
&& n
!= IN6ADDRSZ
) {
1895 #ifdef FILTER_V4MAPPED
1896 if (type
== T_AAAA
) {
1897 struct in6_addr in6
;
1898 memcpy(&in6
, cp
, sizeof(in6
));
1899 if (IN6_IS_ADDR_V4MAPPED(&in6
)) {
1909 nn
= strlen(bp
) + 1; /* for the \0 */
1913 /* don't overwrite pai */
1915 ai
.ai_family
= (type
== T_A
) ? AF_INET
: AF_INET6
;
1916 afd
= find_afd(ai
.ai_family
);
1921 cur
->ai_next
= get_ai(&ai
, afd
, (const char *)cp
);
1922 if (cur
->ai_next
== NULL
)
1924 while (cur
&& cur
->ai_next
)
1935 #if defined(RESOLVSORT)
1937 * We support only IPv4 address for backward
1938 * compatibility against gethostbyname(3).
1940 if (res
->nsort
&& qtype
== T_A
) {
1941 if (addr4sort(&sentinel
, res
) < 0) {
1942 freeaddrinfo(sentinel
.ai_next
);
1943 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1947 #endif /*RESOLVSORT*/
1949 get_canonname(pai
, sentinel
.ai_next
, qname
);
1951 get_canonname(pai
, sentinel
.ai_next
, canonname
);
1952 RES_SET_H_ERRNO(res
, NETDB_SUCCESS
);
1953 return sentinel
.ai_next
;
1956 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
1962 struct addrinfo
*ai
;
1967 addr4sort(struct addrinfo
*sentinel
, res_state res
)
1969 struct addrinfo
*ai
;
1970 struct addr_ptr
*addrs
, addr
;
1971 struct sockaddr_in
*sin
;
1978 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
)
1981 return 0; /* We don't need sorting. */
1982 if ((addrs
= malloc(sizeof(struct addr_ptr
) * naddrs
)) == NULL
)
1985 for (ai
= sentinel
->ai_next
; ai
; ai
= ai
->ai_next
) {
1986 sin
= (struct sockaddr_in
*)ai
->ai_addr
;
1987 for (j
= 0; (unsigned)j
< res
->nsort
; j
++) {
1988 if (res
->sort_list
[j
].addr
.s_addr
==
1989 (sin
->sin_addr
.s_addr
& res
->sort_list
[j
].mask
))
1994 if (needsort
== 0 && i
> 0 && j
< addrs
[i
- 1].aval
)
2003 while (needsort
< naddrs
) {
2004 for (j
= needsort
- 1; j
>= 0; j
--) {
2005 if (addrs
[j
].aval
> addrs
[j
+1].aval
) {
2007 addrs
[j
] = addrs
[j
+ 1];
2008 addrs
[j
+ 1] = addr
;
2016 for (i
= 0; i
< naddrs
; ++i
) {
2017 ai
->ai_next
= addrs
[i
].ai
;
2024 #endif /*RESOLVSORT*/
2028 _dns_getaddrinfo(void *rv
, void *cb_data
, va_list ap
)
2030 struct addrinfo
*ai
;
2031 querybuf
*buf
, *buf2
;
2032 const char *hostname
;
2033 const struct addrinfo
*pai
;
2034 struct addrinfo sentinel
, *cur
;
2035 struct res_target q
, q2
;
2038 hostname
= va_arg(ap
, char *);
2039 pai
= va_arg(ap
, const struct addrinfo
*);
2041 memset(&q
, 0, sizeof(q
));
2042 memset(&q2
, 0, sizeof(q2
));
2043 memset(&sentinel
, 0, sizeof(sentinel
));
2046 buf
= malloc(sizeof(*buf
));
2048 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2051 buf2
= malloc(sizeof(*buf2
));
2054 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2058 switch (pai
->ai_family
) {
2063 q
.answer
= buf
->buf
;
2064 q
.anslen
= sizeof(buf
->buf
);
2069 q2
.answer
= buf2
->buf
;
2070 q2
.anslen
= sizeof(buf2
->buf
);
2076 q
.answer
= buf
->buf
;
2077 q
.anslen
= sizeof(buf
->buf
);
2083 q
.answer
= buf
->buf
;
2084 q
.anslen
= sizeof(buf
->buf
);
2092 res
= __res_state();
2093 if ((res
->options
& RES_INIT
) == 0 && res_ninit(res
) == -1) {
2094 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2100 if (res_searchN(hostname
, &q
, res
) < 0) {
2107 ai
= getanswer(buf2
, q2
.n
, q2
.name
, q2
.qtype
, pai
, res
);
2110 while (cur
&& cur
->ai_next
)
2114 ai
= getanswer(buf
, q
.n
, q
.name
, q
.qtype
, pai
, res
);
2119 if (sentinel
.ai_next
== NULL
)
2120 switch (res
->res_h_errno
) {
2121 case HOST_NOT_FOUND
:
2128 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2133 _sethtent(FILE **hostf
)
2136 *hostf
= fopen(_PATH_HOSTS
, "r");
2142 _endhtent(FILE **hostf
)
2150 static struct addrinfo
*
2151 _gethtent(FILE **hostf
, const char *name
, const struct addrinfo
*pai
)
2154 char *cp
, *tname
, *cname
;
2155 struct addrinfo hints
, *res0
, *res
;
2158 char hostbuf
[8*1024];
2160 if (!*hostf
&& !(*hostf
= fopen(_PATH_HOSTS
, "r")))
2163 if (!(p
= fgets(hostbuf
, sizeof hostbuf
, *hostf
)))
2167 cp
= strpbrk(p
, "#\n");
2170 if (!(cp
= strpbrk(p
, " \t")))
2175 /* if this is not something we're looking for, skip it. */
2177 if (*cp
== ' ' || *cp
== '\t') {
2184 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2186 if (strcasecmp(name
, tname
) == 0)
2192 /* we should not glob socktype/protocol here */
2193 memset(&hints
, 0, sizeof(hints
));
2194 hints
.ai_family
= pai
->ai_family
;
2195 hints
.ai_socktype
= SOCK_DGRAM
;
2196 hints
.ai_protocol
= 0;
2197 hints
.ai_flags
= AI_NUMERICHOST
;
2198 error
= getaddrinfo(addr
, "0", &hints
, &res0
);
2201 #ifdef FILTER_V4MAPPED
2202 /* XXX should check all items in the chain */
2203 if (res0
->ai_family
== AF_INET6
&&
2204 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6
*)res0
->ai_addr
)->sin6_addr
)) {
2209 for (res
= res0
; res
; res
= res
->ai_next
) {
2211 res
->ai_flags
= pai
->ai_flags
;
2212 res
->ai_socktype
= pai
->ai_socktype
;
2213 res
->ai_protocol
= pai
->ai_protocol
;
2215 if (pai
->ai_flags
& AI_CANONNAME
) {
2216 if (get_canonname(pai
, res
, cname
) != 0) {
2227 _files_getaddrinfo(void *rv
, void *cb_data
, va_list ap
)
2230 const struct addrinfo
*pai
;
2231 struct addrinfo sentinel
, *cur
;
2235 name
= va_arg(ap
, char *);
2236 pai
= va_arg(ap
, struct addrinfo
*);
2238 memset(&sentinel
, 0, sizeof(sentinel
));
2242 while ((p
= _gethtent(&hostf
, name
, pai
)) != NULL
) {
2244 while (cur
&& cur
->ai_next
)
2249 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2250 if (sentinel
.ai_next
== NULL
)
2257 static struct addrinfo
*
2258 _yphostent(char *line
, const struct addrinfo
*pai
)
2260 struct addrinfo sentinel
, *cur
;
2261 struct addrinfo hints
, *res
, *res0
;
2264 const char *addr
, *canonname
;
2268 addr
= canonname
= NULL
;
2270 memset(&sentinel
, 0, sizeof(sentinel
));
2274 /* terminate line */
2275 cp
= strchr(p
, '\n');
2282 cp
= strpbrk(p
, " \t");
2284 if (canonname
== NULL
)
2294 if (*cp
== ' ' || *cp
== '\t') {
2300 if ((cp
= strpbrk(cp
, " \t")) != NULL
)
2305 hints
.ai_flags
= AI_NUMERICHOST
;
2306 error
= getaddrinfo(addr
, NULL
, &hints
, &res0
);
2308 for (res
= res0
; res
; res
= res
->ai_next
) {
2310 res
->ai_flags
= pai
->ai_flags
;
2312 if (pai
->ai_flags
& AI_CANONNAME
)
2313 get_canonname(pai
, res
, canonname
);
2318 cur
->ai_next
= res0
;
2319 while (cur
&& cur
->ai_next
)
2329 return sentinel
.ai_next
;
2334 _yp_getaddrinfo(void *rv
, void *cb_data
, va_list ap
)
2336 struct addrinfo sentinel
, *cur
;
2337 struct addrinfo
*ai
= NULL
;
2341 const struct addrinfo
*pai
;
2344 if (_yp_check(&ypdomain
) == 0)
2347 name
= va_arg(ap
, char *);
2348 pai
= va_arg(ap
, const struct addrinfo
*);
2350 memset(&sentinel
, 0, sizeof(sentinel
));
2353 /* hosts.byname is only for IPv4 (Solaris8) */
2354 if (pai
->ai_family
== PF_UNSPEC
|| pai
->ai_family
== PF_INET
) {
2355 r
= yp_match(ypdomain
, "hosts.byname", name
,
2356 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2358 struct addrinfo ai4
;
2361 ai4
.ai_family
= AF_INET
;
2362 ai
= _yphostent(ypbuf
, &ai4
);
2365 while (cur
&& cur
->ai_next
)
2372 /* ipnodes.byname can hold both IPv4/v6 */
2373 r
= yp_match(ypdomain
, "ipnodes.byname", name
,
2374 (int)strlen(name
), &ypbuf
, &ypbuflen
);
2376 ai
= _yphostent(ypbuf
, pai
);
2382 if (sentinel
.ai_next
== NULL
) {
2383 RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND
);
2386 *((struct addrinfo
**)rv
) = sentinel
.ai_next
;
2391 /* resolver logic */
2394 * Formulate a normal query, send, and await answer.
2395 * Returned answer is placed in supplied buffer "answer".
2396 * Perform preliminary check of answer, returning success only
2397 * if no error is indicated and the answer count is nonzero.
2398 * Return the size of the response on success, -1 on error.
2399 * Error number is left in h_errno.
2401 * Caller must parse answer and determine whether it answers the question.
2404 res_queryN(const char *name
, struct res_target
*target
, res_state res
)
2410 struct res_target
*t
;
2417 buf
= malloc(MAXPACKET
);
2419 RES_SET_H_ERRNO(res
, NETDB_INTERNAL
);
2423 for (t
= target
; t
; t
= t
->next
) {
2428 hp
= (HEADER
*)(void *)t
->answer
;
2430 /* make it easier... */
2436 oflags
= res
->_flags
;
2439 hp
->rcode
= NOERROR
; /* default */
2442 if (res
->options
& RES_DEBUG
)
2443 printf(";; res_query(%s, %d, %d)\n", name
, class, type
);
2446 n
= res_nmkquery(res
, QUERY
, name
, class, type
, NULL
, 0, NULL
,
2448 if (n
> 0 && (res
->_flags
& RES_F_EDNS0ERR
) == 0 &&
2449 (res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
)) != 0U)
2450 n
= res_nopt(res
, n
, buf
, MAXPACKET
, anslen
);
2453 if (res
->options
& RES_DEBUG
)
2454 printf(";; res_query: mkquery failed\n");
2457 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2460 n
= res_nsend(res
, buf
, n
, answer
, anslen
);
2463 * if the query choked with EDNS0, retry
2466 if ((res
->options
& (RES_USE_EDNS0
|RES_USE_DNSSEC
))
2468 ((oflags
^ res
->_flags
) & RES_F_EDNS0ERR
) != 0) {
2469 res
->_flags
|= RES_F_EDNS0ERR
;
2470 if (res
->options
& RES_DEBUG
)
2471 printf(";; res_nquery: retry without EDNS0\n");
2474 rcode
= hp
->rcode
; /* record most recent error */
2476 if (res
->options
& RES_DEBUG
)
2477 printf(";; res_query: send error\n");
2483 hp
->rcode
= FORMERR
; /* XXX not very informative */
2484 if (hp
->rcode
!= NOERROR
|| ntohs(hp
->ancount
) == 0) {
2485 rcode
= hp
->rcode
; /* record most recent error */
2487 if (res
->options
& RES_DEBUG
)
2488 printf(";; rcode = %u, ancount=%u\n", hp
->rcode
,
2489 ntohs(hp
->ancount
));
2494 ancount
+= ntohs(hp
->ancount
);
2504 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
);
2507 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2510 RES_SET_H_ERRNO(res
, NO_DATA
);
2516 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2525 * Formulate a normal query, send, and retrieve answer in supplied buffer.
2526 * Return the size of the response on success, -1 on error.
2527 * If enabled, implement search rules until answer or unrecoverable failure
2528 * is detected. Error code, if any, is left in h_errno.
2531 res_searchN(const char *name
, struct res_target
*target
, res_state res
)
2533 const char *cp
, * const *domain
;
2534 HEADER
*hp
= (HEADER
*)(void *)target
->answer
; /*XXX*/
2536 int trailing_dot
, ret
, saved_herrno
;
2537 int got_nodata
= 0, got_servfail
= 0, root_on_list
= 0;
2538 int tried_as_is
= 0;
2540 char abuf
[MAXDNAME
];
2543 RES_SET_H_ERRNO(res
, HOST_NOT_FOUND
); /* default, if we never query */
2545 for (cp
= name
; *cp
; cp
++)
2546 dots
+= (*cp
== '.');
2548 if (cp
> name
&& *--cp
== '.')
2552 * if there aren't any dots, it could be a user-level alias
2555 (cp
= res_hostalias(res
, name
, abuf
, sizeof(abuf
))) != NULL
)
2556 return (res_queryN(cp
, target
, res
));
2559 * If there are enough dots in the name, let's just give it a
2560 * try 'as is'. The threshold can be set with the "ndots" option.
2561 * Also, query 'as is', if there is a trailing dot in the name.
2564 if (dots
>= res
->ndots
|| trailing_dot
) {
2565 ret
= res_querydomainN(name
, NULL
, target
, res
);
2566 if (ret
> 0 || trailing_dot
)
2568 if (errno
== ECONNREFUSED
) {
2569 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2572 switch (res
->res_h_errno
) {
2574 case HOST_NOT_FOUND
:
2577 if (hp
->rcode
== SERVFAIL
)
2583 saved_herrno
= res
->res_h_errno
;
2588 * We do at least one level of search if
2589 * - there is no dot and RES_DEFNAME is set, or
2590 * - there is at least one dot, there is no trailing dot,
2591 * and RES_DNSRCH is set.
2593 if ((!dots
&& (res
->options
& RES_DEFNAMES
)) ||
2594 (dots
&& !trailing_dot
&& (res
->options
& RES_DNSRCH
))) {
2597 for (domain
= (const char * const *)res
->dnsrch
;
2602 if (domain
[0][0] == '\0' ||
2603 (domain
[0][0] == '.' && domain
[0][1] == '\0'))
2606 if (root_on_list
&& tried_as_is
)
2609 ret
= res_querydomainN(name
, *domain
, target
, res
);
2614 * If no server present, give up.
2615 * If name isn't found in this domain,
2616 * keep trying higher domains in the search list
2617 * (if that's enabled).
2618 * On a NO_DATA error, keep trying, otherwise
2619 * a wildcard entry of another type could keep us
2620 * from finding this entry higher in the domain.
2621 * If we get some other error (negative answer or
2622 * server failure), then stop searching up,
2623 * but try the input name below in case it's
2626 if (errno
== ECONNREFUSED
) {
2627 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2631 switch (res
->res_h_errno
) {
2635 case HOST_NOT_FOUND
:
2640 if (hp
->rcode
== SERVFAIL
) {
2641 /* try next search element, if any */
2646 /* anything else implies that we're done */
2650 * if we got here for some reason other than DNSRCH,
2651 * we only wanted one iteration of the loop, so stop.
2653 if (!(res
->options
& RES_DNSRCH
))
2658 switch (res
->res_h_errno
) {
2660 case HOST_NOT_FOUND
:
2663 if (hp
->rcode
== SERVFAIL
)
2671 * If the query has not already been tried as is then try it
2672 * unless RES_NOTLDQUERY is set and there were no dots.
2674 if ((dots
|| !searched
|| !(res
->options
& RES_NOTLDQUERY
)) &&
2675 !(tried_as_is
|| root_on_list
)) {
2676 ret
= res_querydomainN(name
, NULL
, target
, res
);
2682 * if we got here, we didn't satisfy the search.
2683 * if we did an initial full query, return that query's h_errno
2684 * (note that we wouldn't be here if that query had succeeded).
2685 * else if we ever got a nodata, send that back as the reason.
2686 * else send back meaningless h_errno, that being the one from
2687 * the last DNSRCH we did.
2690 if (saved_herrno
!= -1)
2691 RES_SET_H_ERRNO(res
, saved_herrno
);
2692 else if (got_nodata
)
2693 RES_SET_H_ERRNO(res
, NO_DATA
);
2694 else if (got_servfail
)
2695 RES_SET_H_ERRNO(res
, TRY_AGAIN
);
2700 * Perform a call on res_query on the concatenation of name and domain,
2701 * removing a trailing dot from name if domain is NULL.
2704 res_querydomainN(const char *name
, const char *domain
,
2705 struct res_target
*target
, res_state res
)
2707 char nbuf
[MAXDNAME
];
2708 const char *longname
= nbuf
;
2712 if (res
->options
& RES_DEBUG
)
2713 printf(";; res_querydomain(%s, %s)\n",
2714 name
, domain
?domain
:"<Nil>");
2716 if (domain
== NULL
) {
2718 * Check for trailing '.';
2719 * copy without '.' if present.
2722 if (n
>= MAXDNAME
) {
2723 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2726 if (n
> 0 && name
[--n
] == '.') {
2727 strncpy(nbuf
, name
, n
);
2734 if (n
+ d
+ 1 >= MAXDNAME
) {
2735 RES_SET_H_ERRNO(res
, NO_RECOVERY
);
2738 snprintf(nbuf
, sizeof(nbuf
), "%s.%s", name
, domain
);
2740 return (res_queryN(longname
, target
, res
));