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>
51 #include <arpa/inet.h>
53 #include <netinet/in.h>
54 #include <sys/socket.h>
56 #include <sys/types.h>
58 #include <sys/utsname.h>
61 #include <bits/libc-lock.h>
62 #include <not-cancel.h>
63 #include <nscd/nscd-client.h>
64 #include <nscd/nscd_proto.h>
65 #include <resolv/res_hconf.h>
68 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
69 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
71 # include <libidn/idna.h>
82 struct gaih_servtuple
*next
;
88 static const struct gaih_servtuple nullserv
;
100 /* Values for `protoflag'. */
101 #define GAI_PROTO_NOSERVICE 1
102 #define GAI_PROTO_PROTOANY 2
104 static const struct gaih_typeproto gaih_inet_typeproto
[] =
106 { 0, 0, 0, false, "" },
107 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
108 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
109 #if defined SOCK_DCCP && defined IPPROTO_DCCP
110 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
112 #ifdef IPPROTO_UDPLITE
113 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
116 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
117 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
119 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
120 { 0, 0, 0, false, "" }
123 static const struct addrinfo default_hints
=
125 .ai_flags
= AI_DEFAULT
,
126 .ai_family
= PF_UNSPEC
,
131 .ai_canonname
= NULL
,
137 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
138 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
141 size_t tmpbuflen
= 1024;
148 tmpbuf
= __alloca (tmpbuflen
);
150 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
152 if (r
!= 0 || s
== NULL
)
163 st
->socktype
= tp
->socktype
;
164 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
165 ? req
->ai_protocol
: tp
->protocol
);
166 st
->port
= s
->s_port
;
171 #define gethosts(_family, _type) \
177 char *localcanon = NULL; \
181 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
182 &rc, &herrno, NULL, &localcanon)); \
183 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
185 if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
186 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
190 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
194 result = -EAI_MEMORY; \
195 goto free_and_return; \
198 malloc_tmpbuf = true; \
199 tmpbuflen = 2 * tmpbuflen; \
202 if (status == NSS_STATUS_SUCCESS && rc == 0) \
208 if (herrno == NETDB_INTERNAL) \
210 __set_h_errno (herrno); \
211 _res.options |= old_res_options & RES_USE_INET6; \
212 result = -EAI_SYSTEM; \
213 goto free_and_return; \
215 if (herrno == TRY_AGAIN) \
216 no_data = EAI_AGAIN; \
218 no_data = herrno == NO_DATA; \
220 else if (h != NULL) \
222 for (i = 0; h->h_addr_list[i]; i++) \
226 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
227 (*pat)->scopeid = 0; \
229 uint32_t *addr = (*pat)->addr; \
230 (*pat)->next = NULL; \
231 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
232 if (_family == AF_INET && req->ai_family == AF_INET6) \
234 (*pat)->family = AF_INET6; \
235 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
236 addr[2] = htonl (0xffff); \
242 (*pat)->family = _family; \
243 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
245 pat = &((*pat)->next); \
248 if (localcanon != NULL && canon == NULL) \
249 canon = strdupa (localcanon); \
251 if (_family == AF_INET6 && i > 0) \
257 typedef enum nss_status (*nss_gethostbyname4_r
)
258 (const char *name
, struct gaih_addrtuple
**pat
,
259 char *buffer
, size_t buflen
, int *errnop
,
260 int *h_errnop
, int32_t *ttlp
);
261 typedef enum nss_status (*nss_gethostbyname3_r
)
262 (const char *name
, int af
, struct hostent
*host
,
263 char *buffer
, size_t buflen
, int *errnop
,
264 int *h_errnop
, int32_t *ttlp
, char **canonp
);
265 typedef enum nss_status (*nss_getcanonname_r
)
266 (const char *name
, char *buffer
, size_t buflen
, char **result
,
267 int *errnop
, int *h_errnop
);
268 extern service_user
*__nss_hosts_database attribute_hidden
;
272 gaih_inet (const char *name
, const struct gaih_service
*service
,
273 const struct addrinfo
*req
, struct addrinfo
**pai
,
274 unsigned int *naddrs
)
276 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
277 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
278 struct gaih_addrtuple
*at
= NULL
;
280 bool got_ipv6
= false;
281 const char *canon
= NULL
;
282 const char *orig_name
= name
;
283 size_t alloca_used
= 0;
285 if (req
->ai_protocol
|| req
->ai_socktype
)
290 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
291 || (req
->ai_protocol
!= 0
292 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
293 && req
->ai_protocol
!= tp
->protocol
)))
298 if (req
->ai_socktype
)
299 return -EAI_SOCKTYPE
;
308 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
311 if (service
->num
< 0)
315 st
= (struct gaih_servtuple
*)
316 alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
318 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
323 struct gaih_servtuple
**pst
= &st
;
324 for (tp
++; tp
->name
[0]; tp
++)
326 struct gaih_servtuple
*newp
;
328 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
331 if (req
->ai_socktype
!= 0
332 && req
->ai_socktype
!= tp
->socktype
)
334 if (req
->ai_protocol
!= 0
335 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
336 && req
->ai_protocol
!= tp
->protocol
)
339 newp
= (struct gaih_servtuple
*)
340 alloca_account (sizeof (struct gaih_servtuple
),
343 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
353 if (st
== (struct gaih_servtuple
*) &nullserv
)
359 port
= htons (service
->num
);
367 if (req
->ai_socktype
|| req
->ai_protocol
)
369 st
= alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
371 st
->socktype
= tp
->socktype
;
372 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
373 ? req
->ai_protocol
: tp
->protocol
);
378 /* Neither socket type nor protocol is set. Return all socket types
380 struct gaih_servtuple
**lastp
= &st
;
381 for (++tp
; tp
->name
[0]; ++tp
)
384 struct gaih_servtuple
*newp
;
386 newp
= alloca_account (sizeof (struct gaih_servtuple
),
389 newp
->socktype
= tp
->socktype
;
390 newp
->protocol
= tp
->protocol
;
399 bool malloc_name
= false;
400 bool malloc_addrmem
= false;
401 struct gaih_addrtuple
*addrmem
= NULL
;
402 bool malloc_canonbuf
= false;
403 char *canonbuf
= NULL
;
404 bool malloc_tmpbuf
= false;
409 at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
410 at
->family
= AF_UNSPEC
;
415 if (req
->ai_flags
& AI_IDN
)
418 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
419 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
420 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
421 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
424 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
425 if (rc
!= IDNA_SUCCESS
)
427 /* No need to jump to free_and_return here. */
428 if (rc
== IDNA_MALLOC_ERROR
)
430 if (rc
== IDNA_DLOPEN_ERROR
)
432 return -EAI_IDN_ENCODE
;
434 /* In case the output string is the same as the input string
435 no new string has been allocated. */
444 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
446 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
447 at
->family
= AF_INET
;
448 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
450 at
->addr
[3] = at
->addr
[0];
451 at
->addr
[2] = htonl (0xffff);
454 at
->family
= AF_INET6
;
458 result
= -EAI_ADDRFAMILY
;
459 goto free_and_return
;
462 if (req
->ai_flags
& AI_CANONNAME
)
465 else if (at
->family
== AF_UNSPEC
)
467 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
471 bool malloc_namebuf
= false;
472 char *namebuf
= (char *) name
;
474 if (__builtin_expect (scope_delim
!= NULL
, 0))
480 if (__libc_use_alloca (alloca_used
481 + scope_delim
- name
+ 1))
483 namebuf
= alloca_account (scope_delim
- name
+ 1,
485 *((char *) __mempcpy (namebuf
, name
,
486 scope_delim
- name
)) = '\0';
490 namebuf
= strndup (name
, scope_delim
- name
);
493 assert (!malloc_name
);
496 malloc_namebuf
= true;
501 e
= inet_pton (AF_INET6
, namebuf
, at
->addr
);
505 else if (scope_delim
!= NULL
&& malloc_name
)
506 /* Undo what we did above. */
507 *scope_delim
= SCOPE_DELIMITER
;
511 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
512 at
->family
= AF_INET6
;
513 else if (req
->ai_family
== AF_INET
514 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
516 at
->addr
[0] = at
->addr
[3];
517 at
->family
= AF_INET
;
521 result
= -EAI_ADDRFAMILY
;
522 goto free_and_return
;
525 if (scope_delim
!= NULL
)
527 int try_numericscope
= 0;
528 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
529 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
531 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
532 if (at
->scopeid
== 0)
533 try_numericscope
= 1;
536 try_numericscope
= 1;
538 if (try_numericscope
!= 0)
541 assert (sizeof (uint32_t) <= sizeof (unsigned long));
542 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
546 result
= -EAI_NONAME
;
547 goto free_and_return
;
552 if (req
->ai_flags
& AI_CANONNAME
)
557 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
559 struct gaih_addrtuple
**pat
= &at
;
561 int no_inet6_data
= 0;
563 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
564 enum nss_status status
= NSS_STATUS_UNAVAIL
;
568 /* If we do not have to look for IPv6 addresses or the canonical
569 name, use the simple, old functions, which do not support
570 IPv6 scope ids, nor retrieving the canonical name. */
571 if (req
->ai_family
== AF_INET
572 && (req
->ai_flags
& AI_CANONNAME
) == 0)
574 /* Allocate additional room for struct host_data. */
575 size_t tmpbuflen
= (512 + MAX_NR_ALIASES
* sizeof(char*)
576 + 16 * sizeof(char));
577 assert (tmpbuf
== NULL
);
578 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
586 rc
= __gethostbyname2_r (name
, AF_INET
, &th
, tmpbuf
,
587 tmpbuflen
, &h
, &herrno
);
588 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
592 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
593 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
598 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
602 result
= -EAI_MEMORY
;
603 goto free_and_return
;
606 malloc_tmpbuf
= true;
607 tmpbuflen
= 2 * tmpbuflen
;
616 /* We found data, count the number of addresses. */
617 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
619 if (i
> 0 && *pat
!= NULL
)
622 if (__libc_use_alloca (alloca_used
623 + i
* sizeof (struct gaih_addrtuple
)))
624 addrmem
= alloca_account (i
* sizeof (struct gaih_addrtuple
),
629 * sizeof (struct gaih_addrtuple
));
632 result
= -EAI_MEMORY
;
633 goto free_and_return
;
635 malloc_addrmem
= true;
638 /* Now convert it into the list. */
639 struct gaih_addrtuple
*addrfree
= addrmem
;
640 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
648 (*pat
)->family
= AF_INET
;
649 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
651 pat
= &((*pat
)->next
);
657 if (herrno
== NETDB_INTERNAL
)
659 __set_h_errno (herrno
);
660 result
= -EAI_SYSTEM
;
662 else if (herrno
== TRY_AGAIN
)
665 /* We made requests but they turned out no data.
666 The name is known, though. */
667 result
= -EAI_NODATA
;
669 goto free_and_return
;
676 if (__nss_not_use_nscd_hosts
> 0
677 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
678 __nss_not_use_nscd_hosts
= 0;
680 if (!__nss_not_use_nscd_hosts
681 && !__nss_database_custom
[NSS_DBSIDX_hosts
])
683 /* Try to use nscd. */
684 struct nscd_ai_result
*air
= NULL
;
686 int err
= __nscd_getai (name
, &air
, &herrno
);
689 /* Transform into gaih_addrtuple list. */
690 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
691 char *addrs
= air
->addrs
;
693 if (__libc_use_alloca (alloca_used
694 + air
->naddrs
* sizeof (struct gaih_addrtuple
)))
695 addrmem
= alloca_account (air
->naddrs
696 * sizeof (struct gaih_addrtuple
),
700 addrmem
= malloc (air
->naddrs
701 * sizeof (struct gaih_addrtuple
));
704 result
= -EAI_MEMORY
;
705 goto free_and_return
;
707 malloc_addrmem
= true;
710 struct gaih_addrtuple
*addrfree
= addrmem
;
711 for (int i
= 0; i
< air
->naddrs
; ++i
)
713 socklen_t size
= (air
->family
[i
] == AF_INET
714 ? INADDRSZ
: IN6ADDRSZ
);
720 uint32_t *pataddr
= (*pat
)->addr
;
722 if (added_canon
|| air
->canon
== NULL
)
724 else if (canonbuf
== NULL
)
726 size_t canonlen
= strlen (air
->canon
) + 1;
727 if ((req
->ai_flags
& AI_CANONIDN
) != 0
728 && __libc_use_alloca (alloca_used
+ canonlen
))
729 canonbuf
= alloca_account (canonlen
, alloca_used
);
732 canonbuf
= malloc (canonlen
);
733 if (canonbuf
== NULL
)
735 result
= -EAI_MEMORY
;
736 goto free_and_return
;
738 malloc_canonbuf
= true;
740 canon
= (*pat
)->name
= memcpy (canonbuf
, air
->canon
,
744 if (air
->family
[i
] == AF_INET
745 && req
->ai_family
== AF_INET6
746 && (req
->ai_flags
& AI_V4MAPPED
))
748 (*pat
)->family
= AF_INET6
;
749 pataddr
[3] = *(uint32_t *) addrs
;
750 pataddr
[2] = htonl (0xffff);
753 pat
= &((*pat
)->next
);
756 else if (req
->ai_family
== AF_UNSPEC
757 || air
->family
[i
] == req
->ai_family
)
759 (*pat
)->family
= air
->family
[i
];
760 memcpy (pataddr
, addrs
, size
);
761 pat
= &((*pat
)->next
);
763 if (air
->family
[i
] == AF_INET6
)
771 if (at
->family
== AF_UNSPEC
)
773 result
= -EAI_NONAME
;
774 goto free_and_return
;
780 /* The database contains a negative entry. */
781 goto free_and_return
;
782 else if (__nss_not_use_nscd_hosts
== 0)
784 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
785 result
= -EAI_MEMORY
;
786 else if (herrno
== TRY_AGAIN
)
789 result
= -EAI_SYSTEM
;
791 goto free_and_return
;
796 if (__nss_hosts_database
== NULL
)
797 no_more
= __nss_database_lookup ("hosts", NULL
,
798 "dns [!UNAVAIL=return] files",
799 &__nss_hosts_database
);
802 nip
= __nss_hosts_database
;
804 /* Initialize configurations. */
805 if (__glibc_unlikely (!_res_hconf
.initialized
))
807 if (__res_maybe_init (&_res
, 0) == -1)
810 /* If we are looking for both IPv4 and IPv6 address we don't
811 want the lookup functions to automatically promote IPv4
812 addresses to IPv6 addresses. Currently this is decided
813 by setting the RES_USE_INET6 bit in _res.options. */
814 old_res_options
= _res
.options
;
815 _res
.options
&= ~RES_USE_INET6
;
817 size_t tmpbuflen
= 1024 + sizeof(struct gaih_addrtuple
);
818 malloc_tmpbuf
= !__libc_use_alloca (alloca_used
+ tmpbuflen
);
819 assert (tmpbuf
== NULL
);
821 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
824 tmpbuf
= malloc (tmpbuflen
);
827 _res
.options
|= old_res_options
& RES_USE_INET6
;
828 result
= -EAI_MEMORY
;
829 goto free_and_return
;
836 nss_gethostbyname4_r fct4
= NULL
;
838 /* gethostbyname4_r sends out parallel A and AAAA queries and
839 is thus only suitable for PF_UNSPEC. */
840 if (req
->ai_family
== PF_UNSPEC
)
841 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
850 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
851 tmpbuflen
, &rc
, &herrno
,
853 if (status
== NSS_STATUS_SUCCESS
)
855 if (status
!= NSS_STATUS_TRYAGAIN
856 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
858 if (status
== NSS_STATUS_TRYAGAIN
859 && herrno
== TRY_AGAIN
)
862 no_data
= herrno
== NO_DATA
;
867 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
868 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
873 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
877 _res
.options
|= old_res_options
& RES_USE_INET6
;
878 result
= -EAI_MEMORY
;
879 goto free_and_return
;
882 malloc_tmpbuf
= true;
883 tmpbuflen
= 2 * tmpbuflen
;
887 if (status
== NSS_STATUS_SUCCESS
)
892 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
893 canon
= (*pat
)->name
;
897 if ((*pat
)->family
== AF_INET
898 && req
->ai_family
== AF_INET6
899 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
901 uint32_t *pataddr
= (*pat
)->addr
;
902 (*pat
)->family
= AF_INET6
;
903 pataddr
[3] = pataddr
[0];
904 pataddr
[2] = htonl (0xffff);
907 pat
= &((*pat
)->next
);
910 else if (req
->ai_family
== AF_UNSPEC
911 || (*pat
)->family
== req
->ai_family
)
913 pat
= &((*pat
)->next
);
916 if (req
->ai_family
== AF_INET6
)
920 *pat
= ((*pat
)->next
);
924 no_inet6_data
= no_data
;
928 nss_gethostbyname3_r fct
= NULL
;
929 if (req
->ai_flags
& AI_CANONNAME
)
930 /* No need to use this function if we do not look for
931 the canonical name. The function does not exist in
932 all NSS modules and therefore the lookup would
934 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
936 /* We are cheating here. The gethostbyname2_r
937 function does not have the same interface as
938 gethostbyname3_r but the extra arguments the
939 latter takes are added at the end. So the
940 gethostbyname2_r code will just ignore them. */
941 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
945 if (req
->ai_family
== AF_INET6
946 || req
->ai_family
== AF_UNSPEC
)
948 gethosts (AF_INET6
, struct in6_addr
);
949 no_inet6_data
= no_data
;
950 inet6_status
= status
;
952 if (req
->ai_family
== AF_INET
953 || req
->ai_family
== AF_UNSPEC
954 || (req
->ai_family
== AF_INET6
955 && (req
->ai_flags
& AI_V4MAPPED
)
956 /* Avoid generating the mapped addresses if we
957 know we are not going to need them. */
958 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
960 gethosts (AF_INET
, struct in_addr
);
962 if (req
->ai_family
== AF_INET
)
964 no_inet6_data
= no_data
;
965 inet6_status
= status
;
969 /* If we found one address for AF_INET or AF_INET6,
970 don't continue the search. */
971 if (inet6_status
== NSS_STATUS_SUCCESS
972 || status
== NSS_STATUS_SUCCESS
)
974 if ((req
->ai_flags
& AI_CANONNAME
) != 0
977 /* If we need the canonical name, get it
978 from the same service as the result. */
979 nss_getcanonname_r cfct
;
982 cfct
= __nss_lookup_function (nip
,
986 const size_t max_fqdn_len
= 256;
987 if ((req
->ai_flags
& AI_CANONIDN
) != 0
988 && __libc_use_alloca (alloca_used
990 canonbuf
= alloca_account (max_fqdn_len
,
994 canonbuf
= malloc (max_fqdn_len
);
995 if (canonbuf
== NULL
)
998 |= old_res_options
& RES_USE_INET6
;
999 result
= -EAI_MEMORY
;
1000 goto free_and_return
;
1002 malloc_canonbuf
= true;
1006 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
1010 == NSS_STATUS_SUCCESS
)
1014 /* If the canonical name cannot be
1015 determined, use the passed in
1017 if (malloc_canonbuf
)
1020 malloc_canonbuf
= false;
1026 status
= NSS_STATUS_SUCCESS
;
1030 /* We can have different states for AF_INET and
1031 AF_INET6. Try to find a useful one for both. */
1032 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
1033 status
= NSS_STATUS_TRYAGAIN
;
1034 else if (status
== NSS_STATUS_UNAVAIL
1035 && inet6_status
!= NSS_STATUS_UNAVAIL
)
1036 status
= inet6_status
;
1041 status
= NSS_STATUS_UNAVAIL
;
1042 /* Could not load any of the lookup functions. Indicate
1043 an internal error if the failure was due to a system
1044 error other than the file not being found. We use the
1045 errno from the last failed callback. */
1046 if (errno
!= 0 && errno
!= ENOENT
)
1047 __set_h_errno (NETDB_INTERNAL
);
1051 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
1054 if (nip
->next
== NULL
)
1060 _res
.options
|= old_res_options
& RES_USE_INET6
;
1062 if (h_errno
== NETDB_INTERNAL
)
1064 result
= -EAI_SYSTEM
;
1065 goto free_and_return
;
1068 if (no_data
!= 0 && no_inet6_data
!= 0)
1070 /* If both requests timed out report this. */
1071 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
1072 result
= -EAI_AGAIN
;
1074 /* We made requests but they turned out no data. The name
1075 is known, though. */
1076 result
= -EAI_NODATA
;
1078 goto free_and_return
;
1083 if (at
->family
== AF_UNSPEC
)
1085 result
= -EAI_NONAME
;
1086 goto free_and_return
;
1091 struct gaih_addrtuple
*atr
;
1092 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
1093 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
1095 if (req
->ai_family
== AF_UNSPEC
)
1097 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
1098 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1101 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1103 at
->family
= AF_INET6
;
1104 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1105 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1109 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1111 atr
->family
= AF_INET
;
1112 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1113 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1118 struct gaih_servtuple
*st2
;
1119 struct gaih_addrtuple
*at2
= at
;
1124 buffer is the size of an unformatted IPv6 address in printable format.
1128 /* Only the first entry gets the canonical name. */
1129 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1132 /* If the canonical name cannot be determined, use
1133 the passed in string. */
1137 if (req
->ai_flags
& AI_CANONIDN
)
1140 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1141 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1142 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1143 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1146 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1147 if (rc
!= IDNA_SUCCESS
)
1149 if (rc
== IDNA_MALLOC_ERROR
)
1150 result
= -EAI_MEMORY
;
1151 else if (rc
== IDNA_DLOPEN_ERROR
)
1152 result
= -EAI_SYSTEM
;
1154 result
= -EAI_IDN_ENCODE
;
1155 goto free_and_return
;
1157 /* In case the output string is the same as the input
1158 string no new string has been allocated and we
1170 if (malloc_canonbuf
)
1171 /* We already allocated the string using malloc. */
1172 malloc_canonbuf
= false;
1175 canon
= strdup (canon
);
1178 result
= -EAI_MEMORY
;
1179 goto free_and_return
;
1185 family
= at2
->family
;
1186 if (family
== AF_INET6
)
1188 socklen
= sizeof (struct sockaddr_in6
);
1190 /* If we looked up IPv4 mapped address discard them here if
1191 the caller isn't interested in all address and we have
1192 found at least one IPv6 address. */
1194 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1195 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1199 socklen
= sizeof (struct sockaddr_in
);
1201 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1203 struct addrinfo
*ai
;
1204 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1207 free ((char *) canon
);
1208 result
= -EAI_MEMORY
;
1209 goto free_and_return
;
1212 ai
->ai_flags
= req
->ai_flags
;
1213 ai
->ai_family
= family
;
1214 ai
->ai_socktype
= st2
->socktype
;
1215 ai
->ai_protocol
= st2
->protocol
;
1216 ai
->ai_addrlen
= socklen
;
1217 ai
->ai_addr
= (void *) (ai
+ 1);
1219 /* We only add the canonical name once. */
1220 ai
->ai_canonname
= (char *) canon
;
1224 ai
->ai_addr
->sa_len
= socklen
;
1225 #endif /* _HAVE_SA_LEN */
1226 ai
->ai_addr
->sa_family
= family
;
1228 /* In case of an allocation error the list must be NULL
1232 if (family
== AF_INET6
)
1234 struct sockaddr_in6
*sin6p
=
1235 (struct sockaddr_in6
*) ai
->ai_addr
;
1237 sin6p
->sin6_port
= st2
->port
;
1238 sin6p
->sin6_flowinfo
= 0;
1239 memcpy (&sin6p
->sin6_addr
,
1240 at2
->addr
, sizeof (struct in6_addr
));
1241 sin6p
->sin6_scope_id
= at2
->scopeid
;
1245 struct sockaddr_in
*sinp
=
1246 (struct sockaddr_in
*) ai
->ai_addr
;
1247 sinp
->sin_port
= st2
->port
;
1248 memcpy (&sinp
->sin_addr
,
1249 at2
->addr
, sizeof (struct in_addr
));
1250 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1253 pai
= &(ai
->ai_next
);
1265 free ((char *) name
);
1268 if (malloc_canonbuf
)
1279 struct addrinfo
*dest_addr
;
1280 /* Using sockaddr_storage is for now overkill. We only support IPv4
1281 and IPv6 so far. If this changes at some point we can adjust the
1283 struct sockaddr_in6 source_addr
;
1284 uint8_t source_addr_len
;
1285 bool got_source_addr
;
1286 uint8_t source_addr_flags
;
1292 struct sort_result_combo
1294 struct sort_result
*results
;
1299 #if __BYTE_ORDER == __BIG_ENDIAN
1300 # define htonl_c(n) n
1302 # define htonl_c(n) __bswap_constant_32 (n)
1305 static const struct scopeentry
1314 } default_scopes
[] =
1316 /* Link-local addresses: scope 2. */
1317 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1318 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1319 /* Default: scope 14. */
1320 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1323 /* The label table. */
1324 static const struct scopeentry
*scopes
;
1328 get_scope (const struct sockaddr_in6
*in6
)
1331 if (in6
->sin6_family
== PF_INET6
)
1333 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1335 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1336 /* RFC 4291 2.5.3 says that the loopback address is to be
1337 treated like a link-local address. */
1338 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1340 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1343 /* XXX Is this the correct default behavior? */
1347 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1349 else if (in6
->sin6_family
== PF_INET
)
1351 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1356 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1357 == scopes
[cnt
].addr32
)
1358 return scopes
[cnt
].scope
;
1365 /* XXX What is a good default? */
1374 struct in6_addr prefix
;
1380 /* The label table. */
1381 static const struct prefixentry
*labels
;
1383 /* Default labels. */
1384 static const struct prefixentry default_labels
[] =
1386 /* See RFC 3484 for the details. */
1388 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1392 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1396 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1400 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1401 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1403 /* The next two entries differ from RFC 3484. We need to treat
1404 IPv6 site-local addresses special because they are never NATed,
1405 unlike site-locale IPv4 addresses. If this would not happen, on
1406 machines which have only IPv4 and IPv6 site-local addresses, the
1407 sorting would prefer the IPv6 site-local addresses, causing
1408 unnecessary delays when trying to connect to a global IPv6 address
1409 through a site-local IPv6 address. */
1411 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1415 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1418 /* Additional rule for Teredo tunnels. */
1420 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1424 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1430 /* The precedence table. */
1431 static const struct prefixentry
*precedence
;
1433 /* The default precedences. */
1434 static const struct prefixentry default_precedence
[] =
1436 /* See RFC 3484 for the details. */
1438 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1442 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1446 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1450 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1451 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1454 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1461 match_prefix (const struct sockaddr_in6
*in6
,
1462 const struct prefixentry
*list
, int default_val
)
1465 struct sockaddr_in6 in6_mem
;
1467 if (in6
->sin6_family
== PF_INET
)
1469 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1471 /* Construct a V4-to-6 mapped address. */
1472 in6_mem
.sin6_family
= PF_INET6
;
1473 in6_mem
.sin6_port
= in
->sin_port
;
1474 in6_mem
.sin6_flowinfo
= 0;
1475 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1476 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1477 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1478 in6_mem
.sin6_scope_id
= 0;
1482 else if (in6
->sin6_family
!= PF_INET6
)
1485 for (idx
= 0; ; ++idx
)
1487 unsigned int bits
= list
[idx
].bits
;
1488 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1489 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1503 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1509 return list
[idx
].val
;
1514 get_label (const struct sockaddr_in6
*in6
)
1516 /* XXX What is a good default value? */
1517 return match_prefix (in6
, labels
, INT_MAX
);
1522 get_precedence (const struct sockaddr_in6
*in6
)
1524 /* XXX What is a good default value? */
1525 return match_prefix (in6
, precedence
, 0);
1529 /* Find last bit set in a word. */
1535 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1536 if ((a
& mask
) != 0)
1543 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1545 const size_t idx1
= *(const size_t *) p1
;
1546 const size_t idx2
= *(const size_t *) p2
;
1547 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1548 struct sort_result
*a1
= &src
->results
[idx1
];
1549 struct sort_result
*a2
= &src
->results
[idx2
];
1551 /* Rule 1: Avoid unusable destinations.
1552 We have the got_source_addr flag set if the destination is reachable. */
1553 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1555 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1559 /* Rule 2: Prefer matching scope. Only interesting if both
1560 destination addresses are IPv6. */
1562 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1565 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1567 if (a1
->got_source_addr
)
1569 int a1_src_scope
= get_scope (&a1
->source_addr
);
1570 int a2_src_scope
= get_scope (&a2
->source_addr
);
1572 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1574 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1579 /* Rule 3: Avoid deprecated addresses. */
1580 if (a1
->got_source_addr
)
1582 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1583 && (a2
->source_addr_flags
& in6ai_deprecated
))
1585 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1586 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1590 /* Rule 4: Prefer home addresses. */
1591 if (a1
->got_source_addr
)
1593 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1594 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1596 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1597 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1601 /* Rule 5: Prefer matching label. */
1602 if (a1
->got_source_addr
)
1605 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1606 int a1_src_label
= get_label (&a1
->source_addr
);
1609 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1610 int a2_src_label
= get_label (&a2
->source_addr
);
1612 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1614 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1619 /* Rule 6: Prefer higher precedence. */
1621 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1623 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1625 if (a1_prec
> a2_prec
)
1627 if (a1_prec
< a2_prec
)
1631 /* Rule 7: Prefer native transport. */
1632 if (a1
->got_source_addr
)
1634 /* The same interface index means the same interface which means
1635 there is no difference in transport. This should catch many
1637 if (a1
->index
!= a2
->index
)
1639 int a1_native
= a1
->native
;
1640 int a2_native
= a2
->native
;
1642 if (a1_native
== -1 || a2_native
== -1)
1645 if (a1_native
== -1)
1647 /* If we do not have the information use 'native' as
1650 a1_index
= a1
->index
;
1653 a1_index
= 0xffffffffu
;
1656 if (a2_native
== -1)
1658 /* If we do not have the information use 'native' as
1661 a2_index
= a2
->index
;
1664 a2_index
= 0xffffffffu
;
1666 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1668 /* Fill in the results in all the records. */
1669 for (int i
= 0; i
< src
->nresults
; ++i
)
1670 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1672 assert (src
->results
[i
].native
== -1
1673 || src
->results
[i
].native
== a1_native
);
1674 src
->results
[i
].native
= a1_native
;
1676 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1678 assert (src
->results
[i
].native
== -1
1679 || src
->results
[i
].native
== a2_native
);
1680 src
->results
[i
].native
= a2_native
;
1684 if (a1_native
&& !a2_native
)
1686 if (!a1_native
&& a2_native
)
1692 /* Rule 8: Prefer smaller scope. */
1693 if (a1_dst_scope
< a2_dst_scope
)
1695 if (a1_dst_scope
> a2_dst_scope
)
1699 /* Rule 9: Use longest matching prefix. */
1700 if (a1
->got_source_addr
1701 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1706 if (a1
->dest_addr
->ai_family
== PF_INET
)
1708 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1709 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1711 /* Outside of subnets, as defined by the network masks,
1712 common address prefixes for IPv4 addresses make no sense.
1713 So, define a non-zero value only if source and
1714 destination address are on the same subnet. */
1715 struct sockaddr_in
*in1_dst
1716 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1717 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1718 struct sockaddr_in
*in1_src
1719 = (struct sockaddr_in
*) &a1
->source_addr
;
1720 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1721 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1723 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1724 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1726 struct sockaddr_in
*in2_dst
1727 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1728 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1729 struct sockaddr_in
*in2_src
1730 = (struct sockaddr_in
*) &a2
->source_addr
;
1731 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1732 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1734 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1735 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1737 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1739 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1740 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1742 struct sockaddr_in6
*in1_dst
;
1743 struct sockaddr_in6
*in1_src
;
1744 struct sockaddr_in6
*in2_dst
;
1745 struct sockaddr_in6
*in2_src
;
1747 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1748 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1749 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1750 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1753 for (i
= 0; i
< 4; ++i
)
1754 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1755 != in1_src
->sin6_addr
.s6_addr32
[i
]
1756 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1757 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1762 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1763 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1764 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1765 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1776 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1777 compare with the value indicating the order in which the entries
1778 have been received from the services. NB: no two entries can have
1779 the same order so the test will never return zero. */
1780 return idx1
< idx2
? -1 : 1;
1785 in6aicmp (const void *p1
, const void *p2
)
1787 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1788 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1790 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1794 /* Name of the config file for RFC 3484 sorting (for now). */
1795 #define GAICONF_FNAME "/etc/gai.conf"
1798 /* Non-zero if we are supposed to reload the config file automatically
1799 whenever it changed. */
1800 static int gaiconf_reload_flag
;
1802 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1803 static int gaiconf_reload_flag_ever_set
;
1805 /* Last modification time. */
1806 #ifdef _STATBUF_ST_NSEC
1808 static struct timespec gaiconf_mtime
;
1811 save_gaiconf_mtime (const struct stat64
*st
)
1813 gaiconf_mtime
= st
->st_mtim
;
1817 check_gaiconf_mtime (const struct stat64
*st
)
1819 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1820 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1825 static time_t gaiconf_mtime
;
1828 save_gaiconf_mtime (const struct stat64
*st
)
1830 gaiconf_mtime
= st
->st_mtime
;
1834 check_gaiconf_mtime (const struct stat64
*st
)
1836 return st
->st_mtime
== gaiconf_mtime
;
1842 libc_freeres_fn(fini
)
1844 if (labels
!= default_labels
)
1846 const struct prefixentry
*old
= labels
;
1847 labels
= default_labels
;
1848 free ((void *) old
);
1851 if (precedence
!= default_precedence
)
1853 const struct prefixentry
*old
= precedence
;
1854 precedence
= default_precedence
;
1855 free ((void *) old
);
1858 if (scopes
!= default_scopes
)
1860 const struct scopeentry
*old
= scopes
;
1861 scopes
= default_scopes
;
1862 free ((void *) old
);
1869 struct prefixentry entry
;
1870 struct prefixlist
*next
;
1876 struct scopeentry entry
;
1877 struct scopelist
*next
;
1882 free_prefixlist (struct prefixlist
*list
)
1884 while (list
!= NULL
)
1886 struct prefixlist
*oldp
= list
;
1894 free_scopelist (struct scopelist
*list
)
1896 while (list
!= NULL
)
1898 struct scopelist
*oldp
= list
;
1906 prefixcmp (const void *p1
, const void *p2
)
1908 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1909 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1911 if (e1
->bits
< e2
->bits
)
1913 if (e1
->bits
== e2
->bits
)
1920 scopecmp (const void *p1
, const void *p2
)
1922 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1923 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1925 if (e1
->netmask
> e2
->netmask
)
1927 if (e1
->netmask
== e2
->netmask
)
1936 struct prefixlist
*labellist
= NULL
;
1937 size_t nlabellist
= 0;
1938 bool labellist_nullbits
= false;
1939 struct prefixlist
*precedencelist
= NULL
;
1940 size_t nprecedencelist
= 0;
1941 bool precedencelist_nullbits
= false;
1942 struct scopelist
*scopelist
= NULL
;
1943 size_t nscopelist
= 0;
1944 bool scopelist_nullbits
= false;
1946 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1950 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1959 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1961 while (!feof_unlocked (fp
))
1963 ssize_t n
= __getline (&line
, &linelen
, fp
);
1967 /* Handle comments. No escaping possible so this is easy. */
1968 char *cp
= strchr (line
, '#');
1973 while (isspace (*cp
))
1977 while (*cp
!= '\0' && !isspace (*cp
))
1979 size_t cmdlen
= cp
- cmd
;
1983 while (isspace (*cp
))
1987 while (*cp
!= '\0' && !isspace (*cp
))
1989 size_t val1len
= cp
- cmd
;
1991 /* We always need at least two values. */
1997 while (isspace (*cp
))
2001 while (*cp
!= '\0' && !isspace (*cp
))
2004 /* Ignore the rest of the line. */
2007 struct prefixlist
**listp
;
2013 if (strcmp (cmd
, "label") == 0)
2015 struct in6_addr prefix
;
2016 unsigned long int bits
;
2017 unsigned long int val
;
2022 nullbitsp
= &labellist_nullbits
;
2027 cp
= strchr (val1
, '/');
2030 if (inet_pton (AF_INET6
, val1
, &prefix
)
2032 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2036 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2041 struct prefixlist
*newp
= malloc (sizeof (*newp
));
2049 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
2050 newp
->entry
.bits
= bits
;
2051 newp
->entry
.val
= val
;
2052 newp
->next
= *listp
;
2055 *nullbitsp
|= bits
== 0;
2061 if (strcmp (cmd
, "reload") == 0)
2063 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2064 if (gaiconf_reload_flag
)
2065 gaiconf_reload_flag_ever_set
= 1;
2070 if (strcmp (cmd
, "scopev4") == 0)
2072 struct in6_addr prefix
;
2073 unsigned long int bits
;
2074 unsigned long int val
;
2079 cp
= strchr (val1
, '/');
2082 if (inet_pton (AF_INET6
, val1
, &prefix
))
2085 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2087 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2092 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2097 struct scopelist
*newp
;
2099 newp
= malloc (sizeof (*newp
));
2107 newp
->entry
.netmask
= htonl (bits
!= 96
2111 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2112 & newp
->entry
.netmask
);
2113 newp
->entry
.scope
= val
;
2114 newp
->next
= scopelist
;
2117 scopelist_nullbits
|= bits
== 96;
2120 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2122 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2126 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2138 if (strcmp (cmd
, "precedence") == 0)
2140 listp
= &precedencelist
;
2141 lenp
= &nprecedencelist
;
2142 nullbitsp
= &precedencelist_nullbits
;
2153 /* Create the array for the labels. */
2154 struct prefixentry
*new_labels
;
2157 if (!labellist_nullbits
)
2159 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2160 if (new_labels
== NULL
)
2164 if (!labellist_nullbits
)
2167 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2168 new_labels
[i
].bits
= 0;
2169 new_labels
[i
].val
= 1;
2172 struct prefixlist
*l
= labellist
;
2175 new_labels
[i
] = l
->entry
;
2178 free_prefixlist (labellist
);
2180 /* Sort the entries so that the most specific ones are at
2182 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2185 new_labels
= (struct prefixentry
*) default_labels
;
2187 struct prefixentry
*new_precedence
;
2188 if (nprecedencelist
> 0)
2190 if (!precedencelist_nullbits
)
2192 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2193 if (new_precedence
== NULL
)
2195 if (new_labels
!= default_labels
)
2200 int i
= nprecedencelist
;
2201 if (!precedencelist_nullbits
)
2204 memset (&new_precedence
[i
].prefix
, '\0',
2205 sizeof (struct in6_addr
));
2206 new_precedence
[i
].bits
= 0;
2207 new_precedence
[i
].val
= 40;
2210 struct prefixlist
*l
= precedencelist
;
2213 new_precedence
[i
] = l
->entry
;
2216 free_prefixlist (precedencelist
);
2218 /* Sort the entries so that the most specific ones are at
2220 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2224 new_precedence
= (struct prefixentry
*) default_precedence
;
2226 struct scopeentry
*new_scopes
;
2229 if (!scopelist_nullbits
)
2231 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2232 if (new_scopes
== NULL
)
2234 if (new_labels
!= default_labels
)
2236 if (new_precedence
!= default_precedence
)
2237 free (new_precedence
);
2242 if (!scopelist_nullbits
)
2245 new_scopes
[i
].addr32
= 0;
2246 new_scopes
[i
].netmask
= 0;
2247 new_scopes
[i
].scope
= 14;
2250 struct scopelist
*l
= scopelist
;
2253 new_scopes
[i
] = l
->entry
;
2256 free_scopelist (scopelist
);
2258 /* Sort the entries so that the most specific ones are at
2260 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2264 new_scopes
= (struct scopeentry
*) default_scopes
;
2266 /* Now we are ready to replace the values. */
2267 const struct prefixentry
*old
= labels
;
2268 labels
= new_labels
;
2269 if (old
!= default_labels
)
2270 free ((void *) old
);
2273 precedence
= new_precedence
;
2274 if (old
!= default_precedence
)
2275 free ((void *) old
);
2277 const struct scopeentry
*oldscope
= scopes
;
2278 scopes
= new_scopes
;
2279 if (oldscope
!= default_scopes
)
2280 free ((void *) oldscope
);
2282 save_gaiconf_mtime (&st
);
2287 free_prefixlist (labellist
);
2288 free_prefixlist (precedencelist
);
2289 free_scopelist (scopelist
);
2291 /* If we previously read the file but it is gone now, free the
2292 old data and use the builtin one. Leave the reload flag
2300 gaiconf_reload (void)
2303 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2304 || !check_gaiconf_mtime (&st
))
2310 getaddrinfo (const char *name
, const char *service
,
2311 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2313 int i
= 0, last_i
= 0;
2315 struct addrinfo
*p
= NULL
;
2316 struct gaih_service gaih_service
, *pservice
;
2317 struct addrinfo local_hints
;
2319 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2322 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2325 if (name
== NULL
&& service
== NULL
)
2329 hints
= &default_hints
;
2332 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2334 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2335 |AI_IDN_USE_STD3_ASCII_RULES
2337 |AI_NUMERICSERV
|AI_ALL
))
2338 return EAI_BADFLAGS
;
2340 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2341 return EAI_BADFLAGS
;
2343 struct in6addrinfo
*in6ai
= NULL
;
2344 size_t in6ailen
= 0;
2345 bool seen_ipv4
= false;
2346 bool seen_ipv6
= false;
2347 bool check_pf_called
= false;
2349 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2351 /* We might need information about what interfaces are available.
2352 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2353 cannot cache the results since new interfaces could be added at
2355 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2356 check_pf_called
= true;
2358 /* Now make a decision on what we return, if anything. */
2359 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2361 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2362 narrow down the search. */
2363 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2365 local_hints
= *hints
;
2366 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2367 hints
= &local_hints
;
2370 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2371 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2373 /* We cannot possibly return a valid answer. */
2374 __free_in6ai (in6ai
);
2379 if (service
&& service
[0])
2382 gaih_service
.name
= service
;
2383 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2386 if (hints
->ai_flags
& AI_NUMERICSERV
)
2388 __free_in6ai (in6ai
);
2392 gaih_service
.num
= -1;
2395 pservice
= &gaih_service
;
2400 struct addrinfo
**end
= &p
;
2402 unsigned int naddrs
= 0;
2403 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2404 || hints
->ai_family
== AF_INET6
)
2406 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2410 __free_in6ai (in6ai
);
2416 end
= &((*end
)->ai_next
);
2422 __free_in6ai (in6ai
);
2428 /* Read the config file. */
2429 __libc_once_define (static, once
);
2430 __typeof (once
) old_once
= once
;
2431 __libc_once (once
, gaiconf_init
);
2432 /* Sort results according to RFC 3484. */
2433 struct sort_result
*results
;
2436 struct addrinfo
*last
= NULL
;
2437 char *canonname
= NULL
;
2438 bool malloc_results
;
2439 size_t alloc_size
= nresults
* (sizeof (*results
) + sizeof (size_t));
2442 = !__libc_use_alloca (alloc_size
);
2445 results
= malloc (alloc_size
);
2446 if (results
== NULL
)
2448 __free_in6ai (in6ai
);
2453 results
= alloca (alloc_size
);
2454 order
= (size_t *) (results
+ nresults
);
2456 /* Now we definitely need the interface information. */
2457 if (! check_pf_called
)
2458 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2460 /* If we have information about deprecated and temporary addresses
2461 sort the array now. */
2463 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2468 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2470 results
[i
].dest_addr
= q
;
2471 results
[i
].native
= -1;
2474 /* If we just looked up the address for a different
2475 protocol, reuse the result. */
2476 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2477 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2479 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2480 results
[i
- 1].source_addr_len
);
2481 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2482 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2483 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2484 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2485 results
[i
].index
= results
[i
- 1].index
;
2489 results
[i
].got_source_addr
= false;
2490 results
[i
].source_addr_flags
= 0;
2491 results
[i
].prefixlen
= 0;
2492 results
[i
].index
= 0xffffffffu
;
2494 /* We overwrite the type with SOCK_DGRAM since we do not
2495 want connect() to connect to the other side. If we
2496 cannot determine the source address remember this
2498 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2502 close_not_cancel_no_status (fd
);
2504 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2508 /* Reset the connection. */
2509 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2510 __connect (fd
, &sa
, sizeof (sa
));
2513 socklen_t sl
= sizeof (results
[i
].source_addr
);
2515 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2516 && __getsockname (fd
,
2517 (struct sockaddr
*) &results
[i
].source_addr
,
2520 results
[i
].source_addr_len
= sl
;
2521 results
[i
].got_source_addr
= true;
2525 /* See whether the source address is on the list of
2526 deprecated or temporary addresses. */
2527 struct in6addrinfo tmp
;
2529 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2531 struct sockaddr_in
*sinp
2532 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2535 tmp
.addr
[2] = htonl (0xffff);
2536 /* Special case for lo interface, the source address
2537 being possibly different than the interface
2539 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2541 tmp
.addr
[3] = htonl(0x7f000001);
2543 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2547 struct sockaddr_in6
*sin6p
2548 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2549 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2552 struct in6addrinfo
*found
2553 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2557 results
[i
].source_addr_flags
= found
->flags
;
2558 results
[i
].prefixlen
= found
->prefixlen
;
2559 results
[i
].index
= found
->index
;
2563 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2565 /* We have to convert the address. The socket is
2566 IPv6 and the request is for IPv4. */
2567 struct sockaddr_in6
*sin6
2568 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2569 struct sockaddr_in
*sin
2570 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2571 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2572 sin
->sin_family
= AF_INET
;
2573 /* We do not have to initialize sin_port since this
2574 fields has the same position and size in the IPv6
2576 assert (offsetof (struct sockaddr_in
, sin_port
)
2577 == offsetof (struct sockaddr_in6
, sin6_port
));
2578 assert (sizeof (sin
->sin_port
)
2579 == sizeof (sin6
->sin6_port
));
2580 memcpy (&sin
->sin_addr
,
2581 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2582 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2585 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2586 && q
->ai_family
== AF_INET
)
2587 /* This could mean IPv6 sockets are IPv6-only. */
2590 /* Just make sure that if we have to process the same
2591 address again we do not copy any memory. */
2592 results
[i
].source_addr_len
= 0;
2595 /* Remember the canonical name. */
2596 if (q
->ai_canonname
!= NULL
)
2598 assert (canonname
== NULL
);
2599 canonname
= q
->ai_canonname
;
2600 q
->ai_canonname
= NULL
;
2605 close_not_cancel_no_status (fd
);
2607 /* We got all the source addresses we can get, now sort using
2609 struct sort_result_combo src
2610 = { .results
= results
, .nresults
= nresults
};
2611 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2613 __libc_lock_define_initialized (static, lock
);
2615 __libc_lock_lock (lock
);
2616 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2618 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2619 __libc_lock_unlock (lock
);
2622 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2624 /* Queue the results up as they come out of sorting. */
2625 q
= p
= results
[order
[0]].dest_addr
;
2626 for (i
= 1; i
< nresults
; ++i
)
2627 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2630 /* Fill in the canonical name into the new first entry. */
2631 p
->ai_canonname
= canonname
;
2637 __free_in6ai (in6ai
);
2645 return last_i
? -last_i
: EAI_NONAME
;
2647 libc_hidden_def (getaddrinfo
)
2649 nss_interface_function (getaddrinfo
)
2652 freeaddrinfo (struct addrinfo
*ai
)
2660 free (p
->ai_canonname
);
2664 libc_hidden_def (freeaddrinfo
)