1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
47 #include <stdio_ext.h>
50 #include <arpa/inet.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
55 #include <sys/types.h>
57 #include <sys/utsname.h>
60 #include <bits/libc-lock.h>
61 #include <not-cancel.h>
62 #include <nscd/nscd-client.h>
63 #include <nscd/nscd_proto.h>
64 #include <resolv/res_hconf.h>
67 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
68 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
70 # include <libidn/idna.h>
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77 # define UNIX_PATH_MAX 108
88 struct gaih_servtuple
*next
;
94 static const struct gaih_servtuple nullserv
;
106 /* Values for `protoflag'. */
107 #define GAI_PROTO_NOSERVICE 1
108 #define GAI_PROTO_PROTOANY 2
110 static const struct gaih_typeproto gaih_inet_typeproto
[] =
112 { 0, 0, 0, false, "" },
113 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
114 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
115 #if defined SOCK_DCCP && defined IPPROTO_DCCP
116 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
118 #ifdef IPPROTO_UDPLITE
119 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
122 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
123 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
125 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
126 { 0, 0, 0, false, "" }
132 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
133 const struct addrinfo
*req
, struct addrinfo
**pai
,
134 unsigned int *naddrs
);
137 static const struct addrinfo default_hints
=
139 .ai_flags
= AI_DEFAULT
,
140 .ai_family
= PF_UNSPEC
,
145 .ai_canonname
= NULL
,
151 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
152 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
155 size_t tmpbuflen
= 1024;
162 tmpbuf
= __alloca (tmpbuflen
);
164 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
166 if (r
!= 0 || s
== NULL
)
171 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
177 st
->socktype
= tp
->socktype
;
178 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
179 ? req
->ai_protocol
: tp
->protocol
);
180 st
->port
= s
->s_port
;
185 #define gethosts(_family, _type) \
191 char *localcanon = NULL; \
195 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
196 &rc, &herrno, NULL, &localcanon)); \
197 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
199 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
201 if (status == NSS_STATUS_SUCCESS && rc == 0) \
207 if (herrno == NETDB_INTERNAL) \
209 __set_h_errno (herrno); \
210 _res.options = old_res_options; \
211 return -EAI_SYSTEM; \
213 if (herrno == TRY_AGAIN) \
214 no_data = EAI_AGAIN; \
216 no_data = herrno == NO_DATA; \
218 else if (h != NULL) \
220 for (i = 0; h->h_addr_list[i]; i++) \
224 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
225 (*pat)->scopeid = 0; \
227 uint32_t *addr = (*pat)->addr; \
228 (*pat)->next = NULL; \
229 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
230 if (_family == AF_INET && req->ai_family == AF_INET6) \
232 (*pat)->family = AF_INET6; \
233 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
234 addr[2] = htonl (0xffff); \
240 (*pat)->family = _family; \
241 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
243 pat = &((*pat)->next); \
246 if (localcanon != NULL && canon == NULL) \
247 canon = strdupa (localcanon); \
249 if (_family == AF_INET6 && i > 0) \
255 typedef enum nss_status (*nss_gethostbyname4_r
)
256 (const char *name
, struct gaih_addrtuple
**pat
,
257 char *buffer
, size_t buflen
, int *errnop
,
258 int *h_errnop
, int32_t *ttlp
);
259 typedef enum nss_status (*nss_gethostbyname3_r
)
260 (const char *name
, int af
, struct hostent
*host
,
261 char *buffer
, size_t buflen
, int *errnop
,
262 int *h_errnop
, int32_t *ttlp
, char **canonp
);
263 typedef enum nss_status (*nss_getcanonname_r
)
264 (const char *name
, char *buffer
, size_t buflen
, char **result
,
265 int *errnop
, int *h_errnop
);
266 extern service_user
*__nss_hosts_database attribute_hidden
;
270 gaih_inet (const char *name
, const struct gaih_service
*service
,
271 const struct addrinfo
*req
, struct addrinfo
**pai
,
272 unsigned int *naddrs
)
274 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
275 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
276 struct gaih_addrtuple
*at
= NULL
;
278 bool got_ipv6
= false;
279 const char *canon
= NULL
;
280 const char *orig_name
= name
;
282 if (req
->ai_protocol
|| req
->ai_socktype
)
287 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
288 || (req
->ai_protocol
!= 0
289 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
290 && req
->ai_protocol
!= tp
->protocol
)))
295 if (req
->ai_socktype
)
296 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
298 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
305 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
306 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
308 if (service
->num
< 0)
312 st
= (struct gaih_servtuple
*)
313 __alloca (sizeof (struct gaih_servtuple
));
315 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
320 struct gaih_servtuple
**pst
= &st
;
321 for (tp
++; tp
->name
[0]; tp
++)
323 struct gaih_servtuple
*newp
;
325 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
328 if (req
->ai_socktype
!= 0
329 && req
->ai_socktype
!= tp
->socktype
)
331 if (req
->ai_protocol
!= 0
332 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
333 && req
->ai_protocol
!= tp
->protocol
)
336 newp
= (struct gaih_servtuple
*)
337 __alloca (sizeof (struct gaih_servtuple
));
339 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
341 if (rc
& GAIH_OKIFUNSPEC
)
349 if (st
== (struct gaih_servtuple
*) &nullserv
)
350 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
355 port
= htons (service
->num
);
363 if (req
->ai_socktype
|| req
->ai_protocol
)
365 st
= __alloca (sizeof (struct gaih_servtuple
));
367 st
->socktype
= tp
->socktype
;
368 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
369 ? req
->ai_protocol
: tp
->protocol
);
374 /* Neither socket type nor protocol is set. Return all socket types
376 struct gaih_servtuple
**lastp
= &st
;
377 for (++tp
; tp
->name
[0]; ++tp
)
380 struct gaih_servtuple
*newp
;
382 newp
= __alloca (sizeof (struct gaih_servtuple
));
384 newp
->socktype
= tp
->socktype
;
385 newp
->protocol
= tp
->protocol
;
396 at
= __alloca (sizeof (struct gaih_addrtuple
));
398 at
->family
= AF_UNSPEC
;
403 if (req
->ai_flags
& AI_IDN
)
406 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
407 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
408 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
409 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
412 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
413 if (rc
!= IDNA_SUCCESS
)
415 if (rc
== IDNA_MALLOC_ERROR
)
417 if (rc
== IDNA_DLOPEN_ERROR
)
419 return -EAI_IDN_ENCODE
;
421 /* In case the output string is the same as the input string
422 no new string has been allocated. */
431 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
433 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
434 at
->family
= AF_INET
;
435 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
437 at
->addr
[3] = at
->addr
[0];
438 at
->addr
[2] = htonl (0xffff);
441 at
->family
= AF_INET6
;
444 return -EAI_ADDRFAMILY
;
446 if (req
->ai_flags
& AI_CANONNAME
)
449 else if (at
->family
== AF_UNSPEC
)
451 char *namebuf
= (char *) name
;
452 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
454 if (__builtin_expect (scope_delim
!= NULL
, 0))
456 namebuf
= alloca (scope_delim
- name
+ 1);
457 *((char *) __mempcpy (namebuf
, name
, scope_delim
- name
)) = '\0';
460 if (inet_pton (AF_INET6
, namebuf
, at
->addr
) > 0)
462 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
463 at
->family
= AF_INET6
;
464 else if (req
->ai_family
== AF_INET
465 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
467 at
->addr
[0] = at
->addr
[3];
468 at
->family
= AF_INET
;
471 return -EAI_ADDRFAMILY
;
473 if (scope_delim
!= NULL
)
475 int try_numericscope
= 0;
476 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
477 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
479 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
480 if (at
->scopeid
== 0)
481 try_numericscope
= 1;
484 try_numericscope
= 1;
486 if (try_numericscope
!= 0)
489 assert (sizeof (uint32_t) <= sizeof (unsigned long));
490 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
493 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
497 if (req
->ai_flags
& AI_CANONNAME
)
502 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
504 struct gaih_addrtuple
**pat
= &at
;
506 int no_inet6_data
= 0;
507 service_user
*nip
= NULL
;
508 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
509 enum nss_status status
= NSS_STATUS_UNAVAIL
;
513 /* If we do not have to look for IPv4 and IPv6 together, use
514 the simple, old functions. */
515 if (req
->ai_family
== AF_INET
516 || (req
->ai_family
== AF_INET6
517 && ((req
->ai_flags
& AI_V4MAPPED
) == 0
518 || (req
->ai_flags
& AI_ALL
) == 0)))
520 int family
= req
->ai_family
;
521 size_t tmpbuflen
= 512;
522 char *tmpbuf
= alloca (tmpbuflen
);
531 rc
= __gethostbyname2_r (name
, family
, &th
, tmpbuf
,
532 tmpbuflen
, &h
, &herrno
);
533 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
535 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, 2 * tmpbuflen
);
542 if (req
->ai_family
== AF_INET6
543 && (req
->ai_flags
& AI_V4MAPPED
)
544 && family
== AF_INET6
)
546 /* Try again, this time looking for IPv4
554 /* We found data, now convert it into the list. */
555 for (int i
= 0; h
->h_addr_list
[i
]; ++i
)
559 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
563 (*pat
)->family
= req
->ai_family
;
564 if (family
== req
->ai_family
)
565 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
569 uint32_t *addr
= (uint32_t *) (*pat
)->addr
;
570 addr
[3] = *(uint32_t *) h
->h_addr_list
[i
];
571 addr
[2] = htonl (0xffff);
575 pat
= &((*pat
)->next
);
581 if (herrno
== NETDB_INTERNAL
)
583 __set_h_errno (herrno
);
586 if (herrno
== TRY_AGAIN
)
590 /* We made requests but they turned out no data.
591 The name is known, though. */
592 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
599 if (__nss_not_use_nscd_hosts
> 0
600 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
601 __nss_not_use_nscd_hosts
= 0;
603 if (!__nss_not_use_nscd_hosts
)
605 /* Try to use nscd. */
606 struct nscd_ai_result
*air
= NULL
;
608 int err
= __nscd_getai (name
, &air
, &herrno
);
611 /* Transform into gaih_addrtuple list. */
612 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
613 char *addrs
= air
->addrs
;
615 for (int i
= 0; i
< air
->naddrs
; ++i
)
617 socklen_t size
= (air
->family
[i
] == AF_INET
618 ? INADDRSZ
: IN6ADDRSZ
);
621 *pat
= __alloca (sizeof (struct gaih_addrtuple
));
624 uint32_t *pataddr
= (*pat
)->addr
;
626 if (added_canon
|| air
->canon
== NULL
)
629 canon
= (*pat
)->name
= strdupa (air
->canon
);
631 if (air
->family
[i
] == AF_INET
632 && req
->ai_family
== AF_INET6
633 && (req
->ai_flags
& AI_V4MAPPED
))
635 (*pat
)->family
= AF_INET6
;
636 pataddr
[3] = *(uint32_t *) addrs
;
637 pataddr
[2] = htonl (0xffff);
640 pat
= &((*pat
)->next
);
643 else if (req
->ai_family
== AF_UNSPEC
644 || air
->family
[i
] == req
->ai_family
)
646 (*pat
)->family
= air
->family
[i
];
647 memcpy (pataddr
, addrs
, size
);
648 pat
= &((*pat
)->next
);
650 if (air
->family
[i
] == AF_INET6
)
658 if (at
->family
== AF_UNSPEC
)
659 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
664 /* The database contains a negative entry. */
666 else if (__nss_not_use_nscd_hosts
== 0)
668 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
670 if (herrno
== TRY_AGAIN
)
677 if (__nss_hosts_database
!= NULL
)
680 nip
= __nss_hosts_database
;
683 no_more
= __nss_database_lookup ("hosts", NULL
,
684 "dns [!UNAVAIL=return] files",
687 /* Initialize configurations. */
688 if (__builtin_expect (!_res_hconf
.initialized
, 0))
690 if (__res_maybe_init (&_res
, 0) == -1)
693 /* If we are looking for both IPv4 and IPv6 address we don't
694 want the lookup functions to automatically promote IPv4
695 addresses to IPv6 addresses. Currently this is decided
696 by setting the RES_USE_INET6 bit in _res.options. */
697 old_res_options
= _res
.options
;
698 _res
.options
&= ~RES_USE_INET6
;
700 size_t tmpbuflen
= 1024;
701 char *tmpbuf
= alloca (tmpbuflen
);
705 nss_gethostbyname4_r fct4
706 = __nss_lookup_function (nip
, "gethostbyname4_r");
714 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
715 tmpbuflen
, &rc
, &herrno
,
717 if (status
== NSS_STATUS_SUCCESS
)
719 if (status
!= NSS_STATUS_TRYAGAIN
720 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
722 if (status
== NSS_STATUS_TRYAGAIN
723 && herrno
== TRY_AGAIN
)
726 no_data
= herrno
== NO_DATA
;
729 tmpbuf
= extend_alloca (tmpbuf
,
730 tmpbuflen
, 2 * tmpbuflen
);
733 no_inet6_data
= no_data
;
735 if (status
== NSS_STATUS_SUCCESS
)
737 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
738 canon
= (*pat
)->name
;
741 pat
= &((*pat
)->next
);
746 nss_gethostbyname3_r fct
= NULL
;
747 if (req
->ai_flags
& AI_CANONNAME
)
748 /* No need to use this function if we do not look for
749 the canonical name. The function does not exist in
750 all NSS modules and therefore the lookup would
752 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
754 /* We are cheating here. The gethostbyname2_r
755 function does not have the same interface as
756 gethostbyname3_r but the extra arguments the
757 latter takes are added at the end. So the
758 gethostbyname2_r code will just ignore them. */
759 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
763 if (req
->ai_family
== AF_INET6
764 || req
->ai_family
== AF_UNSPEC
)
766 gethosts (AF_INET6
, struct in6_addr
);
767 no_inet6_data
= no_data
;
768 inet6_status
= status
;
770 if (req
->ai_family
== AF_INET
771 || req
->ai_family
== AF_UNSPEC
772 || (req
->ai_family
== AF_INET6
773 && (req
->ai_flags
& AI_V4MAPPED
)
774 /* Avoid generating the mapped addresses if we
775 know we are not going to need them. */
776 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
778 gethosts (AF_INET
, struct in_addr
);
780 if (req
->ai_family
== AF_INET
)
782 no_inet6_data
= no_data
;
783 inet6_status
= status
;
787 /* If we found one address for AF_INET or AF_INET6,
788 don't continue the search. */
789 if (inet6_status
== NSS_STATUS_SUCCESS
790 || status
== NSS_STATUS_SUCCESS
)
792 if ((req
->ai_flags
& AI_CANONNAME
) != 0
795 /* If we need the canonical name, get it
796 from the same service as the result. */
797 nss_getcanonname_r cfct
;
800 cfct
= __nss_lookup_function (nip
,
804 const size_t max_fqdn_len
= 256;
805 char *buf
= alloca (max_fqdn_len
);
808 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
811 == NSS_STATUS_SUCCESS
)
814 /* Set to name now to avoid using
823 /* We can have different states for AF_INET and
824 AF_INET6. Try to find a useful one for both. */
825 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
826 status
= NSS_STATUS_TRYAGAIN
;
827 else if (status
== NSS_STATUS_UNAVAIL
828 && inet6_status
!= NSS_STATUS_UNAVAIL
)
829 status
= inet6_status
;
832 status
= NSS_STATUS_UNAVAIL
;
835 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
838 if (nip
->next
== NULL
)
844 _res
.options
= old_res_options
;
846 if (no_data
!= 0 && no_inet6_data
!= 0)
848 /* If both requests timed out report this. */
849 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
852 /* We made requests but they turned out no data. The name
854 return GAIH_OKIFUNSPEC
| -EAI_NODATA
;
859 if (at
->family
== AF_UNSPEC
)
860 return GAIH_OKIFUNSPEC
| -EAI_NONAME
;
864 struct gaih_addrtuple
*atr
;
865 atr
= at
= __alloca (sizeof (struct gaih_addrtuple
));
866 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
868 if (req
->ai_family
== AF_UNSPEC
)
870 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
871 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
874 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
876 at
->family
= AF_INET6
;
877 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
878 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
882 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
884 atr
->family
= AF_INET
;
885 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
886 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
891 struct gaih_servtuple
*st2
;
892 struct gaih_addrtuple
*at2
= at
;
897 buffer is the size of an unformatted IPv6 address in printable format.
901 /* Only the first entry gets the canonical name. */
902 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
906 struct hostent
*h
= NULL
;
909 size_t tmpbuflen
= 512;
914 tmpbuf
= extend_alloca (tmpbuf
, tmpbuflen
, tmpbuflen
* 2);
915 rc
= __gethostbyaddr_r (at2
->addr
,
916 ((at2
->family
== AF_INET6
)
917 ? sizeof (struct in6_addr
)
918 : sizeof (struct in_addr
)),
919 at2
->family
, &th
, tmpbuf
,
920 tmpbuflen
, &h
, &herrno
);
922 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
924 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
926 __set_h_errno (herrno
);
934 assert (orig_name
!= NULL
);
935 /* If the canonical name cannot be determined, use
936 the passed in string. */
942 if (req
->ai_flags
& AI_CANONIDN
)
945 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
946 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
947 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
948 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
951 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
952 if (rc
!= IDNA_SUCCESS
)
954 if (rc
== IDNA_MALLOC_ERROR
)
956 if (rc
== IDNA_DLOPEN_ERROR
)
958 return -EAI_IDN_ENCODE
;
960 /* In case the output string is the same as the input
961 string no new string has been allocated and we
972 canon
= strdup (canon
);
978 family
= at2
->family
;
979 if (family
== AF_INET6
)
981 socklen
= sizeof (struct sockaddr_in6
);
983 /* If we looked up IPv4 mapped address discard them here if
984 the caller isn't interested in all address and we have
985 found at least one IPv6 address. */
987 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
988 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
992 socklen
= sizeof (struct sockaddr_in
);
994 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
997 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1000 free ((char *) canon
);
1004 ai
->ai_flags
= req
->ai_flags
;
1005 ai
->ai_family
= family
;
1006 ai
->ai_socktype
= st2
->socktype
;
1007 ai
->ai_protocol
= st2
->protocol
;
1008 ai
->ai_addrlen
= socklen
;
1009 ai
->ai_addr
= (void *) (ai
+ 1);
1011 /* We only add the canonical name once. */
1012 ai
->ai_canonname
= (char *) canon
;
1016 ai
->ai_addr
->sa_len
= socklen
;
1017 #endif /* _HAVE_SA_LEN */
1018 ai
->ai_addr
->sa_family
= family
;
1020 /* In case of an allocation error the list must be NULL
1024 if (family
== AF_INET6
)
1026 struct sockaddr_in6
*sin6p
=
1027 (struct sockaddr_in6
*) ai
->ai_addr
;
1029 sin6p
->sin6_port
= st2
->port
;
1030 sin6p
->sin6_flowinfo
= 0;
1031 memcpy (&sin6p
->sin6_addr
,
1032 at2
->addr
, sizeof (struct in6_addr
));
1033 sin6p
->sin6_scope_id
= at2
->scopeid
;
1037 struct sockaddr_in
*sinp
=
1038 (struct sockaddr_in
*) ai
->ai_addr
;
1039 sinp
->sin_port
= st2
->port
;
1040 memcpy (&sinp
->sin_addr
,
1041 at2
->addr
, sizeof (struct in_addr
));
1042 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1045 pai
= &(ai
->ai_next
);
1060 struct addrinfo
*dest_addr
;
1061 /* Using sockaddr_storage is for now overkill. We only support IPv4
1062 and IPv6 so far. If this changes at some point we can adjust the
1064 struct sockaddr_in6 source_addr
;
1065 uint8_t source_addr_len
;
1066 bool got_source_addr
;
1067 uint8_t source_addr_flags
;
1073 struct sort_result_combo
1075 struct sort_result
*results
;
1080 #if __BYTE_ORDER == __BIG_ENDIAN
1081 # define htonl_c(n) n
1083 # define htonl_c(n) __bswap_constant_32 (n)
1086 static const struct scopeentry
1095 } default_scopes
[] =
1097 /* Link-local addresses: scope 2. */
1098 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1099 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1100 /* Site-local addresses: scope 5. */
1101 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1102 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1103 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1104 /* Default: scope 14. */
1105 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1108 /* The label table. */
1109 static const struct scopeentry
*scopes
;
1113 get_scope (const struct sockaddr_in6
*in6
)
1116 if (in6
->sin6_family
== PF_INET6
)
1118 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1120 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1121 /* RFC 4291 2.5.3 says that the loopback address is to be
1122 treated like a link-local address. */
1123 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1125 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1128 /* XXX Is this the correct default behavior? */
1132 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1134 else if (in6
->sin6_family
== PF_INET
)
1136 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1141 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1142 == scopes
[cnt
].addr32
)
1143 return scopes
[cnt
].scope
;
1150 /* XXX What is a good default? */
1159 struct in6_addr prefix
;
1165 /* The label table. */
1166 static const struct prefixentry
*labels
;
1168 /* Default labels. */
1169 static const struct prefixentry default_labels
[] =
1171 /* See RFC 3484 for the details. */
1173 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1177 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1181 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1185 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1188 /* The next two entries differ from RFC 3484. We need to treat
1189 IPv6 site-local addresses special because they are never NATed,
1190 unlike site-locale IPv4 addresses. If this would not happen, on
1191 machines which have only IPv4 and IPv6 site-local addresses, the
1192 sorting would prefer the IPv6 site-local addresses, causing
1193 unnecessary delays when trying to connect to a global IPv6 address
1194 through a site-local IPv6 address. */
1196 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1200 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1203 /* Additional rule for Teredo tunnels. */
1205 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1209 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1215 /* The precedence table. */
1216 static const struct prefixentry
*precedence
;
1218 /* The default precedences. */
1219 static const struct prefixentry default_precedence
[] =
1221 /* See RFC 3484 for the details. */
1223 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1227 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1231 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1235 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1236 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1239 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1246 match_prefix (const struct sockaddr_in6
*in6
,
1247 const struct prefixentry
*list
, int default_val
)
1250 struct sockaddr_in6 in6_mem
;
1252 if (in6
->sin6_family
== PF_INET
)
1254 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1256 /* Construct a V4-to-6 mapped address. */
1257 in6_mem
.sin6_family
= PF_INET6
;
1258 in6_mem
.sin6_port
= in
->sin_port
;
1259 in6_mem
.sin6_flowinfo
= 0;
1260 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1261 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1262 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1263 in6_mem
.sin6_scope_id
= 0;
1267 else if (in6
->sin6_family
!= PF_INET6
)
1270 for (idx
= 0; ; ++idx
)
1272 unsigned int bits
= list
[idx
].bits
;
1273 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1274 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1288 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1294 return list
[idx
].val
;
1299 get_label (const struct sockaddr_in6
*in6
)
1301 /* XXX What is a good default value? */
1302 return match_prefix (in6
, labels
, INT_MAX
);
1307 get_precedence (const struct sockaddr_in6
*in6
)
1309 /* XXX What is a good default value? */
1310 return match_prefix (in6
, precedence
, 0);
1314 /* Find last bit set in a word. */
1320 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1321 if ((a
& mask
) != 0)
1328 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1330 const size_t idx1
= *(const size_t *) p1
;
1331 const size_t idx2
= *(const size_t *) p2
;
1332 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1333 struct sort_result
*a1
= &src
->results
[idx1
];
1334 struct sort_result
*a2
= &src
->results
[idx2
];
1336 /* Rule 1: Avoid unusable destinations.
1337 We have the got_source_addr flag set if the destination is reachable. */
1338 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1340 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1344 /* Rule 2: Prefer matching scope. Only interesting if both
1345 destination addresses are IPv6. */
1347 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1350 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1352 if (a1
->got_source_addr
)
1354 int a1_src_scope
= get_scope (&a1
->source_addr
);
1355 int a2_src_scope
= get_scope (&a2
->source_addr
);
1357 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1359 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1364 /* Rule 3: Avoid deprecated addresses. */
1365 if (a1
->got_source_addr
)
1367 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1368 && (a2
->source_addr_flags
& in6ai_deprecated
))
1370 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1371 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1375 /* Rule 4: Prefer home addresses. */
1376 if (a1
->got_source_addr
)
1378 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1379 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1381 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1382 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1386 /* Rule 5: Prefer matching label. */
1387 if (a1
->got_source_addr
)
1390 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1391 int a1_src_label
= get_label (&a1
->source_addr
);
1394 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1395 int a2_src_label
= get_label (&a2
->source_addr
);
1397 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1399 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1404 /* Rule 6: Prefer higher precedence. */
1406 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1408 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1410 if (a1_prec
> a2_prec
)
1412 if (a1_prec
< a2_prec
)
1416 /* Rule 7: Prefer native transport. */
1417 if (a1
->got_source_addr
)
1419 /* The same interface index means the same interface which means
1420 there is no difference in transport. This should catch many
1422 if (a1
->index
!= a2
->index
)
1424 int a1_native
= a1
->native
;
1425 int a2_native
= a2
->native
;
1427 if (a1_native
== -1 || a2_native
== -1)
1430 if (a1_native
== -1)
1432 /* If we do not have the information use 'native' as
1435 a1_index
= a1
->index
;
1438 a1_index
= 0xffffffffu
;
1441 if (a2_native
== -1)
1443 /* If we do not have the information use 'native' as
1446 a2_index
= a2
->index
;
1449 a2_index
= 0xffffffffu
;
1451 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1453 /* Fill in the results in all the records. */
1454 for (int i
= 0; i
< src
->nresults
; ++i
)
1455 if (src
->results
[i
].index
== a1_index
)
1457 assert (src
->results
[i
].native
== -1
1458 || src
->results
[i
].native
== a1_native
);
1459 src
->results
[i
].native
= a1_native
;
1461 else if (src
->results
[i
].index
== a2_index
)
1463 assert (src
->results
[i
].native
== -1
1464 || src
->results
[i
].native
== a2_native
);
1465 src
->results
[i
].native
= a2_native
;
1469 if (a1_native
&& !a2_native
)
1471 if (!a1_native
&& a2_native
)
1477 /* Rule 8: Prefer smaller scope. */
1478 if (a1_dst_scope
< a2_dst_scope
)
1480 if (a1_dst_scope
> a2_dst_scope
)
1484 /* Rule 9: Use longest matching prefix. */
1485 if (a1
->got_source_addr
1486 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1491 if (a1
->dest_addr
->ai_family
== PF_INET
)
1493 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1494 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1496 /* Outside of subnets, as defined by the network masks,
1497 common address prefixes for IPv4 addresses make no sense.
1498 So, define a non-zero value only if source and
1499 destination address are on the same subnet. */
1500 struct sockaddr_in
*in1_dst
1501 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1502 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1503 struct sockaddr_in
*in1_src
1504 = (struct sockaddr_in
*) &a1
->source_addr
;
1505 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1506 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1508 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1509 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1511 struct sockaddr_in
*in2_dst
1512 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1513 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1514 struct sockaddr_in
*in2_src
1515 = (struct sockaddr_in
*) &a2
->source_addr
;
1516 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1517 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1519 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1520 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1522 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1524 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1525 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1527 struct sockaddr_in6
*in1_dst
;
1528 struct sockaddr_in6
*in1_src
;
1529 struct sockaddr_in6
*in2_dst
;
1530 struct sockaddr_in6
*in2_src
;
1532 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1533 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1534 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1535 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1538 for (i
= 0; i
< 4; ++i
)
1539 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1540 != in1_src
->sin6_addr
.s6_addr32
[i
]
1541 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1542 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1547 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1548 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1549 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1550 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1561 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1562 compare with the value indicating the order in which the entries
1563 have been received from the services. NB: no two entries can have
1564 the same order so the test will never return zero. */
1565 return idx1
< idx2
? -1 : 1;
1570 in6aicmp (const void *p1
, const void *p2
)
1572 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1573 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1575 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1579 /* Name of the config file for RFC 3484 sorting (for now). */
1580 #define GAICONF_FNAME "/etc/gai.conf"
1583 /* Non-zero if we are supposed to reload the config file automatically
1584 whenever it changed. */
1585 static int gaiconf_reload_flag
;
1587 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1588 static int gaiconf_reload_flag_ever_set
;
1590 /* Last modification time. */
1591 static struct timespec gaiconf_mtime
;
1594 libc_freeres_fn(fini
)
1596 if (labels
!= default_labels
)
1598 const struct prefixentry
*old
= labels
;
1599 labels
= default_labels
;
1600 free ((void *) old
);
1603 if (precedence
!= default_precedence
)
1605 const struct prefixentry
*old
= precedence
;
1606 precedence
= default_precedence
;
1607 free ((void *) old
);
1610 if (scopes
!= default_scopes
)
1612 const struct scopeentry
*old
= scopes
;
1613 scopes
= default_scopes
;
1614 free ((void *) old
);
1621 struct prefixentry entry
;
1622 struct prefixlist
*next
;
1628 struct scopeentry entry
;
1629 struct scopelist
*next
;
1634 free_prefixlist (struct prefixlist
*list
)
1636 while (list
!= NULL
)
1638 struct prefixlist
*oldp
= list
;
1646 free_scopelist (struct scopelist
*list
)
1648 while (list
!= NULL
)
1650 struct scopelist
*oldp
= list
;
1658 prefixcmp (const void *p1
, const void *p2
)
1660 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1661 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1663 if (e1
->bits
< e2
->bits
)
1665 if (e1
->bits
== e2
->bits
)
1672 scopecmp (const void *p1
, const void *p2
)
1674 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1675 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1677 if (e1
->netmask
> e2
->netmask
)
1679 if (e1
->netmask
== e2
->netmask
)
1688 struct prefixlist
*labellist
= NULL
;
1689 size_t nlabellist
= 0;
1690 bool labellist_nullbits
= false;
1691 struct prefixlist
*precedencelist
= NULL
;
1692 size_t nprecedencelist
= 0;
1693 bool precedencelist_nullbits
= false;
1694 struct scopelist
*scopelist
= NULL
;
1695 size_t nscopelist
= 0;
1696 bool scopelist_nullbits
= false;
1698 FILE *fp
= fopen (GAICONF_FNAME
, "rc");
1702 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1711 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1713 while (!feof_unlocked (fp
))
1715 ssize_t n
= __getline (&line
, &linelen
, fp
);
1719 /* Handle comments. No escaping possible so this is easy. */
1720 char *cp
= strchr (line
, '#');
1725 while (isspace (*cp
))
1729 while (*cp
!= '\0' && !isspace (*cp
))
1731 size_t cmdlen
= cp
- cmd
;
1735 while (isspace (*cp
))
1739 while (*cp
!= '\0' && !isspace (*cp
))
1741 size_t val1len
= cp
- cmd
;
1743 /* We always need at least two values. */
1749 while (isspace (*cp
))
1753 while (*cp
!= '\0' && !isspace (*cp
))
1756 /* Ignore the rest of the line. */
1759 struct prefixlist
**listp
;
1765 if (strcmp (cmd
, "label") == 0)
1767 struct in6_addr prefix
;
1768 unsigned long int bits
;
1769 unsigned long int val
;
1774 nullbitsp
= &labellist_nullbits
;
1779 cp
= strchr (val1
, '/');
1782 if (inet_pton (AF_INET6
, val1
, &prefix
)
1784 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1788 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1793 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1801 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1802 newp
->entry
.bits
= bits
;
1803 newp
->entry
.val
= val
;
1804 newp
->next
= *listp
;
1807 *nullbitsp
|= bits
== 0;
1813 if (strcmp (cmd
, "reload") == 0)
1815 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1816 if (gaiconf_reload_flag
)
1817 gaiconf_reload_flag_ever_set
= 1;
1822 if (strcmp (cmd
, "scopev4") == 0)
1824 struct in6_addr prefix
;
1825 unsigned long int bits
;
1826 unsigned long int val
;
1831 cp
= strchr (val1
, '/');
1834 if (inet_pton (AF_INET6
, val1
, &prefix
))
1837 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1839 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1844 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1849 struct scopelist
*newp
;
1851 newp
= malloc (sizeof (*newp
));
1859 newp
->entry
.netmask
= htonl (bits
!= 96
1863 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
1864 & newp
->entry
.netmask
);
1865 newp
->entry
.scope
= val
;
1866 newp
->next
= scopelist
;
1869 scopelist_nullbits
|= bits
== 96;
1872 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
1874 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1878 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1890 if (strcmp (cmd
, "precedence") == 0)
1892 listp
= &precedencelist
;
1893 lenp
= &nprecedencelist
;
1894 nullbitsp
= &precedencelist_nullbits
;
1905 /* Create the array for the labels. */
1906 struct prefixentry
*new_labels
;
1909 if (!labellist_nullbits
)
1911 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
1912 if (new_labels
== NULL
)
1916 if (!labellist_nullbits
)
1919 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
1920 new_labels
[i
].bits
= 0;
1921 new_labels
[i
].val
= 1;
1924 struct prefixlist
*l
= labellist
;
1927 new_labels
[i
] = l
->entry
;
1930 free_prefixlist (labellist
);
1932 /* Sort the entries so that the most specific ones are at
1934 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
1937 new_labels
= (struct prefixentry
*) default_labels
;
1939 struct prefixentry
*new_precedence
;
1940 if (nprecedencelist
> 0)
1942 if (!precedencelist_nullbits
)
1944 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
1945 if (new_precedence
== NULL
)
1947 if (new_labels
!= default_labels
)
1952 int i
= nprecedencelist
;
1953 if (!precedencelist_nullbits
)
1956 memset (&new_precedence
[i
].prefix
, '\0',
1957 sizeof (struct in6_addr
));
1958 new_precedence
[i
].bits
= 0;
1959 new_precedence
[i
].val
= 40;
1962 struct prefixlist
*l
= precedencelist
;
1965 new_precedence
[i
] = l
->entry
;
1968 free_prefixlist (precedencelist
);
1970 /* Sort the entries so that the most specific ones are at
1972 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
1976 new_precedence
= (struct prefixentry
*) default_precedence
;
1978 struct scopeentry
*new_scopes
;
1981 if (!scopelist_nullbits
)
1983 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
1984 if (new_scopes
== NULL
)
1986 if (new_labels
!= default_labels
)
1988 if (new_precedence
!= default_precedence
)
1989 free (new_precedence
);
1994 if (!scopelist_nullbits
)
1997 new_scopes
[i
].addr32
= 0;
1998 new_scopes
[i
].netmask
= 0;
1999 new_scopes
[i
].scope
= 14;
2002 struct scopelist
*l
= scopelist
;
2005 new_scopes
[i
] = l
->entry
;
2008 free_scopelist (scopelist
);
2010 /* Sort the entries so that the most specific ones are at
2012 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2016 new_scopes
= (struct scopeentry
*) default_scopes
;
2018 /* Now we are ready to replace the values. */
2019 const struct prefixentry
*old
= labels
;
2020 labels
= new_labels
;
2021 if (old
!= default_labels
)
2022 free ((void *) old
);
2025 precedence
= new_precedence
;
2026 if (old
!= default_precedence
)
2027 free ((void *) old
);
2029 const struct scopeentry
*oldscope
= scopes
;
2030 scopes
= new_scopes
;
2031 if (oldscope
!= default_scopes
)
2032 free ((void *) oldscope
);
2034 gaiconf_mtime
= st
.st_mtim
;
2039 free_prefixlist (labellist
);
2040 free_prefixlist (precedencelist
);
2041 free_scopelist (scopelist
);
2043 /* If we previously read the file but it is gone now, free the
2044 old data and use the builtin one. Leave the reload flag
2052 gaiconf_reload (void)
2055 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2056 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2062 getaddrinfo (const char *name
, const char *service
,
2063 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2065 int i
= 0, last_i
= 0;
2067 struct addrinfo
*p
= NULL
;
2068 struct gaih_service gaih_service
, *pservice
;
2069 struct addrinfo local_hints
;
2071 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2074 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2077 if (name
== NULL
&& service
== NULL
)
2081 hints
= &default_hints
;
2084 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2086 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2087 |AI_IDN_USE_STD3_ASCII_RULES
2089 |AI_NUMERICSERV
|AI_ALL
))
2090 return EAI_BADFLAGS
;
2092 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2093 return EAI_BADFLAGS
;
2095 struct in6addrinfo
*in6ai
= NULL
;
2096 size_t in6ailen
= 0;
2097 bool seen_ipv4
= false;
2098 bool seen_ipv6
= false;
2099 /* We might need information about what interfaces are available.
2100 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2101 cannot cache the results since new interfaces could be added at
2103 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2105 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2107 /* Now make a decision on what we return, if anything. */
2108 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2110 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2111 narrow down the search. */
2112 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2114 local_hints
= *hints
;
2115 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2116 hints
= &local_hints
;
2119 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2120 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2122 /* We cannot possibly return a valid answer. */
2128 if (service
&& service
[0])
2131 gaih_service
.name
= service
;
2132 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2135 if (hints
->ai_flags
& AI_NUMERICSERV
)
2141 gaih_service
.num
= -1;
2144 pservice
= &gaih_service
;
2149 struct addrinfo
**end
= &p
;
2151 unsigned int naddrs
= 0;
2152 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2153 || hints
->ai_family
== AF_INET6
)
2155 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2161 return -(last_i
& GAIH_EAI
);
2165 end
= &((*end
)->ai_next
);
2177 /* Read the config file. */
2178 __libc_once_define (static, once
);
2179 __typeof (once
) old_once
= once
;
2180 __libc_once (once
, gaiconf_init
);
2181 /* Sort results according to RFC 3484. */
2182 struct sort_result results
[nresults
];
2183 size_t order
[nresults
];
2185 struct addrinfo
*last
= NULL
;
2186 char *canonname
= NULL
;
2188 /* If we have information about deprecated and temporary addresses
2189 sort the array now. */
2191 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2196 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2198 results
[i
].dest_addr
= q
;
2199 results
[i
].native
= -1;
2202 /* If we just looked up the address for a different
2203 protocol, reuse the result. */
2204 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2205 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2207 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2208 results
[i
- 1].source_addr_len
);
2209 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2210 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2211 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2212 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2213 results
[i
].index
= results
[i
- 1].index
;
2217 results
[i
].got_source_addr
= false;
2218 results
[i
].source_addr_flags
= 0;
2219 results
[i
].prefixlen
= 0;
2220 results
[i
].index
= 0xffffffffu
;
2222 /* We overwrite the type with SOCK_DGRAM since we do not
2223 want connect() to connect to the other side. If we
2224 cannot determine the source address remember this
2226 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2230 close_not_cancel_no_status (fd
);
2232 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2236 /* Reset the connection. */
2237 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2238 __connect (fd
, &sa
, sizeof (sa
));
2241 socklen_t sl
= sizeof (results
[i
].source_addr
);
2243 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2244 && __getsockname (fd
,
2245 (struct sockaddr
*) &results
[i
].source_addr
,
2248 results
[i
].source_addr_len
= sl
;
2249 results
[i
].got_source_addr
= true;
2253 /* See whether the source address is on the list of
2254 deprecated or temporary addresses. */
2255 struct in6addrinfo tmp
;
2257 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2259 struct sockaddr_in
*sinp
2260 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2263 tmp
.addr
[2] = htonl (0xffff);
2264 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2268 struct sockaddr_in6
*sin6p
2269 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2270 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2273 struct in6addrinfo
*found
2274 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2278 results
[i
].source_addr_flags
= found
->flags
;
2279 results
[i
].prefixlen
= found
->prefixlen
;
2280 results
[i
].index
= found
->index
;
2284 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2286 /* We have to convert the address. The socket is
2287 IPv6 and the request is for IPv4. */
2288 struct sockaddr_in6
*sin6
2289 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2290 struct sockaddr_in
*sin
2291 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2292 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2293 sin
->sin_family
= AF_INET
;
2294 /* We do not have to initialize sin_port since this
2295 fields has the same position and size in the IPv6
2297 assert (offsetof (struct sockaddr_in
, sin_port
)
2298 == offsetof (struct sockaddr_in6
, sin6_port
));
2299 assert (sizeof (sin
->sin_port
)
2300 == sizeof (sin6
->sin6_port
));
2301 memcpy (&sin
->sin_addr
,
2302 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2303 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2306 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2307 && q
->ai_family
== AF_INET
)
2308 /* This could mean IPv6 sockets are IPv6-only. */
2311 /* Just make sure that if we have to process the same
2312 address again we do not copy any memory. */
2313 results
[i
].source_addr_len
= 0;
2316 /* Remember the canonical name. */
2317 if (q
->ai_canonname
!= NULL
)
2319 assert (canonname
== NULL
);
2320 canonname
= q
->ai_canonname
;
2321 q
->ai_canonname
= NULL
;
2326 close_not_cancel_no_status (fd
);
2328 /* We got all the source addresses we can get, now sort using
2330 struct sort_result_combo src
2331 = { .results
= results
, .nresults
= nresults
};
2332 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2334 __libc_lock_define_initialized (static, lock
);
2336 __libc_lock_lock (lock
);
2337 if (old_once
&& gaiconf_reload_flag
)
2339 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2340 __libc_lock_unlock (lock
);
2343 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2345 /* Queue the results up as they come out of sorting. */
2346 q
= p
= results
[order
[0]].dest_addr
;
2347 for (i
= 1; i
< nresults
; ++i
)
2348 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2351 /* Fill in the canonical name into the new first entry. */
2352 p
->ai_canonname
= canonname
;
2363 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2365 libc_hidden_def (getaddrinfo
)
2367 static_link_warning (getaddrinfo
)
2370 freeaddrinfo (struct addrinfo
*ai
)
2378 free (p
->ai_canonname
);
2382 libc_hidden_def (freeaddrinfo
)