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>
74 #define GAIH_OKIFUNSPEC 0x0100
75 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
78 # define UNIX_PATH_MAX 108
89 struct gaih_servtuple
*next
;
95 static const struct gaih_servtuple nullserv
;
107 /* Values for `protoflag'. */
108 #define GAI_PROTO_NOSERVICE 1
109 #define GAI_PROTO_PROTOANY 2
111 static const struct gaih_typeproto gaih_inet_typeproto
[] =
113 { 0, 0, 0, false, "" },
114 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
115 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
116 #if defined SOCK_DCCP && defined IPPROTO_DCCP
117 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
119 #ifdef IPPROTO_UDPLITE
120 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
123 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
124 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
126 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
127 { 0, 0, 0, false, "" }
133 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
134 const struct addrinfo
*req
, struct addrinfo
**pai
,
135 unsigned int *naddrs
);
138 static const struct addrinfo default_hints
=
140 .ai_flags
= AI_DEFAULT
,
141 .ai_family
= PF_UNSPEC
,
146 .ai_canonname
= NULL
,
152 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
153 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
156 size_t tmpbuflen
= 1024;
163 tmpbuf
= __alloca (tmpbuflen
);
165 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
167 if (r
!= 0 || s
== NULL
)
172 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
178 st
->socktype
= tp
->socktype
;
179 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
180 ? req
->ai_protocol
: tp
->protocol
);
181 st
->port
= s
->s_port
;
186 #define gethosts(_family, _type) \
192 char *localcanon = NULL; \
196 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
197 &rc, &herrno, NULL, &localcanon)); \
198 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
200 tmpbuf = extend_alloca (tmpbuf, 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 return -EAI_SYSTEM; \
214 if (herrno == TRY_AGAIN) \
215 no_data = EAI_AGAIN; \
217 no_data = herrno == NO_DATA; \
219 else if (h != NULL) \
221 for (i = 0; h->h_addr_list[i]; i++) \
225 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
226 (*pat)->scopeid = 0; \
228 uint32_t *addr = (*pat)->addr; \
229 (*pat)->next = NULL; \
230 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
231 if (_family == AF_INET && req->ai_family == AF_INET6) \
233 (*pat)->family = AF_INET6; \
234 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
235 addr[2] = htonl (0xffff); \
241 (*pat)->family = _family; \
242 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
244 pat = &((*pat)->next); \
247 if (localcanon != NULL && canon == NULL) \
248 canon = strdupa (localcanon); \
250 if (_family == AF_INET6 && i > 0) \
256 typedef enum nss_status (*nss_gethostbyname4_r
)
257 (const char *name
, struct gaih_addrtuple
**pat
,
258 char *buffer
, size_t buflen
, int *errnop
,
259 int *h_errnop
, int32_t *ttlp
);
260 typedef enum nss_status (*nss_gethostbyname3_r
)
261 (const char *name
, int af
, struct hostent
*host
,
262 char *buffer
, size_t buflen
, int *errnop
,
263 int *h_errnop
, int32_t *ttlp
, char **canonp
);
264 typedef enum nss_status (*nss_getcanonname_r
)
265 (const char *name
, char *buffer
, size_t buflen
, char **result
,
266 int *errnop
, int *h_errnop
);
267 extern service_user
*__nss_hosts_database attribute_hidden
;
271 gaih_inet (const char *name
, const struct gaih_service
*service
,
272 const struct addrinfo
*req
, struct addrinfo
**pai
,
273 unsigned int *naddrs
)
275 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
276 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
277 struct gaih_addrtuple
*at
= NULL
;
279 bool got_ipv6
= false;
280 const char *canon
= NULL
;
281 const char *orig_name
= name
;
282 size_t alloca_used
= 0;
284 if (req
->ai_protocol
|| req
->ai_socktype
)
289 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
290 || (req
->ai_protocol
!= 0
291 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
292 && req
->ai_protocol
!= tp
->protocol
)))
297 if (req
->ai_socktype
)
298 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
300 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
307 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
308 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
310 if (service
->num
< 0)
314 st
= (struct gaih_servtuple
*)
315 alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
317 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
322 struct gaih_servtuple
**pst
= &st
;
323 for (tp
++; tp
->name
[0]; tp
++)
325 struct gaih_servtuple
*newp
;
327 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
330 if (req
->ai_socktype
!= 0
331 && req
->ai_socktype
!= tp
->socktype
)
333 if (req
->ai_protocol
!= 0
334 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
335 && req
->ai_protocol
!= tp
->protocol
)
338 newp
= (struct gaih_servtuple
*)
339 alloca_account (sizeof (struct gaih_servtuple
),
342 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
344 if (rc
& GAIH_OKIFUNSPEC
)
352 if (st
== (struct gaih_servtuple
*) &nullserv
)
353 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
358 port
= htons (service
->num
);
366 if (req
->ai_socktype
|| req
->ai_protocol
)
368 st
= alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
370 st
->socktype
= tp
->socktype
;
371 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
372 ? req
->ai_protocol
: tp
->protocol
);
377 /* Neither socket type nor protocol is set. Return all socket types
379 struct gaih_servtuple
**lastp
= &st
;
380 for (++tp
; tp
->name
[0]; ++tp
)
383 struct gaih_servtuple
*newp
;
385 newp
= alloca_account (sizeof (struct gaih_servtuple
),
388 newp
->socktype
= tp
->socktype
;
389 newp
->protocol
= tp
->protocol
;
398 bool malloc_name
= false;
399 bool malloc_addrmem
= false;
400 struct gaih_addrtuple
*addrmem
= NULL
;
401 bool malloc_canonbuf
= false;
402 char *canonbuf
= NULL
;
403 bool malloc_tmpbuf
= false;
408 at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
409 at
->family
= AF_UNSPEC
;
414 if (req
->ai_flags
& AI_IDN
)
417 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
418 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
419 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
420 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
423 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
424 if (rc
!= IDNA_SUCCESS
)
426 /* No need to jump to free_and_return here. */
427 if (rc
== IDNA_MALLOC_ERROR
)
429 if (rc
== IDNA_DLOPEN_ERROR
)
431 return -EAI_IDN_ENCODE
;
433 /* In case the output string is the same as the input string
434 no new string has been allocated. */
443 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
445 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
446 at
->family
= AF_INET
;
447 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
449 at
->addr
[3] = at
->addr
[0];
450 at
->addr
[2] = htonl (0xffff);
453 at
->family
= AF_INET6
;
457 result
= -EAI_ADDRFAMILY
;
458 goto free_and_return
;
461 if (req
->ai_flags
& AI_CANONNAME
)
464 else if (at
->family
== AF_UNSPEC
)
466 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
470 bool malloc_namebuf
= false;
471 char *namebuf
= (char *) name
;
473 if (__builtin_expect (scope_delim
!= NULL
, 0))
479 if (__libc_use_alloca (alloca_used
480 + scope_delim
- name
+ 1))
482 namebuf
= alloca_account (scope_delim
- name
+ 1,
484 *((char *) __mempcpy (namebuf
, name
,
485 scope_delim
- name
)) = '\0';
489 namebuf
= strndup (name
, scope_delim
- name
);
492 assert (!malloc_name
);
495 malloc_namebuf
= true;
500 e
= inet_pton (AF_INET6
, namebuf
, at
->addr
);
504 else if (scope_delim
!= NULL
&& malloc_name
)
505 /* Undo what we did above. */
506 *scope_delim
= SCOPE_DELIMITER
;
510 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
511 at
->family
= AF_INET6
;
512 else if (req
->ai_family
== AF_INET
513 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
515 at
->addr
[0] = at
->addr
[3];
516 at
->family
= AF_INET
;
520 result
= -EAI_ADDRFAMILY
;
521 goto free_and_return
;
524 if (scope_delim
!= NULL
)
526 int try_numericscope
= 0;
527 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
528 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
530 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
531 if (at
->scopeid
== 0)
532 try_numericscope
= 1;
535 try_numericscope
= 1;
537 if (try_numericscope
!= 0)
540 assert (sizeof (uint32_t) <= sizeof (unsigned long));
541 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
545 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
546 goto free_and_return
;
551 if (req
->ai_flags
& AI_CANONNAME
)
556 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
558 struct gaih_addrtuple
**pat
= &at
;
560 int no_inet6_data
= 0;
562 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
563 enum nss_status status
= NSS_STATUS_UNAVAIL
;
567 /* If we do not have to look for IPv6 addresses or the canonical
568 name, use the simple, old functions, which do not support
569 IPv6 scope ids, nor retrieving the canonical name. */
570 if (req
->ai_family
== AF_INET
571 && (req
->ai_flags
& AI_CANONNAME
) == 0)
573 /* Allocate additional room for struct host_data. */
574 size_t tmpbuflen
= (512 + MAX_NR_ALIASES
* sizeof(char*)
575 + 16 * sizeof(char));
576 assert (tmpbuf
== NULL
);
577 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
585 rc
= __gethostbyname2_r (name
, AF_INET
, &th
, tmpbuf
,
586 tmpbuflen
, &h
, &herrno
);
587 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
591 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
592 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
597 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
601 result
= -EAI_MEMORY
;
602 goto free_and_return
;
605 malloc_tmpbuf
= true;
606 tmpbuflen
= 2 * tmpbuflen
;
615 /* We found data, count the number of addresses. */
616 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
618 if (i
> 0 && *pat
!= NULL
)
621 if (__libc_use_alloca (alloca_used
622 + i
* sizeof (struct gaih_addrtuple
)))
623 addrmem
= alloca_account (i
* sizeof (struct gaih_addrtuple
),
628 * sizeof (struct gaih_addrtuple
));
631 result
= -EAI_MEMORY
;
632 goto free_and_return
;
634 malloc_addrmem
= true;
637 /* Now convert it into the list. */
638 struct gaih_addrtuple
*addrfree
= addrmem
;
639 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
647 (*pat
)->family
= AF_INET
;
648 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
650 pat
= &((*pat
)->next
);
656 if (herrno
== NETDB_INTERNAL
)
658 __set_h_errno (herrno
);
659 result
= -EAI_SYSTEM
;
661 else if (herrno
== TRY_AGAIN
)
664 /* We made requests but they turned out no data.
665 The name is known, though. */
666 result
= GAIH_OKIFUNSPEC
| -EAI_NODATA
;
668 goto free_and_return
;
675 if (__nss_not_use_nscd_hosts
> 0
676 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
677 __nss_not_use_nscd_hosts
= 0;
679 if (!__nss_not_use_nscd_hosts
680 && !__nss_database_custom
[NSS_DBSIDX_hosts
])
682 /* Try to use nscd. */
683 struct nscd_ai_result
*air
= NULL
;
685 int err
= __nscd_getai (name
, &air
, &herrno
);
688 /* Transform into gaih_addrtuple list. */
689 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
690 char *addrs
= air
->addrs
;
692 if (__libc_use_alloca (alloca_used
693 + air
->naddrs
* sizeof (struct gaih_addrtuple
)))
694 addrmem
= alloca_account (air
->naddrs
695 * sizeof (struct gaih_addrtuple
),
699 addrmem
= malloc (air
->naddrs
700 * sizeof (struct gaih_addrtuple
));
703 result
= -EAI_MEMORY
;
704 goto free_and_return
;
706 malloc_addrmem
= true;
709 struct gaih_addrtuple
*addrfree
= addrmem
;
710 for (int i
= 0; i
< air
->naddrs
; ++i
)
712 socklen_t size
= (air
->family
[i
] == AF_INET
713 ? INADDRSZ
: IN6ADDRSZ
);
719 uint32_t *pataddr
= (*pat
)->addr
;
721 if (added_canon
|| air
->canon
== NULL
)
723 else if (canonbuf
== NULL
)
725 size_t canonlen
= strlen (air
->canon
) + 1;
726 if ((req
->ai_flags
& AI_CANONIDN
) != 0
727 && __libc_use_alloca (alloca_used
+ canonlen
))
728 canonbuf
= alloca_account (canonlen
, alloca_used
);
731 canonbuf
= malloc (canonlen
);
732 if (canonbuf
== NULL
)
734 result
= -EAI_MEMORY
;
735 goto free_and_return
;
737 malloc_canonbuf
= true;
739 canon
= (*pat
)->name
= memcpy (canonbuf
, air
->canon
,
743 if (air
->family
[i
] == AF_INET
744 && req
->ai_family
== AF_INET6
745 && (req
->ai_flags
& AI_V4MAPPED
))
747 (*pat
)->family
= AF_INET6
;
748 pataddr
[3] = *(uint32_t *) addrs
;
749 pataddr
[2] = htonl (0xffff);
752 pat
= &((*pat
)->next
);
755 else if (req
->ai_family
== AF_UNSPEC
756 || air
->family
[i
] == req
->ai_family
)
758 (*pat
)->family
= air
->family
[i
];
759 memcpy (pataddr
, addrs
, size
);
760 pat
= &((*pat
)->next
);
762 if (air
->family
[i
] == AF_INET6
)
770 if (at
->family
== AF_UNSPEC
)
772 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
773 goto free_and_return
;
779 /* The database contains a negative entry. */
780 goto free_and_return
;
781 else if (__nss_not_use_nscd_hosts
== 0)
783 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
784 result
= -EAI_MEMORY
;
785 else if (herrno
== TRY_AGAIN
)
788 result
= -EAI_SYSTEM
;
790 goto free_and_return
;
795 if (__nss_hosts_database
== NULL
)
796 no_more
= __nss_database_lookup ("hosts", NULL
,
797 "dns [!UNAVAIL=return] files",
798 &__nss_hosts_database
);
801 nip
= __nss_hosts_database
;
803 /* Initialize configurations. */
804 if (__glibc_unlikely (!_res_hconf
.initialized
))
806 if (__res_maybe_init (&_res
, 0) == -1)
809 /* If we are looking for both IPv4 and IPv6 address we don't
810 want the lookup functions to automatically promote IPv4
811 addresses to IPv6 addresses. Currently this is decided
812 by setting the RES_USE_INET6 bit in _res.options. */
813 old_res_options
= _res
.options
;
814 _res
.options
&= ~RES_USE_INET6
;
816 size_t tmpbuflen
= 1024 + sizeof(struct gaih_addrtuple
);
817 malloc_tmpbuf
= !__libc_use_alloca (alloca_used
+ tmpbuflen
);
818 assert (tmpbuf
== NULL
);
820 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
823 tmpbuf
= malloc (tmpbuflen
);
826 _res
.options
|= old_res_options
& RES_USE_INET6
;
827 result
= -EAI_MEMORY
;
828 goto free_and_return
;
835 nss_gethostbyname4_r fct4
= NULL
;
837 /* gethostbyname4_r sends out parallel A and AAAA queries and
838 is thus only suitable for PF_UNSPEC. */
839 if (req
->ai_family
== PF_UNSPEC
)
840 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
849 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
850 tmpbuflen
, &rc
, &herrno
,
852 if (status
== NSS_STATUS_SUCCESS
)
854 if (status
!= NSS_STATUS_TRYAGAIN
855 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
857 if (status
== NSS_STATUS_TRYAGAIN
858 && herrno
== TRY_AGAIN
)
861 no_data
= herrno
== NO_DATA
;
866 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
867 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
872 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
876 _res
.options
|= old_res_options
& RES_USE_INET6
;
877 result
= -EAI_MEMORY
;
878 goto free_and_return
;
881 malloc_tmpbuf
= true;
882 tmpbuflen
= 2 * tmpbuflen
;
886 if (status
== NSS_STATUS_SUCCESS
)
891 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
892 canon
= (*pat
)->name
;
896 if ((*pat
)->family
== AF_INET
897 && req
->ai_family
== AF_INET6
898 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
900 uint32_t *pataddr
= (*pat
)->addr
;
901 (*pat
)->family
= AF_INET6
;
902 pataddr
[3] = pataddr
[0];
903 pataddr
[2] = htonl (0xffff);
906 pat
= &((*pat
)->next
);
909 else if (req
->ai_family
== AF_UNSPEC
910 || (*pat
)->family
== req
->ai_family
)
912 pat
= &((*pat
)->next
);
915 if (req
->ai_family
== AF_INET6
)
919 *pat
= ((*pat
)->next
);
923 no_inet6_data
= no_data
;
927 nss_gethostbyname3_r fct
= NULL
;
928 if (req
->ai_flags
& AI_CANONNAME
)
929 /* No need to use this function if we do not look for
930 the canonical name. The function does not exist in
931 all NSS modules and therefore the lookup would
933 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
935 /* We are cheating here. The gethostbyname2_r
936 function does not have the same interface as
937 gethostbyname3_r but the extra arguments the
938 latter takes are added at the end. So the
939 gethostbyname2_r code will just ignore them. */
940 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
944 if (req
->ai_family
== AF_INET6
945 || req
->ai_family
== AF_UNSPEC
)
947 gethosts (AF_INET6
, struct in6_addr
);
948 no_inet6_data
= no_data
;
949 inet6_status
= status
;
951 if (req
->ai_family
== AF_INET
952 || req
->ai_family
== AF_UNSPEC
953 || (req
->ai_family
== AF_INET6
954 && (req
->ai_flags
& AI_V4MAPPED
)
955 /* Avoid generating the mapped addresses if we
956 know we are not going to need them. */
957 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
959 gethosts (AF_INET
, struct in_addr
);
961 if (req
->ai_family
== AF_INET
)
963 no_inet6_data
= no_data
;
964 inet6_status
= status
;
968 /* If we found one address for AF_INET or AF_INET6,
969 don't continue the search. */
970 if (inet6_status
== NSS_STATUS_SUCCESS
971 || status
== NSS_STATUS_SUCCESS
)
973 if ((req
->ai_flags
& AI_CANONNAME
) != 0
976 /* If we need the canonical name, get it
977 from the same service as the result. */
978 nss_getcanonname_r cfct
;
981 cfct
= __nss_lookup_function (nip
,
985 const size_t max_fqdn_len
= 256;
986 if ((req
->ai_flags
& AI_CANONIDN
) != 0
987 && __libc_use_alloca (alloca_used
989 canonbuf
= alloca_account (max_fqdn_len
,
993 canonbuf
= malloc (max_fqdn_len
);
994 if (canonbuf
== NULL
)
997 |= old_res_options
& RES_USE_INET6
;
998 result
= -EAI_MEMORY
;
999 goto free_and_return
;
1001 malloc_canonbuf
= true;
1005 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
1009 == NSS_STATUS_SUCCESS
)
1013 /* If the canonical name cannot be
1014 determined, use the passed in
1016 if (malloc_canonbuf
)
1019 malloc_canonbuf
= false;
1025 status
= NSS_STATUS_SUCCESS
;
1029 /* We can have different states for AF_INET and
1030 AF_INET6. Try to find a useful one for both. */
1031 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
1032 status
= NSS_STATUS_TRYAGAIN
;
1033 else if (status
== NSS_STATUS_UNAVAIL
1034 && inet6_status
!= NSS_STATUS_UNAVAIL
)
1035 status
= inet6_status
;
1040 status
= NSS_STATUS_UNAVAIL
;
1041 /* Could not load any of the lookup functions. Indicate
1042 an internal error if the failure was due to a system
1043 error other than the file not being found. We use the
1044 errno from the last failed callback. */
1045 if (errno
!= 0 && errno
!= ENOENT
)
1046 __set_h_errno (NETDB_INTERNAL
);
1050 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
1053 if (nip
->next
== NULL
)
1059 _res
.options
|= old_res_options
& RES_USE_INET6
;
1061 if (h_errno
== NETDB_INTERNAL
)
1063 result
= GAIH_OKIFUNSPEC
| -EAI_SYSTEM
;
1064 goto free_and_return
;
1067 if (no_data
!= 0 && no_inet6_data
!= 0)
1069 /* If both requests timed out report this. */
1070 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
1071 result
= -EAI_AGAIN
;
1073 /* We made requests but they turned out no data. The name
1074 is known, though. */
1075 result
= GAIH_OKIFUNSPEC
| -EAI_NODATA
;
1077 goto free_and_return
;
1082 if (at
->family
== AF_UNSPEC
)
1084 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
1085 goto free_and_return
;
1090 struct gaih_addrtuple
*atr
;
1091 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
1092 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
1094 if (req
->ai_family
== AF_UNSPEC
)
1096 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
1097 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1100 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1102 at
->family
= AF_INET6
;
1103 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1104 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1108 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1110 atr
->family
= AF_INET
;
1111 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1112 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1117 struct gaih_servtuple
*st2
;
1118 struct gaih_addrtuple
*at2
= at
;
1123 buffer is the size of an unformatted IPv6 address in printable format.
1127 /* Only the first entry gets the canonical name. */
1128 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1131 /* If the canonical name cannot be determined, use
1132 the passed in string. */
1136 if (req
->ai_flags
& AI_CANONIDN
)
1139 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1140 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1141 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1142 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1145 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1146 if (rc
!= IDNA_SUCCESS
)
1148 if (rc
== IDNA_MALLOC_ERROR
)
1149 result
= -EAI_MEMORY
;
1150 else if (rc
== IDNA_DLOPEN_ERROR
)
1151 result
= -EAI_SYSTEM
;
1153 result
= -EAI_IDN_ENCODE
;
1154 goto free_and_return
;
1156 /* In case the output string is the same as the input
1157 string no new string has been allocated and we
1169 if (malloc_canonbuf
)
1170 /* We already allocated the string using malloc. */
1171 malloc_canonbuf
= false;
1174 canon
= strdup (canon
);
1177 result
= -EAI_MEMORY
;
1178 goto free_and_return
;
1184 family
= at2
->family
;
1185 if (family
== AF_INET6
)
1187 socklen
= sizeof (struct sockaddr_in6
);
1189 /* If we looked up IPv4 mapped address discard them here if
1190 the caller isn't interested in all address and we have
1191 found at least one IPv6 address. */
1193 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1194 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1198 socklen
= sizeof (struct sockaddr_in
);
1200 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1202 struct addrinfo
*ai
;
1203 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1206 free ((char *) canon
);
1207 result
= -EAI_MEMORY
;
1208 goto free_and_return
;
1211 ai
->ai_flags
= req
->ai_flags
;
1212 ai
->ai_family
= family
;
1213 ai
->ai_socktype
= st2
->socktype
;
1214 ai
->ai_protocol
= st2
->protocol
;
1215 ai
->ai_addrlen
= socklen
;
1216 ai
->ai_addr
= (void *) (ai
+ 1);
1218 /* We only add the canonical name once. */
1219 ai
->ai_canonname
= (char *) canon
;
1223 ai
->ai_addr
->sa_len
= socklen
;
1224 #endif /* _HAVE_SA_LEN */
1225 ai
->ai_addr
->sa_family
= family
;
1227 /* In case of an allocation error the list must be NULL
1231 if (family
== AF_INET6
)
1233 struct sockaddr_in6
*sin6p
=
1234 (struct sockaddr_in6
*) ai
->ai_addr
;
1236 sin6p
->sin6_port
= st2
->port
;
1237 sin6p
->sin6_flowinfo
= 0;
1238 memcpy (&sin6p
->sin6_addr
,
1239 at2
->addr
, sizeof (struct in6_addr
));
1240 sin6p
->sin6_scope_id
= at2
->scopeid
;
1244 struct sockaddr_in
*sinp
=
1245 (struct sockaddr_in
*) ai
->ai_addr
;
1246 sinp
->sin_port
= st2
->port
;
1247 memcpy (&sinp
->sin_addr
,
1248 at2
->addr
, sizeof (struct in_addr
));
1249 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1252 pai
= &(ai
->ai_next
);
1264 free ((char *) name
);
1267 if (malloc_canonbuf
)
1278 struct addrinfo
*dest_addr
;
1279 /* Using sockaddr_storage is for now overkill. We only support IPv4
1280 and IPv6 so far. If this changes at some point we can adjust the
1282 struct sockaddr_in6 source_addr
;
1283 uint8_t source_addr_len
;
1284 bool got_source_addr
;
1285 uint8_t source_addr_flags
;
1291 struct sort_result_combo
1293 struct sort_result
*results
;
1298 #if __BYTE_ORDER == __BIG_ENDIAN
1299 # define htonl_c(n) n
1301 # define htonl_c(n) __bswap_constant_32 (n)
1304 static const struct scopeentry
1313 } default_scopes
[] =
1315 /* Link-local addresses: scope 2. */
1316 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1317 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1318 /* Default: scope 14. */
1319 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1322 /* The label table. */
1323 static const struct scopeentry
*scopes
;
1327 get_scope (const struct sockaddr_in6
*in6
)
1330 if (in6
->sin6_family
== PF_INET6
)
1332 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1334 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1335 /* RFC 4291 2.5.3 says that the loopback address is to be
1336 treated like a link-local address. */
1337 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1339 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1342 /* XXX Is this the correct default behavior? */
1346 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1348 else if (in6
->sin6_family
== PF_INET
)
1350 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1355 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1356 == scopes
[cnt
].addr32
)
1357 return scopes
[cnt
].scope
;
1364 /* XXX What is a good default? */
1373 struct in6_addr prefix
;
1379 /* The label table. */
1380 static const struct prefixentry
*labels
;
1382 /* Default labels. */
1383 static const struct prefixentry default_labels
[] =
1385 /* See RFC 3484 for the details. */
1387 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1391 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1395 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1399 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1400 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1402 /* The next two entries differ from RFC 3484. We need to treat
1403 IPv6 site-local addresses special because they are never NATed,
1404 unlike site-locale IPv4 addresses. If this would not happen, on
1405 machines which have only IPv4 and IPv6 site-local addresses, the
1406 sorting would prefer the IPv6 site-local addresses, causing
1407 unnecessary delays when trying to connect to a global IPv6 address
1408 through a site-local IPv6 address. */
1410 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1414 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1417 /* Additional rule for Teredo tunnels. */
1419 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1423 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1429 /* The precedence table. */
1430 static const struct prefixentry
*precedence
;
1432 /* The default precedences. */
1433 static const struct prefixentry default_precedence
[] =
1435 /* See RFC 3484 for the details. */
1437 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1441 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1445 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1449 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1450 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1453 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1460 match_prefix (const struct sockaddr_in6
*in6
,
1461 const struct prefixentry
*list
, int default_val
)
1464 struct sockaddr_in6 in6_mem
;
1466 if (in6
->sin6_family
== PF_INET
)
1468 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1470 /* Construct a V4-to-6 mapped address. */
1471 in6_mem
.sin6_family
= PF_INET6
;
1472 in6_mem
.sin6_port
= in
->sin_port
;
1473 in6_mem
.sin6_flowinfo
= 0;
1474 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1475 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1476 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1477 in6_mem
.sin6_scope_id
= 0;
1481 else if (in6
->sin6_family
!= PF_INET6
)
1484 for (idx
= 0; ; ++idx
)
1486 unsigned int bits
= list
[idx
].bits
;
1487 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1488 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1502 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1508 return list
[idx
].val
;
1513 get_label (const struct sockaddr_in6
*in6
)
1515 /* XXX What is a good default value? */
1516 return match_prefix (in6
, labels
, INT_MAX
);
1521 get_precedence (const struct sockaddr_in6
*in6
)
1523 /* XXX What is a good default value? */
1524 return match_prefix (in6
, precedence
, 0);
1528 /* Find last bit set in a word. */
1534 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1535 if ((a
& mask
) != 0)
1542 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1544 const size_t idx1
= *(const size_t *) p1
;
1545 const size_t idx2
= *(const size_t *) p2
;
1546 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1547 struct sort_result
*a1
= &src
->results
[idx1
];
1548 struct sort_result
*a2
= &src
->results
[idx2
];
1550 /* Rule 1: Avoid unusable destinations.
1551 We have the got_source_addr flag set if the destination is reachable. */
1552 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1554 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1558 /* Rule 2: Prefer matching scope. Only interesting if both
1559 destination addresses are IPv6. */
1561 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1564 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1566 if (a1
->got_source_addr
)
1568 int a1_src_scope
= get_scope (&a1
->source_addr
);
1569 int a2_src_scope
= get_scope (&a2
->source_addr
);
1571 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1573 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1578 /* Rule 3: Avoid deprecated addresses. */
1579 if (a1
->got_source_addr
)
1581 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1582 && (a2
->source_addr_flags
& in6ai_deprecated
))
1584 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1585 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1589 /* Rule 4: Prefer home addresses. */
1590 if (a1
->got_source_addr
)
1592 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1593 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1595 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1596 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1600 /* Rule 5: Prefer matching label. */
1601 if (a1
->got_source_addr
)
1604 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1605 int a1_src_label
= get_label (&a1
->source_addr
);
1608 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1609 int a2_src_label
= get_label (&a2
->source_addr
);
1611 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1613 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1618 /* Rule 6: Prefer higher precedence. */
1620 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1622 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1624 if (a1_prec
> a2_prec
)
1626 if (a1_prec
< a2_prec
)
1630 /* Rule 7: Prefer native transport. */
1631 if (a1
->got_source_addr
)
1633 /* The same interface index means the same interface which means
1634 there is no difference in transport. This should catch many
1636 if (a1
->index
!= a2
->index
)
1638 int a1_native
= a1
->native
;
1639 int a2_native
= a2
->native
;
1641 if (a1_native
== -1 || a2_native
== -1)
1644 if (a1_native
== -1)
1646 /* If we do not have the information use 'native' as
1649 a1_index
= a1
->index
;
1652 a1_index
= 0xffffffffu
;
1655 if (a2_native
== -1)
1657 /* If we do not have the information use 'native' as
1660 a2_index
= a2
->index
;
1663 a2_index
= 0xffffffffu
;
1665 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1667 /* Fill in the results in all the records. */
1668 for (int i
= 0; i
< src
->nresults
; ++i
)
1669 if (src
->results
[i
].index
== a1_index
)
1671 assert (src
->results
[i
].native
== -1
1672 || src
->results
[i
].native
== a1_native
);
1673 src
->results
[i
].native
= a1_native
;
1675 else if (src
->results
[i
].index
== a2_index
)
1677 assert (src
->results
[i
].native
== -1
1678 || src
->results
[i
].native
== a2_native
);
1679 src
->results
[i
].native
= a2_native
;
1683 if (a1_native
&& !a2_native
)
1685 if (!a1_native
&& a2_native
)
1691 /* Rule 8: Prefer smaller scope. */
1692 if (a1_dst_scope
< a2_dst_scope
)
1694 if (a1_dst_scope
> a2_dst_scope
)
1698 /* Rule 9: Use longest matching prefix. */
1699 if (a1
->got_source_addr
1700 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1705 if (a1
->dest_addr
->ai_family
== PF_INET
)
1707 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1708 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1710 /* Outside of subnets, as defined by the network masks,
1711 common address prefixes for IPv4 addresses make no sense.
1712 So, define a non-zero value only if source and
1713 destination address are on the same subnet. */
1714 struct sockaddr_in
*in1_dst
1715 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1716 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1717 struct sockaddr_in
*in1_src
1718 = (struct sockaddr_in
*) &a1
->source_addr
;
1719 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1720 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1722 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1723 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1725 struct sockaddr_in
*in2_dst
1726 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1727 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1728 struct sockaddr_in
*in2_src
1729 = (struct sockaddr_in
*) &a2
->source_addr
;
1730 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1731 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1733 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1734 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1736 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1738 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1739 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1741 struct sockaddr_in6
*in1_dst
;
1742 struct sockaddr_in6
*in1_src
;
1743 struct sockaddr_in6
*in2_dst
;
1744 struct sockaddr_in6
*in2_src
;
1746 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1747 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1748 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1749 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1752 for (i
= 0; i
< 4; ++i
)
1753 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1754 != in1_src
->sin6_addr
.s6_addr32
[i
]
1755 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1756 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1761 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1762 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1763 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1764 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1775 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1776 compare with the value indicating the order in which the entries
1777 have been received from the services. NB: no two entries can have
1778 the same order so the test will never return zero. */
1779 return idx1
< idx2
? -1 : 1;
1784 in6aicmp (const void *p1
, const void *p2
)
1786 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1787 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1789 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1793 /* Name of the config file for RFC 3484 sorting (for now). */
1794 #define GAICONF_FNAME "/etc/gai.conf"
1797 /* Non-zero if we are supposed to reload the config file automatically
1798 whenever it changed. */
1799 static int gaiconf_reload_flag
;
1801 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1802 static int gaiconf_reload_flag_ever_set
;
1804 /* Last modification time. */
1805 #ifdef _STATBUF_ST_NSEC
1807 static struct timespec gaiconf_mtime
;
1810 save_gaiconf_mtime (const struct stat64
*st
)
1812 gaiconf_mtime
= st
->st_mtim
;
1816 check_gaiconf_mtime (const struct stat64
*st
)
1818 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1819 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1824 static time_t gaiconf_mtime
;
1827 save_gaiconf_mtime (const struct stat64
*st
)
1829 gaiconf_mtime
= st
->st_mtime
;
1833 check_gaiconf_mtime (const struct stat64
*st
)
1835 return st
->st_mtime
== gaiconf_mtime
;
1841 libc_freeres_fn(fini
)
1843 if (labels
!= default_labels
)
1845 const struct prefixentry
*old
= labels
;
1846 labels
= default_labels
;
1847 free ((void *) old
);
1850 if (precedence
!= default_precedence
)
1852 const struct prefixentry
*old
= precedence
;
1853 precedence
= default_precedence
;
1854 free ((void *) old
);
1857 if (scopes
!= default_scopes
)
1859 const struct scopeentry
*old
= scopes
;
1860 scopes
= default_scopes
;
1861 free ((void *) old
);
1868 struct prefixentry entry
;
1869 struct prefixlist
*next
;
1875 struct scopeentry entry
;
1876 struct scopelist
*next
;
1881 free_prefixlist (struct prefixlist
*list
)
1883 while (list
!= NULL
)
1885 struct prefixlist
*oldp
= list
;
1893 free_scopelist (struct scopelist
*list
)
1895 while (list
!= NULL
)
1897 struct scopelist
*oldp
= list
;
1905 prefixcmp (const void *p1
, const void *p2
)
1907 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1908 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1910 if (e1
->bits
< e2
->bits
)
1912 if (e1
->bits
== e2
->bits
)
1919 scopecmp (const void *p1
, const void *p2
)
1921 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1922 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1924 if (e1
->netmask
> e2
->netmask
)
1926 if (e1
->netmask
== e2
->netmask
)
1935 struct prefixlist
*labellist
= NULL
;
1936 size_t nlabellist
= 0;
1937 bool labellist_nullbits
= false;
1938 struct prefixlist
*precedencelist
= NULL
;
1939 size_t nprecedencelist
= 0;
1940 bool precedencelist_nullbits
= false;
1941 struct scopelist
*scopelist
= NULL
;
1942 size_t nscopelist
= 0;
1943 bool scopelist_nullbits
= false;
1945 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1949 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1958 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1960 while (!feof_unlocked (fp
))
1962 ssize_t n
= __getline (&line
, &linelen
, fp
);
1966 /* Handle comments. No escaping possible so this is easy. */
1967 char *cp
= strchr (line
, '#');
1972 while (isspace (*cp
))
1976 while (*cp
!= '\0' && !isspace (*cp
))
1978 size_t cmdlen
= cp
- cmd
;
1982 while (isspace (*cp
))
1986 while (*cp
!= '\0' && !isspace (*cp
))
1988 size_t val1len
= cp
- cmd
;
1990 /* We always need at least two values. */
1996 while (isspace (*cp
))
2000 while (*cp
!= '\0' && !isspace (*cp
))
2003 /* Ignore the rest of the line. */
2006 struct prefixlist
**listp
;
2012 if (strcmp (cmd
, "label") == 0)
2014 struct in6_addr prefix
;
2015 unsigned long int bits
;
2016 unsigned long int val
;
2021 nullbitsp
= &labellist_nullbits
;
2026 cp
= strchr (val1
, '/');
2029 if (inet_pton (AF_INET6
, val1
, &prefix
)
2031 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2035 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2040 struct prefixlist
*newp
= malloc (sizeof (*newp
));
2048 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
2049 newp
->entry
.bits
= bits
;
2050 newp
->entry
.val
= val
;
2051 newp
->next
= *listp
;
2054 *nullbitsp
|= bits
== 0;
2060 if (strcmp (cmd
, "reload") == 0)
2062 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2063 if (gaiconf_reload_flag
)
2064 gaiconf_reload_flag_ever_set
= 1;
2069 if (strcmp (cmd
, "scopev4") == 0)
2071 struct in6_addr prefix
;
2072 unsigned long int bits
;
2073 unsigned long int val
;
2078 cp
= strchr (val1
, '/');
2081 if (inet_pton (AF_INET6
, val1
, &prefix
))
2084 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2086 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2091 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2096 struct scopelist
*newp
;
2098 newp
= malloc (sizeof (*newp
));
2106 newp
->entry
.netmask
= htonl (bits
!= 96
2110 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2111 & newp
->entry
.netmask
);
2112 newp
->entry
.scope
= val
;
2113 newp
->next
= scopelist
;
2116 scopelist_nullbits
|= bits
== 96;
2119 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2121 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2125 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2137 if (strcmp (cmd
, "precedence") == 0)
2139 listp
= &precedencelist
;
2140 lenp
= &nprecedencelist
;
2141 nullbitsp
= &precedencelist_nullbits
;
2152 /* Create the array for the labels. */
2153 struct prefixentry
*new_labels
;
2156 if (!labellist_nullbits
)
2158 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2159 if (new_labels
== NULL
)
2163 if (!labellist_nullbits
)
2166 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2167 new_labels
[i
].bits
= 0;
2168 new_labels
[i
].val
= 1;
2171 struct prefixlist
*l
= labellist
;
2174 new_labels
[i
] = l
->entry
;
2177 free_prefixlist (labellist
);
2179 /* Sort the entries so that the most specific ones are at
2181 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2184 new_labels
= (struct prefixentry
*) default_labels
;
2186 struct prefixentry
*new_precedence
;
2187 if (nprecedencelist
> 0)
2189 if (!precedencelist_nullbits
)
2191 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2192 if (new_precedence
== NULL
)
2194 if (new_labels
!= default_labels
)
2199 int i
= nprecedencelist
;
2200 if (!precedencelist_nullbits
)
2203 memset (&new_precedence
[i
].prefix
, '\0',
2204 sizeof (struct in6_addr
));
2205 new_precedence
[i
].bits
= 0;
2206 new_precedence
[i
].val
= 40;
2209 struct prefixlist
*l
= precedencelist
;
2212 new_precedence
[i
] = l
->entry
;
2215 free_prefixlist (precedencelist
);
2217 /* Sort the entries so that the most specific ones are at
2219 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2223 new_precedence
= (struct prefixentry
*) default_precedence
;
2225 struct scopeentry
*new_scopes
;
2228 if (!scopelist_nullbits
)
2230 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2231 if (new_scopes
== NULL
)
2233 if (new_labels
!= default_labels
)
2235 if (new_precedence
!= default_precedence
)
2236 free (new_precedence
);
2241 if (!scopelist_nullbits
)
2244 new_scopes
[i
].addr32
= 0;
2245 new_scopes
[i
].netmask
= 0;
2246 new_scopes
[i
].scope
= 14;
2249 struct scopelist
*l
= scopelist
;
2252 new_scopes
[i
] = l
->entry
;
2255 free_scopelist (scopelist
);
2257 /* Sort the entries so that the most specific ones are at
2259 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2263 new_scopes
= (struct scopeentry
*) default_scopes
;
2265 /* Now we are ready to replace the values. */
2266 const struct prefixentry
*old
= labels
;
2267 labels
= new_labels
;
2268 if (old
!= default_labels
)
2269 free ((void *) old
);
2272 precedence
= new_precedence
;
2273 if (old
!= default_precedence
)
2274 free ((void *) old
);
2276 const struct scopeentry
*oldscope
= scopes
;
2277 scopes
= new_scopes
;
2278 if (oldscope
!= default_scopes
)
2279 free ((void *) oldscope
);
2281 save_gaiconf_mtime (&st
);
2286 free_prefixlist (labellist
);
2287 free_prefixlist (precedencelist
);
2288 free_scopelist (scopelist
);
2290 /* If we previously read the file but it is gone now, free the
2291 old data and use the builtin one. Leave the reload flag
2299 gaiconf_reload (void)
2302 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2303 || !check_gaiconf_mtime (&st
))
2309 getaddrinfo (const char *name
, const char *service
,
2310 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2312 int i
= 0, last_i
= 0;
2314 struct addrinfo
*p
= NULL
;
2315 struct gaih_service gaih_service
, *pservice
;
2316 struct addrinfo local_hints
;
2318 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2321 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2324 if (name
== NULL
&& service
== NULL
)
2328 hints
= &default_hints
;
2331 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2333 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2334 |AI_IDN_USE_STD3_ASCII_RULES
2336 |AI_NUMERICSERV
|AI_ALL
))
2337 return EAI_BADFLAGS
;
2339 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2340 return EAI_BADFLAGS
;
2342 struct in6addrinfo
*in6ai
= NULL
;
2343 size_t in6ailen
= 0;
2344 bool seen_ipv4
= false;
2345 bool seen_ipv6
= false;
2346 bool check_pf_called
= false;
2348 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2350 /* We might need information about what interfaces are available.
2351 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2352 cannot cache the results since new interfaces could be added at
2354 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2355 check_pf_called
= true;
2357 /* Now make a decision on what we return, if anything. */
2358 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2360 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2361 narrow down the search. */
2362 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2364 local_hints
= *hints
;
2365 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2366 hints
= &local_hints
;
2369 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2370 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2372 /* We cannot possibly return a valid answer. */
2373 __free_in6ai (in6ai
);
2378 if (service
&& service
[0])
2381 gaih_service
.name
= service
;
2382 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2385 if (hints
->ai_flags
& AI_NUMERICSERV
)
2387 __free_in6ai (in6ai
);
2391 gaih_service
.num
= -1;
2394 pservice
= &gaih_service
;
2399 struct addrinfo
**end
= &p
;
2401 unsigned int naddrs
= 0;
2402 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2403 || hints
->ai_family
== AF_INET6
)
2405 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2409 __free_in6ai (in6ai
);
2411 return -(last_i
& GAIH_EAI
);
2415 end
= &((*end
)->ai_next
);
2421 __free_in6ai (in6ai
);
2427 /* Read the config file. */
2428 __libc_once_define (static, once
);
2429 __typeof (once
) old_once
= once
;
2430 __libc_once (once
, gaiconf_init
);
2431 /* Sort results according to RFC 3484. */
2432 struct sort_result
*results
;
2435 struct addrinfo
*last
= NULL
;
2436 char *canonname
= NULL
;
2437 bool malloc_results
;
2438 size_t alloc_size
= nresults
* (sizeof (*results
) + sizeof (size_t));
2441 = !__libc_use_alloca (alloc_size
);
2444 results
= malloc (alloc_size
);
2445 if (results
== NULL
)
2447 __free_in6ai (in6ai
);
2452 results
= alloca (alloc_size
);
2453 order
= (size_t *) (results
+ nresults
);
2455 /* Now we definitely need the interface information. */
2456 if (! check_pf_called
)
2457 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2459 /* If we have information about deprecated and temporary addresses
2460 sort the array now. */
2462 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2467 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2469 results
[i
].dest_addr
= q
;
2470 results
[i
].native
= -1;
2473 /* If we just looked up the address for a different
2474 protocol, reuse the result. */
2475 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2476 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2478 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2479 results
[i
- 1].source_addr_len
);
2480 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2481 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2482 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2483 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2484 results
[i
].index
= results
[i
- 1].index
;
2488 results
[i
].got_source_addr
= false;
2489 results
[i
].source_addr_flags
= 0;
2490 results
[i
].prefixlen
= 0;
2491 results
[i
].index
= 0xffffffffu
;
2493 /* We overwrite the type with SOCK_DGRAM since we do not
2494 want connect() to connect to the other side. If we
2495 cannot determine the source address remember this
2497 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2501 close_not_cancel_no_status (fd
);
2503 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2507 /* Reset the connection. */
2508 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2509 __connect (fd
, &sa
, sizeof (sa
));
2512 socklen_t sl
= sizeof (results
[i
].source_addr
);
2514 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2515 && __getsockname (fd
,
2516 (struct sockaddr
*) &results
[i
].source_addr
,
2519 results
[i
].source_addr_len
= sl
;
2520 results
[i
].got_source_addr
= true;
2524 /* See whether the source address is on the list of
2525 deprecated or temporary addresses. */
2526 struct in6addrinfo tmp
;
2528 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2530 struct sockaddr_in
*sinp
2531 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2534 tmp
.addr
[2] = htonl (0xffff);
2535 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2539 struct sockaddr_in6
*sin6p
2540 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2541 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2544 struct in6addrinfo
*found
2545 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2549 results
[i
].source_addr_flags
= found
->flags
;
2550 results
[i
].prefixlen
= found
->prefixlen
;
2551 results
[i
].index
= found
->index
;
2555 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2557 /* We have to convert the address. The socket is
2558 IPv6 and the request is for IPv4. */
2559 struct sockaddr_in6
*sin6
2560 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2561 struct sockaddr_in
*sin
2562 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2563 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2564 sin
->sin_family
= AF_INET
;
2565 /* We do not have to initialize sin_port since this
2566 fields has the same position and size in the IPv6
2568 assert (offsetof (struct sockaddr_in
, sin_port
)
2569 == offsetof (struct sockaddr_in6
, sin6_port
));
2570 assert (sizeof (sin
->sin_port
)
2571 == sizeof (sin6
->sin6_port
));
2572 memcpy (&sin
->sin_addr
,
2573 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2574 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2577 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2578 && q
->ai_family
== AF_INET
)
2579 /* This could mean IPv6 sockets are IPv6-only. */
2582 /* Just make sure that if we have to process the same
2583 address again we do not copy any memory. */
2584 results
[i
].source_addr_len
= 0;
2587 /* Remember the canonical name. */
2588 if (q
->ai_canonname
!= NULL
)
2590 assert (canonname
== NULL
);
2591 canonname
= q
->ai_canonname
;
2592 q
->ai_canonname
= NULL
;
2597 close_not_cancel_no_status (fd
);
2599 /* We got all the source addresses we can get, now sort using
2601 struct sort_result_combo src
2602 = { .results
= results
, .nresults
= nresults
};
2603 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2605 __libc_lock_define_initialized (static, lock
);
2607 __libc_lock_lock (lock
);
2608 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2610 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2611 __libc_lock_unlock (lock
);
2614 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2616 /* Queue the results up as they come out of sorting. */
2617 q
= p
= results
[order
[0]].dest_addr
;
2618 for (i
= 1; i
< nresults
; ++i
)
2619 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2622 /* Fill in the canonical name into the new first entry. */
2623 p
->ai_canonname
= canonname
;
2629 __free_in6ai (in6ai
);
2637 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2639 libc_hidden_def (getaddrinfo
)
2641 nss_interface_function (getaddrinfo
)
2644 freeaddrinfo (struct addrinfo
*ai
)
2652 free (p
->ai_canonname
);
2656 libc_hidden_def (freeaddrinfo
)