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 (__glibc_unlikely (scope_delim
!= NULL
))
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
);
716 if (!((air
->family
[i
] == AF_INET
717 && req
->ai_family
== AF_INET6
718 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
719 || req
->ai_family
== AF_UNSPEC
720 || air
->family
[i
] == req
->ai_family
))
722 /* Skip over non-matching result. */
732 uint32_t *pataddr
= (*pat
)->addr
;
734 if (added_canon
|| air
->canon
== NULL
)
736 else if (canonbuf
== NULL
)
738 size_t canonlen
= strlen (air
->canon
) + 1;
739 if ((req
->ai_flags
& AI_CANONIDN
) != 0
740 && __libc_use_alloca (alloca_used
+ canonlen
))
741 canonbuf
= alloca_account (canonlen
, alloca_used
);
744 canonbuf
= malloc (canonlen
);
745 if (canonbuf
== NULL
)
747 result
= -EAI_MEMORY
;
748 goto free_and_return
;
750 malloc_canonbuf
= true;
752 canon
= (*pat
)->name
= memcpy (canonbuf
, air
->canon
,
756 if (air
->family
[i
] == AF_INET
757 && req
->ai_family
== AF_INET6
758 && (req
->ai_flags
& AI_V4MAPPED
))
760 (*pat
)->family
= AF_INET6
;
761 pataddr
[3] = *(uint32_t *) addrs
;
762 pataddr
[2] = htonl (0xffff);
765 pat
= &((*pat
)->next
);
768 else if (req
->ai_family
== AF_UNSPEC
769 || air
->family
[i
] == req
->ai_family
)
771 (*pat
)->family
= air
->family
[i
];
772 memcpy (pataddr
, addrs
, size
);
773 pat
= &((*pat
)->next
);
775 if (air
->family
[i
] == AF_INET6
)
783 if (at
->family
== AF_UNSPEC
)
785 result
= -EAI_NONAME
;
786 goto free_and_return
;
792 /* The database contains a negative entry. */
793 goto free_and_return
;
794 else if (__nss_not_use_nscd_hosts
== 0)
796 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
797 result
= -EAI_MEMORY
;
798 else if (herrno
== TRY_AGAIN
)
801 result
= -EAI_SYSTEM
;
803 goto free_and_return
;
808 if (__nss_hosts_database
== NULL
)
809 no_more
= __nss_database_lookup ("hosts", NULL
,
810 "dns [!UNAVAIL=return] files",
811 &__nss_hosts_database
);
814 nip
= __nss_hosts_database
;
816 /* Initialize configurations. */
817 if (__glibc_unlikely (!_res_hconf
.initialized
))
819 if (__res_maybe_init (&_res
, 0) == -1)
822 /* If we are looking for both IPv4 and IPv6 address we don't
823 want the lookup functions to automatically promote IPv4
824 addresses to IPv6 addresses. Currently this is decided
825 by setting the RES_USE_INET6 bit in _res.options. */
826 old_res_options
= _res
.options
;
827 _res
.options
&= ~RES_USE_INET6
;
829 size_t tmpbuflen
= 1024 + sizeof(struct gaih_addrtuple
);
830 malloc_tmpbuf
= !__libc_use_alloca (alloca_used
+ tmpbuflen
);
831 assert (tmpbuf
== NULL
);
833 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
836 tmpbuf
= malloc (tmpbuflen
);
839 _res
.options
|= old_res_options
& RES_USE_INET6
;
840 result
= -EAI_MEMORY
;
841 goto free_and_return
;
848 nss_gethostbyname4_r fct4
= NULL
;
850 /* gethostbyname4_r sends out parallel A and AAAA queries and
851 is thus only suitable for PF_UNSPEC. */
852 if (req
->ai_family
== PF_UNSPEC
)
853 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
862 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
863 tmpbuflen
, &rc
, &herrno
,
865 if (status
== NSS_STATUS_SUCCESS
)
867 if (status
!= NSS_STATUS_TRYAGAIN
868 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
870 if (herrno
== TRY_AGAIN
)
873 no_data
= herrno
== NO_DATA
;
878 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
879 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
884 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
888 _res
.options
|= old_res_options
& RES_USE_INET6
;
889 result
= -EAI_MEMORY
;
890 goto free_and_return
;
893 malloc_tmpbuf
= true;
894 tmpbuflen
= 2 * tmpbuflen
;
898 if (status
== NSS_STATUS_SUCCESS
)
903 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
904 canon
= (*pat
)->name
;
908 if ((*pat
)->family
== AF_INET
909 && req
->ai_family
== AF_INET6
910 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
912 uint32_t *pataddr
= (*pat
)->addr
;
913 (*pat
)->family
= AF_INET6
;
914 pataddr
[3] = pataddr
[0];
915 pataddr
[2] = htonl (0xffff);
918 pat
= &((*pat
)->next
);
921 else if (req
->ai_family
== AF_UNSPEC
922 || (*pat
)->family
== req
->ai_family
)
924 pat
= &((*pat
)->next
);
927 if (req
->ai_family
== AF_INET6
)
931 *pat
= ((*pat
)->next
);
935 no_inet6_data
= no_data
;
939 nss_gethostbyname3_r fct
= NULL
;
940 if (req
->ai_flags
& AI_CANONNAME
)
941 /* No need to use this function if we do not look for
942 the canonical name. The function does not exist in
943 all NSS modules and therefore the lookup would
945 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
947 /* We are cheating here. The gethostbyname2_r
948 function does not have the same interface as
949 gethostbyname3_r but the extra arguments the
950 latter takes are added at the end. So the
951 gethostbyname2_r code will just ignore them. */
952 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
956 if (req
->ai_family
== AF_INET6
957 || req
->ai_family
== AF_UNSPEC
)
959 gethosts (AF_INET6
, struct in6_addr
);
960 no_inet6_data
= no_data
;
961 inet6_status
= status
;
963 if (req
->ai_family
== AF_INET
964 || req
->ai_family
== AF_UNSPEC
965 || (req
->ai_family
== AF_INET6
966 && (req
->ai_flags
& AI_V4MAPPED
)
967 /* Avoid generating the mapped addresses if we
968 know we are not going to need them. */
969 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
971 gethosts (AF_INET
, struct in_addr
);
973 if (req
->ai_family
== AF_INET
)
975 no_inet6_data
= no_data
;
976 inet6_status
= status
;
980 /* If we found one address for AF_INET or AF_INET6,
981 don't continue the search. */
982 if (inet6_status
== NSS_STATUS_SUCCESS
983 || status
== NSS_STATUS_SUCCESS
)
985 if ((req
->ai_flags
& AI_CANONNAME
) != 0
988 /* If we need the canonical name, get it
989 from the same service as the result. */
990 nss_getcanonname_r cfct
;
993 cfct
= __nss_lookup_function (nip
,
997 const size_t max_fqdn_len
= 256;
998 if ((req
->ai_flags
& AI_CANONIDN
) != 0
999 && __libc_use_alloca (alloca_used
1001 canonbuf
= alloca_account (max_fqdn_len
,
1005 canonbuf
= malloc (max_fqdn_len
);
1006 if (canonbuf
== NULL
)
1009 |= old_res_options
& RES_USE_INET6
;
1010 result
= -EAI_MEMORY
;
1011 goto free_and_return
;
1013 malloc_canonbuf
= true;
1017 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
1021 == NSS_STATUS_SUCCESS
)
1025 /* If the canonical name cannot be
1026 determined, use the passed in
1028 if (malloc_canonbuf
)
1031 malloc_canonbuf
= false;
1037 status
= NSS_STATUS_SUCCESS
;
1041 /* We can have different states for AF_INET and
1042 AF_INET6. Try to find a useful one for both. */
1043 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
1044 status
= NSS_STATUS_TRYAGAIN
;
1045 else if (status
== NSS_STATUS_UNAVAIL
1046 && inet6_status
!= NSS_STATUS_UNAVAIL
)
1047 status
= inet6_status
;
1052 status
= NSS_STATUS_UNAVAIL
;
1053 /* Could not load any of the lookup functions. Indicate
1054 an internal error if the failure was due to a system
1055 error other than the file not being found. We use the
1056 errno from the last failed callback. */
1057 if (errno
!= 0 && errno
!= ENOENT
)
1058 __set_h_errno (NETDB_INTERNAL
);
1062 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
1065 if (nip
->next
== NULL
)
1071 _res
.options
|= old_res_options
& RES_USE_INET6
;
1073 if (h_errno
== NETDB_INTERNAL
)
1075 result
= -EAI_SYSTEM
;
1076 goto free_and_return
;
1079 if (no_data
!= 0 && no_inet6_data
!= 0)
1081 /* If both requests timed out report this. */
1082 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
1083 result
= -EAI_AGAIN
;
1085 /* We made requests but they turned out no data. The name
1086 is known, though. */
1087 result
= -EAI_NODATA
;
1089 goto free_and_return
;
1094 if (at
->family
== AF_UNSPEC
)
1096 result
= -EAI_NONAME
;
1097 goto free_and_return
;
1102 struct gaih_addrtuple
*atr
;
1103 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
1104 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
1106 if (req
->ai_family
== AF_UNSPEC
)
1108 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
1109 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1112 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1114 at
->family
= AF_INET6
;
1115 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1116 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1120 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1122 atr
->family
= AF_INET
;
1123 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1124 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1129 struct gaih_servtuple
*st2
;
1130 struct gaih_addrtuple
*at2
= at
;
1135 buffer is the size of an unformatted IPv6 address in printable format.
1139 /* Only the first entry gets the canonical name. */
1140 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1143 /* If the canonical name cannot be determined, use
1144 the passed in string. */
1148 if (req
->ai_flags
& AI_CANONIDN
)
1151 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1152 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1153 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1154 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1157 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1158 if (rc
!= IDNA_SUCCESS
)
1160 if (rc
== IDNA_MALLOC_ERROR
)
1161 result
= -EAI_MEMORY
;
1162 else if (rc
== IDNA_DLOPEN_ERROR
)
1163 result
= -EAI_SYSTEM
;
1165 result
= -EAI_IDN_ENCODE
;
1166 goto free_and_return
;
1168 /* In case the output string is the same as the input
1169 string no new string has been allocated and we
1181 if (malloc_canonbuf
)
1182 /* We already allocated the string using malloc. */
1183 malloc_canonbuf
= false;
1186 canon
= strdup (canon
);
1189 result
= -EAI_MEMORY
;
1190 goto free_and_return
;
1196 family
= at2
->family
;
1197 if (family
== AF_INET6
)
1199 socklen
= sizeof (struct sockaddr_in6
);
1201 /* If we looked up IPv4 mapped address discard them here if
1202 the caller isn't interested in all address and we have
1203 found at least one IPv6 address. */
1205 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1206 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1210 socklen
= sizeof (struct sockaddr_in
);
1212 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1214 struct addrinfo
*ai
;
1215 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1218 free ((char *) canon
);
1219 result
= -EAI_MEMORY
;
1220 goto free_and_return
;
1223 ai
->ai_flags
= req
->ai_flags
;
1224 ai
->ai_family
= family
;
1225 ai
->ai_socktype
= st2
->socktype
;
1226 ai
->ai_protocol
= st2
->protocol
;
1227 ai
->ai_addrlen
= socklen
;
1228 ai
->ai_addr
= (void *) (ai
+ 1);
1230 /* We only add the canonical name once. */
1231 ai
->ai_canonname
= (char *) canon
;
1235 ai
->ai_addr
->sa_len
= socklen
;
1236 #endif /* _HAVE_SA_LEN */
1237 ai
->ai_addr
->sa_family
= family
;
1239 /* In case of an allocation error the list must be NULL
1243 if (family
== AF_INET6
)
1245 struct sockaddr_in6
*sin6p
=
1246 (struct sockaddr_in6
*) ai
->ai_addr
;
1248 sin6p
->sin6_port
= st2
->port
;
1249 sin6p
->sin6_flowinfo
= 0;
1250 memcpy (&sin6p
->sin6_addr
,
1251 at2
->addr
, sizeof (struct in6_addr
));
1252 sin6p
->sin6_scope_id
= at2
->scopeid
;
1256 struct sockaddr_in
*sinp
=
1257 (struct sockaddr_in
*) ai
->ai_addr
;
1258 sinp
->sin_port
= st2
->port
;
1259 memcpy (&sinp
->sin_addr
,
1260 at2
->addr
, sizeof (struct in_addr
));
1261 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1264 pai
= &(ai
->ai_next
);
1276 free ((char *) name
);
1279 if (malloc_canonbuf
)
1290 struct addrinfo
*dest_addr
;
1291 /* Using sockaddr_storage is for now overkill. We only support IPv4
1292 and IPv6 so far. If this changes at some point we can adjust the
1294 struct sockaddr_in6 source_addr
;
1295 uint8_t source_addr_len
;
1296 bool got_source_addr
;
1297 uint8_t source_addr_flags
;
1303 struct sort_result_combo
1305 struct sort_result
*results
;
1310 #if __BYTE_ORDER == __BIG_ENDIAN
1311 # define htonl_c(n) n
1313 # define htonl_c(n) __bswap_constant_32 (n)
1316 static const struct scopeentry
1325 } default_scopes
[] =
1327 /* Link-local addresses: scope 2. */
1328 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1329 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1330 /* Default: scope 14. */
1331 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1334 /* The label table. */
1335 static const struct scopeentry
*scopes
;
1339 get_scope (const struct sockaddr_in6
*in6
)
1342 if (in6
->sin6_family
== PF_INET6
)
1344 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1346 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1347 /* RFC 4291 2.5.3 says that the loopback address is to be
1348 treated like a link-local address. */
1349 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1351 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1354 /* XXX Is this the correct default behavior? */
1358 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1360 else if (in6
->sin6_family
== PF_INET
)
1362 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1367 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1368 == scopes
[cnt
].addr32
)
1369 return scopes
[cnt
].scope
;
1376 /* XXX What is a good default? */
1385 struct in6_addr prefix
;
1391 /* The label table. */
1392 static const struct prefixentry
*labels
;
1394 /* Default labels. */
1395 static const struct prefixentry default_labels
[] =
1397 /* See RFC 3484 for the details. */
1399 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1403 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1407 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1411 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1412 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1414 /* The next two entries differ from RFC 3484. We need to treat
1415 IPv6 site-local addresses special because they are never NATed,
1416 unlike site-locale IPv4 addresses. If this would not happen, on
1417 machines which have only IPv4 and IPv6 site-local addresses, the
1418 sorting would prefer the IPv6 site-local addresses, causing
1419 unnecessary delays when trying to connect to a global IPv6 address
1420 through a site-local IPv6 address. */
1422 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1426 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1429 /* Additional rule for Teredo tunnels. */
1431 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1435 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1441 /* The precedence table. */
1442 static const struct prefixentry
*precedence
;
1444 /* The default precedences. */
1445 static const struct prefixentry default_precedence
[] =
1447 /* See RFC 3484 for the details. */
1449 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1453 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1457 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1461 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1462 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1465 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1472 match_prefix (const struct sockaddr_in6
*in6
,
1473 const struct prefixentry
*list
, int default_val
)
1476 struct sockaddr_in6 in6_mem
;
1478 if (in6
->sin6_family
== PF_INET
)
1480 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1482 /* Construct a V4-to-6 mapped address. */
1483 in6_mem
.sin6_family
= PF_INET6
;
1484 in6_mem
.sin6_port
= in
->sin_port
;
1485 in6_mem
.sin6_flowinfo
= 0;
1486 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1487 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1488 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1489 in6_mem
.sin6_scope_id
= 0;
1493 else if (in6
->sin6_family
!= PF_INET6
)
1496 for (idx
= 0; ; ++idx
)
1498 unsigned int bits
= list
[idx
].bits
;
1499 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1500 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1514 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1520 return list
[idx
].val
;
1525 get_label (const struct sockaddr_in6
*in6
)
1527 /* XXX What is a good default value? */
1528 return match_prefix (in6
, labels
, INT_MAX
);
1533 get_precedence (const struct sockaddr_in6
*in6
)
1535 /* XXX What is a good default value? */
1536 return match_prefix (in6
, precedence
, 0);
1540 /* Find last bit set in a word. */
1546 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1547 if ((a
& mask
) != 0)
1554 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1556 const size_t idx1
= *(const size_t *) p1
;
1557 const size_t idx2
= *(const size_t *) p2
;
1558 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1559 struct sort_result
*a1
= &src
->results
[idx1
];
1560 struct sort_result
*a2
= &src
->results
[idx2
];
1562 /* Rule 1: Avoid unusable destinations.
1563 We have the got_source_addr flag set if the destination is reachable. */
1564 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1566 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1570 /* Rule 2: Prefer matching scope. Only interesting if both
1571 destination addresses are IPv6. */
1573 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1576 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1578 if (a1
->got_source_addr
)
1580 int a1_src_scope
= get_scope (&a1
->source_addr
);
1581 int a2_src_scope
= get_scope (&a2
->source_addr
);
1583 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1585 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1590 /* Rule 3: Avoid deprecated addresses. */
1591 if (a1
->got_source_addr
)
1593 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1594 && (a2
->source_addr_flags
& in6ai_deprecated
))
1596 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1597 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1601 /* Rule 4: Prefer home addresses. */
1602 if (a1
->got_source_addr
)
1604 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1605 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1607 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1608 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1612 /* Rule 5: Prefer matching label. */
1613 if (a1
->got_source_addr
)
1616 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1617 int a1_src_label
= get_label (&a1
->source_addr
);
1620 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1621 int a2_src_label
= get_label (&a2
->source_addr
);
1623 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1625 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1630 /* Rule 6: Prefer higher precedence. */
1632 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1634 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1636 if (a1_prec
> a2_prec
)
1638 if (a1_prec
< a2_prec
)
1642 /* Rule 7: Prefer native transport. */
1643 if (a1
->got_source_addr
)
1645 /* The same interface index means the same interface which means
1646 there is no difference in transport. This should catch many
1648 if (a1
->index
!= a2
->index
)
1650 int a1_native
= a1
->native
;
1651 int a2_native
= a2
->native
;
1653 if (a1_native
== -1 || a2_native
== -1)
1656 if (a1_native
== -1)
1658 /* If we do not have the information use 'native' as
1661 a1_index
= a1
->index
;
1664 a1_index
= 0xffffffffu
;
1667 if (a2_native
== -1)
1669 /* If we do not have the information use 'native' as
1672 a2_index
= a2
->index
;
1675 a2_index
= 0xffffffffu
;
1677 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1679 /* Fill in the results in all the records. */
1680 for (int i
= 0; i
< src
->nresults
; ++i
)
1681 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1683 assert (src
->results
[i
].native
== -1
1684 || src
->results
[i
].native
== a1_native
);
1685 src
->results
[i
].native
= a1_native
;
1687 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1689 assert (src
->results
[i
].native
== -1
1690 || src
->results
[i
].native
== a2_native
);
1691 src
->results
[i
].native
= a2_native
;
1695 if (a1_native
&& !a2_native
)
1697 if (!a1_native
&& a2_native
)
1703 /* Rule 8: Prefer smaller scope. */
1704 if (a1_dst_scope
< a2_dst_scope
)
1706 if (a1_dst_scope
> a2_dst_scope
)
1710 /* Rule 9: Use longest matching prefix. */
1711 if (a1
->got_source_addr
1712 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1717 if (a1
->dest_addr
->ai_family
== PF_INET
)
1719 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1720 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1722 /* Outside of subnets, as defined by the network masks,
1723 common address prefixes for IPv4 addresses make no sense.
1724 So, define a non-zero value only if source and
1725 destination address are on the same subnet. */
1726 struct sockaddr_in
*in1_dst
1727 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1728 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1729 struct sockaddr_in
*in1_src
1730 = (struct sockaddr_in
*) &a1
->source_addr
;
1731 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1732 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1734 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1735 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1737 struct sockaddr_in
*in2_dst
1738 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1739 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1740 struct sockaddr_in
*in2_src
1741 = (struct sockaddr_in
*) &a2
->source_addr
;
1742 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1743 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1745 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1746 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1748 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1750 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1751 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1753 struct sockaddr_in6
*in1_dst
;
1754 struct sockaddr_in6
*in1_src
;
1755 struct sockaddr_in6
*in2_dst
;
1756 struct sockaddr_in6
*in2_src
;
1758 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1759 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1760 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1761 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1764 for (i
= 0; i
< 4; ++i
)
1765 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1766 != in1_src
->sin6_addr
.s6_addr32
[i
]
1767 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1768 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1773 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1774 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1775 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1776 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1787 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1788 compare with the value indicating the order in which the entries
1789 have been received from the services. NB: no two entries can have
1790 the same order so the test will never return zero. */
1791 return idx1
< idx2
? -1 : 1;
1796 in6aicmp (const void *p1
, const void *p2
)
1798 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1799 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1801 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1805 /* Name of the config file for RFC 3484 sorting (for now). */
1806 #define GAICONF_FNAME "/etc/gai.conf"
1809 /* Non-zero if we are supposed to reload the config file automatically
1810 whenever it changed. */
1811 static int gaiconf_reload_flag
;
1813 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1814 static int gaiconf_reload_flag_ever_set
;
1816 /* Last modification time. */
1817 #ifdef _STATBUF_ST_NSEC
1819 static struct timespec gaiconf_mtime
;
1822 save_gaiconf_mtime (const struct stat64
*st
)
1824 gaiconf_mtime
= st
->st_mtim
;
1828 check_gaiconf_mtime (const struct stat64
*st
)
1830 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1831 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1836 static time_t gaiconf_mtime
;
1839 save_gaiconf_mtime (const struct stat64
*st
)
1841 gaiconf_mtime
= st
->st_mtime
;
1845 check_gaiconf_mtime (const struct stat64
*st
)
1847 return st
->st_mtime
== gaiconf_mtime
;
1853 libc_freeres_fn(fini
)
1855 if (labels
!= default_labels
)
1857 const struct prefixentry
*old
= labels
;
1858 labels
= default_labels
;
1859 free ((void *) old
);
1862 if (precedence
!= default_precedence
)
1864 const struct prefixentry
*old
= precedence
;
1865 precedence
= default_precedence
;
1866 free ((void *) old
);
1869 if (scopes
!= default_scopes
)
1871 const struct scopeentry
*old
= scopes
;
1872 scopes
= default_scopes
;
1873 free ((void *) old
);
1880 struct prefixentry entry
;
1881 struct prefixlist
*next
;
1887 struct scopeentry entry
;
1888 struct scopelist
*next
;
1893 free_prefixlist (struct prefixlist
*list
)
1895 while (list
!= NULL
)
1897 struct prefixlist
*oldp
= list
;
1905 free_scopelist (struct scopelist
*list
)
1907 while (list
!= NULL
)
1909 struct scopelist
*oldp
= list
;
1917 prefixcmp (const void *p1
, const void *p2
)
1919 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1920 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1922 if (e1
->bits
< e2
->bits
)
1924 if (e1
->bits
== e2
->bits
)
1931 scopecmp (const void *p1
, const void *p2
)
1933 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1934 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1936 if (e1
->netmask
> e2
->netmask
)
1938 if (e1
->netmask
== e2
->netmask
)
1947 struct prefixlist
*labellist
= NULL
;
1948 size_t nlabellist
= 0;
1949 bool labellist_nullbits
= false;
1950 struct prefixlist
*precedencelist
= NULL
;
1951 size_t nprecedencelist
= 0;
1952 bool precedencelist_nullbits
= false;
1953 struct scopelist
*scopelist
= NULL
;
1954 size_t nscopelist
= 0;
1955 bool scopelist_nullbits
= false;
1957 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1961 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1970 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1972 while (!feof_unlocked (fp
))
1974 ssize_t n
= __getline (&line
, &linelen
, fp
);
1978 /* Handle comments. No escaping possible so this is easy. */
1979 char *cp
= strchr (line
, '#');
1984 while (isspace (*cp
))
1988 while (*cp
!= '\0' && !isspace (*cp
))
1990 size_t cmdlen
= cp
- cmd
;
1994 while (isspace (*cp
))
1998 while (*cp
!= '\0' && !isspace (*cp
))
2000 size_t val1len
= cp
- cmd
;
2002 /* We always need at least two values. */
2008 while (isspace (*cp
))
2012 while (*cp
!= '\0' && !isspace (*cp
))
2015 /* Ignore the rest of the line. */
2018 struct prefixlist
**listp
;
2024 if (strcmp (cmd
, "label") == 0)
2026 struct in6_addr prefix
;
2027 unsigned long int bits
;
2028 unsigned long int val
;
2033 nullbitsp
= &labellist_nullbits
;
2038 cp
= strchr (val1
, '/');
2041 if (inet_pton (AF_INET6
, val1
, &prefix
)
2043 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2047 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2052 struct prefixlist
*newp
= malloc (sizeof (*newp
));
2060 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
2061 newp
->entry
.bits
= bits
;
2062 newp
->entry
.val
= val
;
2063 newp
->next
= *listp
;
2066 *nullbitsp
|= bits
== 0;
2072 if (strcmp (cmd
, "reload") == 0)
2074 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2075 if (gaiconf_reload_flag
)
2076 gaiconf_reload_flag_ever_set
= 1;
2081 if (strcmp (cmd
, "scopev4") == 0)
2083 struct in6_addr prefix
;
2084 unsigned long int bits
;
2085 unsigned long int val
;
2090 cp
= strchr (val1
, '/');
2093 if (inet_pton (AF_INET6
, val1
, &prefix
))
2096 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2098 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2103 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2108 struct scopelist
*newp
;
2110 newp
= malloc (sizeof (*newp
));
2118 newp
->entry
.netmask
= htonl (bits
!= 96
2122 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2123 & newp
->entry
.netmask
);
2124 newp
->entry
.scope
= val
;
2125 newp
->next
= scopelist
;
2128 scopelist_nullbits
|= bits
== 96;
2131 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2133 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2137 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2149 if (strcmp (cmd
, "precedence") == 0)
2151 listp
= &precedencelist
;
2152 lenp
= &nprecedencelist
;
2153 nullbitsp
= &precedencelist_nullbits
;
2164 /* Create the array for the labels. */
2165 struct prefixentry
*new_labels
;
2168 if (!labellist_nullbits
)
2170 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2171 if (new_labels
== NULL
)
2175 if (!labellist_nullbits
)
2178 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2179 new_labels
[i
].bits
= 0;
2180 new_labels
[i
].val
= 1;
2183 struct prefixlist
*l
= labellist
;
2186 new_labels
[i
] = l
->entry
;
2189 free_prefixlist (labellist
);
2191 /* Sort the entries so that the most specific ones are at
2193 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2196 new_labels
= (struct prefixentry
*) default_labels
;
2198 struct prefixentry
*new_precedence
;
2199 if (nprecedencelist
> 0)
2201 if (!precedencelist_nullbits
)
2203 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2204 if (new_precedence
== NULL
)
2206 if (new_labels
!= default_labels
)
2211 int i
= nprecedencelist
;
2212 if (!precedencelist_nullbits
)
2215 memset (&new_precedence
[i
].prefix
, '\0',
2216 sizeof (struct in6_addr
));
2217 new_precedence
[i
].bits
= 0;
2218 new_precedence
[i
].val
= 40;
2221 struct prefixlist
*l
= precedencelist
;
2224 new_precedence
[i
] = l
->entry
;
2227 free_prefixlist (precedencelist
);
2229 /* Sort the entries so that the most specific ones are at
2231 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2235 new_precedence
= (struct prefixentry
*) default_precedence
;
2237 struct scopeentry
*new_scopes
;
2240 if (!scopelist_nullbits
)
2242 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2243 if (new_scopes
== NULL
)
2245 if (new_labels
!= default_labels
)
2247 if (new_precedence
!= default_precedence
)
2248 free (new_precedence
);
2253 if (!scopelist_nullbits
)
2256 new_scopes
[i
].addr32
= 0;
2257 new_scopes
[i
].netmask
= 0;
2258 new_scopes
[i
].scope
= 14;
2261 struct scopelist
*l
= scopelist
;
2264 new_scopes
[i
] = l
->entry
;
2267 free_scopelist (scopelist
);
2269 /* Sort the entries so that the most specific ones are at
2271 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2275 new_scopes
= (struct scopeentry
*) default_scopes
;
2277 /* Now we are ready to replace the values. */
2278 const struct prefixentry
*old
= labels
;
2279 labels
= new_labels
;
2280 if (old
!= default_labels
)
2281 free ((void *) old
);
2284 precedence
= new_precedence
;
2285 if (old
!= default_precedence
)
2286 free ((void *) old
);
2288 const struct scopeentry
*oldscope
= scopes
;
2289 scopes
= new_scopes
;
2290 if (oldscope
!= default_scopes
)
2291 free ((void *) oldscope
);
2293 save_gaiconf_mtime (&st
);
2298 free_prefixlist (labellist
);
2299 free_prefixlist (precedencelist
);
2300 free_scopelist (scopelist
);
2302 /* If we previously read the file but it is gone now, free the
2303 old data and use the builtin one. Leave the reload flag
2311 gaiconf_reload (void)
2314 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2315 || !check_gaiconf_mtime (&st
))
2321 getaddrinfo (const char *name
, const char *service
,
2322 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2324 int i
= 0, last_i
= 0;
2326 struct addrinfo
*p
= NULL
;
2327 struct gaih_service gaih_service
, *pservice
;
2328 struct addrinfo local_hints
;
2330 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2333 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2336 if (name
== NULL
&& service
== NULL
)
2340 hints
= &default_hints
;
2343 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2345 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2346 |AI_IDN_USE_STD3_ASCII_RULES
2348 |AI_NUMERICSERV
|AI_ALL
))
2349 return EAI_BADFLAGS
;
2351 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2352 return EAI_BADFLAGS
;
2354 struct in6addrinfo
*in6ai
= NULL
;
2355 size_t in6ailen
= 0;
2356 bool seen_ipv4
= false;
2357 bool seen_ipv6
= false;
2358 bool check_pf_called
= false;
2360 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2362 /* We might need information about what interfaces are available.
2363 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2364 cannot cache the results since new interfaces could be added at
2366 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2367 check_pf_called
= true;
2369 /* Now make a decision on what we return, if anything. */
2370 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2372 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2373 narrow down the search. */
2374 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2376 local_hints
= *hints
;
2377 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2378 hints
= &local_hints
;
2381 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2382 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2384 /* We cannot possibly return a valid answer. */
2385 __free_in6ai (in6ai
);
2390 if (service
&& service
[0])
2393 gaih_service
.name
= service
;
2394 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2397 if (hints
->ai_flags
& AI_NUMERICSERV
)
2399 __free_in6ai (in6ai
);
2403 gaih_service
.num
= -1;
2406 pservice
= &gaih_service
;
2411 struct addrinfo
**end
= &p
;
2413 unsigned int naddrs
= 0;
2414 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2415 || hints
->ai_family
== AF_INET6
)
2417 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2421 __free_in6ai (in6ai
);
2427 end
= &((*end
)->ai_next
);
2433 __free_in6ai (in6ai
);
2439 /* Read the config file. */
2440 __libc_once_define (static, once
);
2441 __typeof (once
) old_once
= once
;
2442 __libc_once (once
, gaiconf_init
);
2443 /* Sort results according to RFC 3484. */
2444 struct sort_result
*results
;
2447 struct addrinfo
*last
= NULL
;
2448 char *canonname
= NULL
;
2449 bool malloc_results
;
2450 size_t alloc_size
= nresults
* (sizeof (*results
) + sizeof (size_t));
2453 = !__libc_use_alloca (alloc_size
);
2456 results
= malloc (alloc_size
);
2457 if (results
== NULL
)
2459 __free_in6ai (in6ai
);
2464 results
= alloca (alloc_size
);
2465 order
= (size_t *) (results
+ nresults
);
2467 /* Now we definitely need the interface information. */
2468 if (! check_pf_called
)
2469 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2471 /* If we have information about deprecated and temporary addresses
2472 sort the array now. */
2474 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2479 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2481 results
[i
].dest_addr
= q
;
2482 results
[i
].native
= -1;
2485 /* If we just looked up the address for a different
2486 protocol, reuse the result. */
2487 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2488 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2490 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2491 results
[i
- 1].source_addr_len
);
2492 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2493 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2494 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2495 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2496 results
[i
].index
= results
[i
- 1].index
;
2500 results
[i
].got_source_addr
= false;
2501 results
[i
].source_addr_flags
= 0;
2502 results
[i
].prefixlen
= 0;
2503 results
[i
].index
= 0xffffffffu
;
2505 /* We overwrite the type with SOCK_DGRAM since we do not
2506 want connect() to connect to the other side. If we
2507 cannot determine the source address remember this
2509 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2513 close_not_cancel_no_status (fd
);
2515 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2519 /* Reset the connection. */
2520 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2521 __connect (fd
, &sa
, sizeof (sa
));
2524 socklen_t sl
= sizeof (results
[i
].source_addr
);
2526 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2527 && __getsockname (fd
,
2528 (struct sockaddr
*) &results
[i
].source_addr
,
2531 results
[i
].source_addr_len
= sl
;
2532 results
[i
].got_source_addr
= true;
2536 /* See whether the source address is on the list of
2537 deprecated or temporary addresses. */
2538 struct in6addrinfo tmp
;
2540 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2542 struct sockaddr_in
*sinp
2543 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2546 tmp
.addr
[2] = htonl (0xffff);
2547 /* Special case for lo interface, the source address
2548 being possibly different than the interface
2550 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2552 tmp
.addr
[3] = htonl(0x7f000001);
2554 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2558 struct sockaddr_in6
*sin6p
2559 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2560 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2563 struct in6addrinfo
*found
2564 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2568 results
[i
].source_addr_flags
= found
->flags
;
2569 results
[i
].prefixlen
= found
->prefixlen
;
2570 results
[i
].index
= found
->index
;
2574 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2576 /* We have to convert the address. The socket is
2577 IPv6 and the request is for IPv4. */
2578 struct sockaddr_in6
*sin6
2579 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2580 struct sockaddr_in
*sin
2581 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2582 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2583 sin
->sin_family
= AF_INET
;
2584 /* We do not have to initialize sin_port since this
2585 fields has the same position and size in the IPv6
2587 assert (offsetof (struct sockaddr_in
, sin_port
)
2588 == offsetof (struct sockaddr_in6
, sin6_port
));
2589 assert (sizeof (sin
->sin_port
)
2590 == sizeof (sin6
->sin6_port
));
2591 memcpy (&sin
->sin_addr
,
2592 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2593 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2596 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2597 && q
->ai_family
== AF_INET
)
2598 /* This could mean IPv6 sockets are IPv6-only. */
2601 /* Just make sure that if we have to process the same
2602 address again we do not copy any memory. */
2603 results
[i
].source_addr_len
= 0;
2606 /* Remember the canonical name. */
2607 if (q
->ai_canonname
!= NULL
)
2609 assert (canonname
== NULL
);
2610 canonname
= q
->ai_canonname
;
2611 q
->ai_canonname
= NULL
;
2616 close_not_cancel_no_status (fd
);
2618 /* We got all the source addresses we can get, now sort using
2620 struct sort_result_combo src
2621 = { .results
= results
, .nresults
= nresults
};
2622 if (__glibc_unlikely (gaiconf_reload_flag_ever_set
))
2624 __libc_lock_define_initialized (static, lock
);
2626 __libc_lock_lock (lock
);
2627 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2629 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2630 __libc_lock_unlock (lock
);
2633 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2635 /* Queue the results up as they come out of sorting. */
2636 q
= p
= results
[order
[0]].dest_addr
;
2637 for (i
= 1; i
< nresults
; ++i
)
2638 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2641 /* Fill in the canonical name into the new first entry. */
2642 p
->ai_canonname
= canonname
;
2648 __free_in6ai (in6ai
);
2656 return last_i
? -last_i
: EAI_NONAME
;
2658 libc_hidden_def (getaddrinfo
)
2660 nss_interface_function (getaddrinfo
)
2663 freeaddrinfo (struct addrinfo
*ai
)
2671 free (p
->ai_canonname
);
2675 libc_hidden_def (freeaddrinfo
)