1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
47 #include <stdio_ext.h>
50 #include <arpa/inet.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
55 #include <sys/types.h>
57 #include <sys/utsname.h>
60 #include <bits/libc-lock.h>
61 #include <not-cancel.h>
62 #include <nscd/nscd-client.h>
63 #include <nscd/nscd_proto.h>
64 #include <resolv/res_hconf.h>
67 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
68 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
70 # include <libidn/idna.h>
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77 # define UNIX_PATH_MAX 108
88 struct gaih_servtuple
*next
;
94 static const struct gaih_servtuple nullserv
;
106 /* Values for `protoflag'. */
107 #define GAI_PROTO_NOSERVICE 1
108 #define GAI_PROTO_PROTOANY 2
110 static const struct gaih_typeproto gaih_inet_typeproto
[] =
112 { 0, 0, 0, false, "" },
113 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
114 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
115 #if defined SOCK_DCCP && defined IPPROTO_DCCP
116 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
118 #ifdef IPPROTO_UDPLITE
119 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
122 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
123 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
125 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
126 { 0, 0, 0, false, "" }
132 int (*gaih
)(const char *name
, const struct gaih_service
*service
,
133 const struct addrinfo
*req
, struct addrinfo
**pai
,
134 unsigned int *naddrs
);
137 static const struct addrinfo default_hints
=
139 .ai_flags
= AI_DEFAULT
,
140 .ai_family
= PF_UNSPEC
,
145 .ai_canonname
= NULL
,
151 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
152 const struct addrinfo
*req
, struct gaih_servtuple
*st
)
155 size_t tmpbuflen
= 1024;
162 tmpbuf
= __alloca (tmpbuflen
);
164 r
= __getservbyname_r (servicename
, tp
->name
, &ts
, tmpbuf
, tmpbuflen
,
166 if (r
!= 0 || s
== NULL
)
171 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
177 st
->socktype
= tp
->socktype
;
178 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
179 ? req
->ai_protocol
: tp
->protocol
);
180 st
->port
= s
->s_port
;
185 #define gethosts(_family, _type) \
191 char *localcanon = NULL; \
195 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
196 &rc, &herrno, NULL, &localcanon)); \
197 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
199 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
201 if (status == NSS_STATUS_SUCCESS && rc == 0) \
207 if (herrno == NETDB_INTERNAL) \
209 __set_h_errno (herrno); \
210 _res.options |= old_res_options & RES_USE_INET6; \
211 return -EAI_SYSTEM; \
213 if (herrno == TRY_AGAIN) \
214 no_data = EAI_AGAIN; \
216 no_data = herrno == NO_DATA; \
218 else if (h != NULL) \
220 for (i = 0; h->h_addr_list[i]; i++) \
224 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
225 (*pat)->scopeid = 0; \
227 uint32_t *addr = (*pat)->addr; \
228 (*pat)->next = NULL; \
229 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
230 if (_family == AF_INET && req->ai_family == AF_INET6) \
232 (*pat)->family = AF_INET6; \
233 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
234 addr[2] = htonl (0xffff); \
240 (*pat)->family = _family; \
241 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
243 pat = &((*pat)->next); \
246 if (localcanon != NULL && canon == NULL) \
247 canon = strdupa (localcanon); \
249 if (_family == AF_INET6 && i > 0) \
255 typedef enum nss_status (*nss_gethostbyname4_r
)
256 (const char *name
, struct gaih_addrtuple
**pat
,
257 char *buffer
, size_t buflen
, int *errnop
,
258 int *h_errnop
, int32_t *ttlp
);
259 typedef enum nss_status (*nss_gethostbyname3_r
)
260 (const char *name
, int af
, struct hostent
*host
,
261 char *buffer
, size_t buflen
, int *errnop
,
262 int *h_errnop
, int32_t *ttlp
, char **canonp
);
263 typedef enum nss_status (*nss_getcanonname_r
)
264 (const char *name
, char *buffer
, size_t buflen
, char **result
,
265 int *errnop
, int *h_errnop
);
266 extern service_user
*__nss_hosts_database attribute_hidden
;
270 gaih_inet (const char *name
, const struct gaih_service
*service
,
271 const struct addrinfo
*req
, struct addrinfo
**pai
,
272 unsigned int *naddrs
)
274 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
275 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
276 struct gaih_addrtuple
*at
= NULL
;
278 bool got_ipv6
= false;
279 const char *canon
= NULL
;
280 const char *orig_name
= name
;
281 size_t alloca_used
= 0;
283 if (req
->ai_protocol
|| req
->ai_socktype
)
288 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
289 || (req
->ai_protocol
!= 0
290 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
291 && req
->ai_protocol
!= tp
->protocol
)))
296 if (req
->ai_socktype
)
297 return GAIH_OKIFUNSPEC
| -EAI_SOCKTYPE
;
299 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
306 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
307 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
309 if (service
->num
< 0)
313 st
= (struct gaih_servtuple
*)
314 alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
316 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
)))
321 struct gaih_servtuple
**pst
= &st
;
322 for (tp
++; tp
->name
[0]; tp
++)
324 struct gaih_servtuple
*newp
;
326 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
329 if (req
->ai_socktype
!= 0
330 && req
->ai_socktype
!= tp
->socktype
)
332 if (req
->ai_protocol
!= 0
333 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
334 && req
->ai_protocol
!= tp
->protocol
)
337 newp
= (struct gaih_servtuple
*)
338 alloca_account (sizeof (struct gaih_servtuple
),
341 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, newp
)))
343 if (rc
& GAIH_OKIFUNSPEC
)
351 if (st
== (struct gaih_servtuple
*) &nullserv
)
352 return GAIH_OKIFUNSPEC
| -EAI_SERVICE
;
357 port
= htons (service
->num
);
365 if (req
->ai_socktype
|| req
->ai_protocol
)
367 st
= alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
369 st
->socktype
= tp
->socktype
;
370 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
371 ? req
->ai_protocol
: tp
->protocol
);
376 /* Neither socket type nor protocol is set. Return all socket types
378 struct gaih_servtuple
**lastp
= &st
;
379 for (++tp
; tp
->name
[0]; ++tp
)
382 struct gaih_servtuple
*newp
;
384 newp
= alloca_account (sizeof (struct gaih_servtuple
),
387 newp
->socktype
= tp
->socktype
;
388 newp
->protocol
= tp
->protocol
;
397 bool malloc_name
= false;
398 bool malloc_addrmem
= false;
399 struct gaih_addrtuple
*addrmem
= NULL
;
400 bool malloc_canonbuf
= false;
401 char *canonbuf
= NULL
;
402 bool malloc_tmpbuf
= false;
407 at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
408 at
->family
= AF_UNSPEC
;
413 if (req
->ai_flags
& AI_IDN
)
416 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
417 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
418 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
419 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
422 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
423 if (rc
!= IDNA_SUCCESS
)
425 /* No need to jump to free_and_return here. */
426 if (rc
== IDNA_MALLOC_ERROR
)
428 if (rc
== IDNA_DLOPEN_ERROR
)
430 return -EAI_IDN_ENCODE
;
432 /* In case the output string is the same as the input string
433 no new string has been allocated. */
442 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
444 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
445 at
->family
= AF_INET
;
446 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
448 at
->addr
[3] = at
->addr
[0];
449 at
->addr
[2] = htonl (0xffff);
452 at
->family
= AF_INET6
;
456 result
= -EAI_ADDRFAMILY
;
457 goto free_and_return
;
460 if (req
->ai_flags
& AI_CANONNAME
)
463 else if (at
->family
== AF_UNSPEC
)
465 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
469 bool malloc_namebuf
= false;
470 char *namebuf
= (char *) name
;
472 if (__builtin_expect (scope_delim
!= NULL
, 0))
478 if (__libc_use_alloca (alloca_used
479 + scope_delim
- name
+ 1))
481 namebuf
= alloca_account (scope_delim
- name
+ 1,
483 *((char *) __mempcpy (namebuf
, name
,
484 scope_delim
- name
)) = '\0';
488 namebuf
= strndup (name
, scope_delim
- name
);
491 assert (!malloc_name
);
494 malloc_namebuf
= true;
499 e
= inet_pton (AF_INET6
, namebuf
, at
->addr
);
503 else if (scope_delim
!= NULL
&& malloc_name
)
504 /* Undo what we did above. */
505 *scope_delim
= SCOPE_DELIMITER
;
509 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
510 at
->family
= AF_INET6
;
511 else if (req
->ai_family
== AF_INET
512 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
514 at
->addr
[0] = at
->addr
[3];
515 at
->family
= AF_INET
;
519 result
= -EAI_ADDRFAMILY
;
520 goto free_and_return
;
523 if (scope_delim
!= NULL
)
525 int try_numericscope
= 0;
526 if (IN6_IS_ADDR_LINKLOCAL (at
->addr
)
527 || IN6_IS_ADDR_MC_LINKLOCAL (at
->addr
))
529 at
->scopeid
= if_nametoindex (scope_delim
+ 1);
530 if (at
->scopeid
== 0)
531 try_numericscope
= 1;
534 try_numericscope
= 1;
536 if (try_numericscope
!= 0)
539 assert (sizeof (uint32_t) <= sizeof (unsigned long));
540 at
->scopeid
= (uint32_t) strtoul (scope_delim
+ 1, &end
,
544 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
545 goto free_and_return
;
550 if (req
->ai_flags
& AI_CANONNAME
)
555 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
557 struct gaih_addrtuple
**pat
= &at
;
559 int no_inet6_data
= 0;
560 service_user
*nip
= NULL
;
561 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
562 enum nss_status status
= NSS_STATUS_UNAVAIL
;
566 /* If we do not have to look for IPv6 addresses, use
567 the simple, old functions, which do not support
569 if (req
->ai_family
== AF_INET
)
571 size_t tmpbuflen
= 512;
572 assert (tmpbuf
== NULL
);
573 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
581 rc
= __gethostbyname2_r (name
, AF_INET
, &th
, tmpbuf
,
582 tmpbuflen
, &h
, &herrno
);
583 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
587 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
588 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
593 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
597 result
= -EAI_MEMORY
;
598 goto free_and_return
;
601 malloc_tmpbuf
= true;
602 tmpbuflen
= 2 * tmpbuflen
;
611 /* We found data, count the number of addresses. */
612 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
614 if (i
> 0 && *pat
!= NULL
)
617 if (__libc_use_alloca (alloca_used
618 + i
* sizeof (struct gaih_addrtuple
)))
619 addrmem
= alloca_account (i
* sizeof (struct gaih_addrtuple
),
624 * sizeof (struct gaih_addrtuple
));
627 result
= -EAI_MEMORY
;
628 goto free_and_return
;
630 malloc_addrmem
= true;
633 /* Now convert it into the list. */
634 struct gaih_addrtuple
*addrfree
= addrmem
;
635 for (i
= 0; h
->h_addr_list
[i
]; ++i
)
643 (*pat
)->family
= AF_INET
;
644 memcpy ((*pat
)->addr
, h
->h_addr_list
[i
],
646 pat
= &((*pat
)->next
);
652 if (herrno
== NETDB_INTERNAL
)
654 __set_h_errno (herrno
);
655 result
= -EAI_SYSTEM
;
657 else if (herrno
== TRY_AGAIN
)
660 /* We made requests but they turned out no data.
661 The name is known, though. */
662 result
= GAIH_OKIFUNSPEC
| -EAI_NODATA
;
664 goto free_and_return
;
671 if (__nss_not_use_nscd_hosts
> 0
672 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
673 __nss_not_use_nscd_hosts
= 0;
675 if (!__nss_not_use_nscd_hosts
676 && !__nss_database_custom
[NSS_DBSIDX_hosts
])
678 /* Try to use nscd. */
679 struct nscd_ai_result
*air
= NULL
;
681 int err
= __nscd_getai (name
, &air
, &herrno
);
684 /* Transform into gaih_addrtuple list. */
685 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
686 char *addrs
= air
->addrs
;
688 if (__libc_use_alloca (alloca_used
689 + air
->naddrs
* sizeof (struct gaih_addrtuple
)))
690 addrmem
= alloca_account (air
->naddrs
691 * sizeof (struct gaih_addrtuple
),
695 addrmem
= malloc (air
->naddrs
696 * sizeof (struct gaih_addrtuple
));
699 result
= -EAI_MEMORY
;
700 goto free_and_return
;
702 malloc_addrmem
= true;
705 struct gaih_addrtuple
*addrfree
= addrmem
;
706 for (int i
= 0; i
< air
->naddrs
; ++i
)
708 socklen_t size
= (air
->family
[i
] == AF_INET
709 ? INADDRSZ
: IN6ADDRSZ
);
715 uint32_t *pataddr
= (*pat
)->addr
;
717 if (added_canon
|| air
->canon
== NULL
)
719 else if (canonbuf
== NULL
)
721 size_t canonlen
= strlen (air
->canon
) + 1;
722 if ((req
->ai_flags
& AI_CANONIDN
) != 0
723 && __libc_use_alloca (alloca_used
+ canonlen
))
724 canonbuf
= alloca_account (canonlen
, alloca_used
);
727 canonbuf
= malloc (canonlen
);
728 if (canonbuf
== NULL
)
730 result
= -EAI_MEMORY
;
731 goto free_and_return
;
733 malloc_canonbuf
= true;
735 canon
= (*pat
)->name
= memcpy (canonbuf
, air
->canon
,
739 if (air
->family
[i
] == AF_INET
740 && req
->ai_family
== AF_INET6
741 && (req
->ai_flags
& AI_V4MAPPED
))
743 (*pat
)->family
= AF_INET6
;
744 pataddr
[3] = *(uint32_t *) addrs
;
745 pataddr
[2] = htonl (0xffff);
748 pat
= &((*pat
)->next
);
751 else if (req
->ai_family
== AF_UNSPEC
752 || air
->family
[i
] == req
->ai_family
)
754 (*pat
)->family
= air
->family
[i
];
755 memcpy (pataddr
, addrs
, size
);
756 pat
= &((*pat
)->next
);
758 if (air
->family
[i
] == AF_INET6
)
766 if (at
->family
== AF_UNSPEC
)
768 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
769 goto free_and_return
;
775 /* The database contains a negative entry. */
776 goto free_and_return
;
777 else if (__nss_not_use_nscd_hosts
== 0)
779 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
780 result
= -EAI_MEMORY
;
781 else if (herrno
== TRY_AGAIN
)
784 result
= -EAI_SYSTEM
;
786 goto free_and_return
;
791 if (__nss_hosts_database
!= NULL
)
794 nip
= __nss_hosts_database
;
797 no_more
= __nss_database_lookup ("hosts", NULL
,
798 "dns [!UNAVAIL=return] files",
801 /* Initialize configurations. */
802 if (__builtin_expect (!_res_hconf
.initialized
, 0))
804 if (__res_maybe_init (&_res
, 0) == -1)
807 /* If we are looking for both IPv4 and IPv6 address we don't
808 want the lookup functions to automatically promote IPv4
809 addresses to IPv6 addresses. Currently this is decided
810 by setting the RES_USE_INET6 bit in _res.options. */
811 old_res_options
= _res
.options
;
812 _res
.options
&= ~RES_USE_INET6
;
814 size_t tmpbuflen
= 1024;
815 malloc_tmpbuf
= !__libc_use_alloca (alloca_used
+ tmpbuflen
);
816 assert (tmpbuf
== NULL
);
818 tmpbuf
= alloca_account (tmpbuflen
, alloca_used
);
821 tmpbuf
= malloc (tmpbuflen
);
824 _res
.options
|= old_res_options
& RES_USE_INET6
;
825 result
= -EAI_MEMORY
;
826 goto free_and_return
;
833 nss_gethostbyname4_r fct4
834 = __nss_lookup_function (nip
, "gethostbyname4_r");
842 status
= DL_CALL_FCT (fct4
, (name
, pat
, tmpbuf
,
843 tmpbuflen
, &rc
, &herrno
,
845 if (status
== NSS_STATUS_SUCCESS
)
847 if (status
!= NSS_STATUS_TRYAGAIN
848 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
850 if (status
== NSS_STATUS_TRYAGAIN
851 && herrno
== TRY_AGAIN
)
854 no_data
= herrno
== NO_DATA
;
859 && __libc_use_alloca (alloca_used
+ 2 * tmpbuflen
))
860 tmpbuf
= extend_alloca_account (tmpbuf
, tmpbuflen
,
865 char *newp
= realloc (malloc_tmpbuf
? tmpbuf
: NULL
,
869 _res
.options
|= old_res_options
& RES_USE_INET6
;
870 result
= -EAI_MEMORY
;
871 goto free_and_return
;
874 malloc_tmpbuf
= true;
875 tmpbuflen
= 2 * tmpbuflen
;
879 if (status
== NSS_STATUS_SUCCESS
)
884 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
885 canon
= (*pat
)->name
;
889 if ((*pat
)->family
== AF_INET
890 && req
->ai_family
== AF_INET6
891 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
893 uint32_t *pataddr
= (*pat
)->addr
;
894 (*pat
)->family
= AF_INET6
;
895 pataddr
[3] = pataddr
[0];
896 pataddr
[2] = htonl (0xffff);
899 pat
= &((*pat
)->next
);
902 else if (req
->ai_family
== AF_UNSPEC
903 || (*pat
)->family
== req
->ai_family
)
905 pat
= &((*pat
)->next
);
908 if (req
->ai_family
== AF_INET6
)
912 *pat
= ((*pat
)->next
);
916 no_inet6_data
= no_data
;
920 nss_gethostbyname3_r fct
= NULL
;
921 if (req
->ai_flags
& AI_CANONNAME
)
922 /* No need to use this function if we do not look for
923 the canonical name. The function does not exist in
924 all NSS modules and therefore the lookup would
926 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
928 /* We are cheating here. The gethostbyname2_r
929 function does not have the same interface as
930 gethostbyname3_r but the extra arguments the
931 latter takes are added at the end. So the
932 gethostbyname2_r code will just ignore them. */
933 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
937 if (req
->ai_family
== AF_INET6
938 || req
->ai_family
== AF_UNSPEC
)
940 gethosts (AF_INET6
, struct in6_addr
);
941 no_inet6_data
= no_data
;
942 inet6_status
= status
;
944 if (req
->ai_family
== AF_INET
945 || req
->ai_family
== AF_UNSPEC
946 || (req
->ai_family
== AF_INET6
947 && (req
->ai_flags
& AI_V4MAPPED
)
948 /* Avoid generating the mapped addresses if we
949 know we are not going to need them. */
950 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
952 gethosts (AF_INET
, struct in_addr
);
954 if (req
->ai_family
== AF_INET
)
956 no_inet6_data
= no_data
;
957 inet6_status
= status
;
961 /* If we found one address for AF_INET or AF_INET6,
962 don't continue the search. */
963 if (inet6_status
== NSS_STATUS_SUCCESS
964 || status
== NSS_STATUS_SUCCESS
)
966 if ((req
->ai_flags
& AI_CANONNAME
) != 0
969 /* If we need the canonical name, get it
970 from the same service as the result. */
971 nss_getcanonname_r cfct
;
974 cfct
= __nss_lookup_function (nip
,
978 const size_t max_fqdn_len
= 256;
979 if ((req
->ai_flags
& AI_CANONIDN
) != 0
980 && __libc_use_alloca (alloca_used
982 canonbuf
= alloca_account (max_fqdn_len
,
986 canonbuf
= malloc (max_fqdn_len
);
987 if (canonbuf
== NULL
)
990 |= old_res_options
& RES_USE_INET6
;
991 result
= -EAI_MEMORY
;
992 goto free_and_return
;
994 malloc_canonbuf
= true;
998 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
1002 == NSS_STATUS_SUCCESS
)
1006 /* Set to name now to avoid using
1008 if (malloc_canonbuf
)
1011 malloc_canonbuf
= false;
1017 status
= NSS_STATUS_SUCCESS
;
1021 /* We can have different states for AF_INET and
1022 AF_INET6. Try to find a useful one for both. */
1023 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
1024 status
= NSS_STATUS_TRYAGAIN
;
1025 else if (status
== NSS_STATUS_UNAVAIL
1026 && inet6_status
!= NSS_STATUS_UNAVAIL
)
1027 status
= inet6_status
;
1031 status
= NSS_STATUS_UNAVAIL
;
1034 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
1037 if (nip
->next
== NULL
)
1043 _res
.options
|= old_res_options
& RES_USE_INET6
;
1045 if (no_data
!= 0 && no_inet6_data
!= 0)
1047 /* If both requests timed out report this. */
1048 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
1049 result
= -EAI_AGAIN
;
1051 /* We made requests but they turned out no data. The name
1052 is known, though. */
1053 result
= GAIH_OKIFUNSPEC
| -EAI_NODATA
;
1055 goto free_and_return
;
1060 if (at
->family
== AF_UNSPEC
)
1062 result
= GAIH_OKIFUNSPEC
| -EAI_NONAME
;
1063 goto free_and_return
;
1068 struct gaih_addrtuple
*atr
;
1069 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
1070 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
1072 if (req
->ai_family
== AF_UNSPEC
)
1074 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
1075 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1078 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1080 at
->family
= AF_INET6
;
1081 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1082 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1086 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1088 atr
->family
= AF_INET
;
1089 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1090 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1095 struct gaih_servtuple
*st2
;
1096 struct gaih_addrtuple
*at2
= at
;
1101 buffer is the size of an unformatted IPv6 address in printable format.
1105 /* Only the first entry gets the canonical name. */
1106 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1108 char *tmpbuf2
= NULL
;
1109 bool malloc_tmpbuf2
= false;
1113 struct hostent
*h
= NULL
;
1116 size_t tmpbuf2len
= 512;
1120 if (__libc_use_alloca (alloca_used
+ 2 * tmpbuf2len
))
1121 tmpbuf2
= extend_alloca_account (tmpbuf2
, tmpbuf2len
,
1126 char *newp
= realloc (malloc_tmpbuf2
? tmpbuf2
: NULL
,
1132 result
= -EAI_MEMORY
;
1133 goto free_and_return
;
1137 tmpbuf2len
= 2 * tmpbuf2len
;
1138 malloc_tmpbuf2
= true;
1141 rc
= __gethostbyaddr_r (at2
->addr
,
1142 ((at2
->family
== AF_INET6
)
1143 ? sizeof (struct in6_addr
)
1144 : sizeof (struct in_addr
)),
1145 at2
->family
, &th
, tmpbuf2
,
1146 tmpbuf2len
, &h
, &herrno
);
1148 while (rc
== ERANGE
&& herrno
== NETDB_INTERNAL
);
1150 if (rc
!= 0 && herrno
== NETDB_INTERNAL
)
1155 __set_h_errno (herrno
);
1156 result
= -EAI_SYSTEM
;
1157 goto free_and_return
;
1164 assert (orig_name
!= NULL
);
1165 /* If the canonical name cannot be determined, use
1166 the passed in string. */
1172 if (req
->ai_flags
& AI_CANONIDN
)
1175 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1176 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1177 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1178 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1181 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1182 if (rc
!= IDNA_SUCCESS
)
1187 if (rc
== IDNA_MALLOC_ERROR
)
1188 result
= -EAI_MEMORY
;
1189 else if (rc
== IDNA_DLOPEN_ERROR
)
1190 result
= -EAI_SYSTEM
;
1192 result
= -EAI_IDN_ENCODE
;
1193 goto free_and_return
;
1195 /* In case the output string is the same as the input
1196 string no new string has been allocated and we
1208 if (malloc_canonbuf
)
1209 /* We already allocated the string using malloc. */
1210 malloc_canonbuf
= false;
1213 canon
= strdup (canon
);
1219 result
= -EAI_MEMORY
;
1220 goto free_and_return
;
1229 family
= at2
->family
;
1230 if (family
== AF_INET6
)
1232 socklen
= sizeof (struct sockaddr_in6
);
1234 /* If we looked up IPv4 mapped address discard them here if
1235 the caller isn't interested in all address and we have
1236 found at least one IPv6 address. */
1238 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1239 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1243 socklen
= sizeof (struct sockaddr_in
);
1245 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1247 struct addrinfo
*ai
;
1248 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1251 free ((char *) canon
);
1252 result
= -EAI_MEMORY
;
1253 goto free_and_return
;
1256 ai
->ai_flags
= req
->ai_flags
;
1257 ai
->ai_family
= family
;
1258 ai
->ai_socktype
= st2
->socktype
;
1259 ai
->ai_protocol
= st2
->protocol
;
1260 ai
->ai_addrlen
= socklen
;
1261 ai
->ai_addr
= (void *) (ai
+ 1);
1263 /* We only add the canonical name once. */
1264 ai
->ai_canonname
= (char *) canon
;
1268 ai
->ai_addr
->sa_len
= socklen
;
1269 #endif /* _HAVE_SA_LEN */
1270 ai
->ai_addr
->sa_family
= family
;
1272 /* In case of an allocation error the list must be NULL
1276 if (family
== AF_INET6
)
1278 struct sockaddr_in6
*sin6p
=
1279 (struct sockaddr_in6
*) ai
->ai_addr
;
1281 sin6p
->sin6_port
= st2
->port
;
1282 sin6p
->sin6_flowinfo
= 0;
1283 memcpy (&sin6p
->sin6_addr
,
1284 at2
->addr
, sizeof (struct in6_addr
));
1285 sin6p
->sin6_scope_id
= at2
->scopeid
;
1289 struct sockaddr_in
*sinp
=
1290 (struct sockaddr_in
*) ai
->ai_addr
;
1291 sinp
->sin_port
= st2
->port
;
1292 memcpy (&sinp
->sin_addr
,
1293 at2
->addr
, sizeof (struct in_addr
));
1294 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1297 pai
= &(ai
->ai_next
);
1309 free ((char *) name
);
1312 if (malloc_canonbuf
)
1323 struct addrinfo
*dest_addr
;
1324 /* Using sockaddr_storage is for now overkill. We only support IPv4
1325 and IPv6 so far. If this changes at some point we can adjust the
1327 struct sockaddr_in6 source_addr
;
1328 uint8_t source_addr_len
;
1329 bool got_source_addr
;
1330 uint8_t source_addr_flags
;
1336 struct sort_result_combo
1338 struct sort_result
*results
;
1343 #if __BYTE_ORDER == __BIG_ENDIAN
1344 # define htonl_c(n) n
1346 # define htonl_c(n) __bswap_constant_32 (n)
1349 static const struct scopeentry
1358 } default_scopes
[] =
1360 /* Link-local addresses: scope 2. */
1361 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1362 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1363 /* Site-local addresses: scope 5. */
1364 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1365 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1366 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1367 /* Default: scope 14. */
1368 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1371 /* The label table. */
1372 static const struct scopeentry
*scopes
;
1376 get_scope (const struct sockaddr_in6
*in6
)
1379 if (in6
->sin6_family
== PF_INET6
)
1381 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1383 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1384 /* RFC 4291 2.5.3 says that the loopback address is to be
1385 treated like a link-local address. */
1386 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1388 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1391 /* XXX Is this the correct default behavior? */
1395 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1397 else if (in6
->sin6_family
== PF_INET
)
1399 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1404 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1405 == scopes
[cnt
].addr32
)
1406 return scopes
[cnt
].scope
;
1413 /* XXX What is a good default? */
1422 struct in6_addr prefix
;
1428 /* The label table. */
1429 static const struct prefixentry
*labels
;
1431 /* Default labels. */
1432 static const struct prefixentry default_labels
[] =
1434 /* See RFC 3484 for the details. */
1436 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1440 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1444 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1448 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1451 /* The next two entries differ from RFC 3484. We need to treat
1452 IPv6 site-local addresses special because they are never NATed,
1453 unlike site-locale IPv4 addresses. If this would not happen, on
1454 machines which have only IPv4 and IPv6 site-local addresses, the
1455 sorting would prefer the IPv6 site-local addresses, causing
1456 unnecessary delays when trying to connect to a global IPv6 address
1457 through a site-local IPv6 address. */
1459 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1463 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1466 /* Additional rule for Teredo tunnels. */
1468 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1472 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1478 /* The precedence table. */
1479 static const struct prefixentry
*precedence
;
1481 /* The default precedences. */
1482 static const struct prefixentry default_precedence
[] =
1484 /* See RFC 3484 for the details. */
1486 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1490 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1494 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1498 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1499 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1502 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1509 match_prefix (const struct sockaddr_in6
*in6
,
1510 const struct prefixentry
*list
, int default_val
)
1513 struct sockaddr_in6 in6_mem
;
1515 if (in6
->sin6_family
== PF_INET
)
1517 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1519 /* Construct a V4-to-6 mapped address. */
1520 in6_mem
.sin6_family
= PF_INET6
;
1521 in6_mem
.sin6_port
= in
->sin_port
;
1522 in6_mem
.sin6_flowinfo
= 0;
1523 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1524 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1525 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1526 in6_mem
.sin6_scope_id
= 0;
1530 else if (in6
->sin6_family
!= PF_INET6
)
1533 for (idx
= 0; ; ++idx
)
1535 unsigned int bits
= list
[idx
].bits
;
1536 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1537 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1551 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1557 return list
[idx
].val
;
1562 get_label (const struct sockaddr_in6
*in6
)
1564 /* XXX What is a good default value? */
1565 return match_prefix (in6
, labels
, INT_MAX
);
1570 get_precedence (const struct sockaddr_in6
*in6
)
1572 /* XXX What is a good default value? */
1573 return match_prefix (in6
, precedence
, 0);
1577 /* Find last bit set in a word. */
1583 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1584 if ((a
& mask
) != 0)
1591 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1593 const size_t idx1
= *(const size_t *) p1
;
1594 const size_t idx2
= *(const size_t *) p2
;
1595 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1596 struct sort_result
*a1
= &src
->results
[idx1
];
1597 struct sort_result
*a2
= &src
->results
[idx2
];
1599 /* Rule 1: Avoid unusable destinations.
1600 We have the got_source_addr flag set if the destination is reachable. */
1601 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1603 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1607 /* Rule 2: Prefer matching scope. Only interesting if both
1608 destination addresses are IPv6. */
1610 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1613 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1615 if (a1
->got_source_addr
)
1617 int a1_src_scope
= get_scope (&a1
->source_addr
);
1618 int a2_src_scope
= get_scope (&a2
->source_addr
);
1620 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1622 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1627 /* Rule 3: Avoid deprecated addresses. */
1628 if (a1
->got_source_addr
)
1630 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1631 && (a2
->source_addr_flags
& in6ai_deprecated
))
1633 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1634 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1638 /* Rule 4: Prefer home addresses. */
1639 if (a1
->got_source_addr
)
1641 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1642 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1644 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1645 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1649 /* Rule 5: Prefer matching label. */
1650 if (a1
->got_source_addr
)
1653 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1654 int a1_src_label
= get_label (&a1
->source_addr
);
1657 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1658 int a2_src_label
= get_label (&a2
->source_addr
);
1660 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1662 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1667 /* Rule 6: Prefer higher precedence. */
1669 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1671 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1673 if (a1_prec
> a2_prec
)
1675 if (a1_prec
< a2_prec
)
1679 /* Rule 7: Prefer native transport. */
1680 if (a1
->got_source_addr
)
1682 /* The same interface index means the same interface which means
1683 there is no difference in transport. This should catch many
1685 if (a1
->index
!= a2
->index
)
1687 int a1_native
= a1
->native
;
1688 int a2_native
= a2
->native
;
1690 if (a1_native
== -1 || a2_native
== -1)
1693 if (a1_native
== -1)
1695 /* If we do not have the information use 'native' as
1698 a1_index
= a1
->index
;
1701 a1_index
= 0xffffffffu
;
1704 if (a2_native
== -1)
1706 /* If we do not have the information use 'native' as
1709 a2_index
= a2
->index
;
1712 a2_index
= 0xffffffffu
;
1714 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1716 /* Fill in the results in all the records. */
1717 for (int i
= 0; i
< src
->nresults
; ++i
)
1718 if (src
->results
[i
].index
== a1_index
)
1720 assert (src
->results
[i
].native
== -1
1721 || src
->results
[i
].native
== a1_native
);
1722 src
->results
[i
].native
= a1_native
;
1724 else if (src
->results
[i
].index
== a2_index
)
1726 assert (src
->results
[i
].native
== -1
1727 || src
->results
[i
].native
== a2_native
);
1728 src
->results
[i
].native
= a2_native
;
1732 if (a1_native
&& !a2_native
)
1734 if (!a1_native
&& a2_native
)
1740 /* Rule 8: Prefer smaller scope. */
1741 if (a1_dst_scope
< a2_dst_scope
)
1743 if (a1_dst_scope
> a2_dst_scope
)
1747 /* Rule 9: Use longest matching prefix. */
1748 if (a1
->got_source_addr
1749 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1754 if (a1
->dest_addr
->ai_family
== PF_INET
)
1756 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1757 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1759 /* Outside of subnets, as defined by the network masks,
1760 common address prefixes for IPv4 addresses make no sense.
1761 So, define a non-zero value only if source and
1762 destination address are on the same subnet. */
1763 struct sockaddr_in
*in1_dst
1764 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1765 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1766 struct sockaddr_in
*in1_src
1767 = (struct sockaddr_in
*) &a1
->source_addr
;
1768 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1769 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1771 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1772 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1774 struct sockaddr_in
*in2_dst
1775 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1776 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1777 struct sockaddr_in
*in2_src
1778 = (struct sockaddr_in
*) &a2
->source_addr
;
1779 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1780 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1782 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1783 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1785 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1787 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1788 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1790 struct sockaddr_in6
*in1_dst
;
1791 struct sockaddr_in6
*in1_src
;
1792 struct sockaddr_in6
*in2_dst
;
1793 struct sockaddr_in6
*in2_src
;
1795 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1796 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1797 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1798 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1801 for (i
= 0; i
< 4; ++i
)
1802 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1803 != in1_src
->sin6_addr
.s6_addr32
[i
]
1804 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1805 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1810 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1811 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1812 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1813 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1824 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1825 compare with the value indicating the order in which the entries
1826 have been received from the services. NB: no two entries can have
1827 the same order so the test will never return zero. */
1828 return idx1
< idx2
? -1 : 1;
1833 in6aicmp (const void *p1
, const void *p2
)
1835 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1836 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1838 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1842 /* Name of the config file for RFC 3484 sorting (for now). */
1843 #define GAICONF_FNAME "/etc/gai.conf"
1846 /* Non-zero if we are supposed to reload the config file automatically
1847 whenever it changed. */
1848 static int gaiconf_reload_flag
;
1850 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1851 static int gaiconf_reload_flag_ever_set
;
1853 /* Last modification time. */
1854 static struct timespec gaiconf_mtime
;
1857 libc_freeres_fn(fini
)
1859 if (labels
!= default_labels
)
1861 const struct prefixentry
*old
= labels
;
1862 labels
= default_labels
;
1863 free ((void *) old
);
1866 if (precedence
!= default_precedence
)
1868 const struct prefixentry
*old
= precedence
;
1869 precedence
= default_precedence
;
1870 free ((void *) old
);
1873 if (scopes
!= default_scopes
)
1875 const struct scopeentry
*old
= scopes
;
1876 scopes
= default_scopes
;
1877 free ((void *) old
);
1884 struct prefixentry entry
;
1885 struct prefixlist
*next
;
1891 struct scopeentry entry
;
1892 struct scopelist
*next
;
1897 free_prefixlist (struct prefixlist
*list
)
1899 while (list
!= NULL
)
1901 struct prefixlist
*oldp
= list
;
1909 free_scopelist (struct scopelist
*list
)
1911 while (list
!= NULL
)
1913 struct scopelist
*oldp
= list
;
1921 prefixcmp (const void *p1
, const void *p2
)
1923 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1924 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1926 if (e1
->bits
< e2
->bits
)
1928 if (e1
->bits
== e2
->bits
)
1935 scopecmp (const void *p1
, const void *p2
)
1937 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1938 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1940 if (e1
->netmask
> e2
->netmask
)
1942 if (e1
->netmask
== e2
->netmask
)
1951 struct prefixlist
*labellist
= NULL
;
1952 size_t nlabellist
= 0;
1953 bool labellist_nullbits
= false;
1954 struct prefixlist
*precedencelist
= NULL
;
1955 size_t nprecedencelist
= 0;
1956 bool precedencelist_nullbits
= false;
1957 struct scopelist
*scopelist
= NULL
;
1958 size_t nscopelist
= 0;
1959 bool scopelist_nullbits
= false;
1961 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1965 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1974 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1976 while (!feof_unlocked (fp
))
1978 ssize_t n
= __getline (&line
, &linelen
, fp
);
1982 /* Handle comments. No escaping possible so this is easy. */
1983 char *cp
= strchr (line
, '#');
1988 while (isspace (*cp
))
1992 while (*cp
!= '\0' && !isspace (*cp
))
1994 size_t cmdlen
= cp
- cmd
;
1998 while (isspace (*cp
))
2002 while (*cp
!= '\0' && !isspace (*cp
))
2004 size_t val1len
= cp
- cmd
;
2006 /* We always need at least two values. */
2012 while (isspace (*cp
))
2016 while (*cp
!= '\0' && !isspace (*cp
))
2019 /* Ignore the rest of the line. */
2022 struct prefixlist
**listp
;
2028 if (strcmp (cmd
, "label") == 0)
2030 struct in6_addr prefix
;
2031 unsigned long int bits
;
2032 unsigned long int val
;
2037 nullbitsp
= &labellist_nullbits
;
2042 cp
= strchr (val1
, '/');
2045 if (inet_pton (AF_INET6
, val1
, &prefix
)
2047 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2051 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2056 struct prefixlist
*newp
= malloc (sizeof (*newp
));
2064 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
2065 newp
->entry
.bits
= bits
;
2066 newp
->entry
.val
= val
;
2067 newp
->next
= *listp
;
2070 *nullbitsp
|= bits
== 0;
2076 if (strcmp (cmd
, "reload") == 0)
2078 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2079 if (gaiconf_reload_flag
)
2080 gaiconf_reload_flag_ever_set
= 1;
2085 if (strcmp (cmd
, "scopev4") == 0)
2087 struct in6_addr prefix
;
2088 unsigned long int bits
;
2089 unsigned long int val
;
2094 cp
= strchr (val1
, '/');
2097 if (inet_pton (AF_INET6
, val1
, &prefix
))
2100 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2102 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2107 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2112 struct scopelist
*newp
;
2114 newp
= malloc (sizeof (*newp
));
2122 newp
->entry
.netmask
= htonl (bits
!= 96
2126 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2127 & newp
->entry
.netmask
);
2128 newp
->entry
.scope
= val
;
2129 newp
->next
= scopelist
;
2132 scopelist_nullbits
|= bits
== 96;
2135 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2137 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2141 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2153 if (strcmp (cmd
, "precedence") == 0)
2155 listp
= &precedencelist
;
2156 lenp
= &nprecedencelist
;
2157 nullbitsp
= &precedencelist_nullbits
;
2168 /* Create the array for the labels. */
2169 struct prefixentry
*new_labels
;
2172 if (!labellist_nullbits
)
2174 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2175 if (new_labels
== NULL
)
2179 if (!labellist_nullbits
)
2182 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2183 new_labels
[i
].bits
= 0;
2184 new_labels
[i
].val
= 1;
2187 struct prefixlist
*l
= labellist
;
2190 new_labels
[i
] = l
->entry
;
2193 free_prefixlist (labellist
);
2195 /* Sort the entries so that the most specific ones are at
2197 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2200 new_labels
= (struct prefixentry
*) default_labels
;
2202 struct prefixentry
*new_precedence
;
2203 if (nprecedencelist
> 0)
2205 if (!precedencelist_nullbits
)
2207 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2208 if (new_precedence
== NULL
)
2210 if (new_labels
!= default_labels
)
2215 int i
= nprecedencelist
;
2216 if (!precedencelist_nullbits
)
2219 memset (&new_precedence
[i
].prefix
, '\0',
2220 sizeof (struct in6_addr
));
2221 new_precedence
[i
].bits
= 0;
2222 new_precedence
[i
].val
= 40;
2225 struct prefixlist
*l
= precedencelist
;
2228 new_precedence
[i
] = l
->entry
;
2231 free_prefixlist (precedencelist
);
2233 /* Sort the entries so that the most specific ones are at
2235 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2239 new_precedence
= (struct prefixentry
*) default_precedence
;
2241 struct scopeentry
*new_scopes
;
2244 if (!scopelist_nullbits
)
2246 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2247 if (new_scopes
== NULL
)
2249 if (new_labels
!= default_labels
)
2251 if (new_precedence
!= default_precedence
)
2252 free (new_precedence
);
2257 if (!scopelist_nullbits
)
2260 new_scopes
[i
].addr32
= 0;
2261 new_scopes
[i
].netmask
= 0;
2262 new_scopes
[i
].scope
= 14;
2265 struct scopelist
*l
= scopelist
;
2268 new_scopes
[i
] = l
->entry
;
2271 free_scopelist (scopelist
);
2273 /* Sort the entries so that the most specific ones are at
2275 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2279 new_scopes
= (struct scopeentry
*) default_scopes
;
2281 /* Now we are ready to replace the values. */
2282 const struct prefixentry
*old
= labels
;
2283 labels
= new_labels
;
2284 if (old
!= default_labels
)
2285 free ((void *) old
);
2288 precedence
= new_precedence
;
2289 if (old
!= default_precedence
)
2290 free ((void *) old
);
2292 const struct scopeentry
*oldscope
= scopes
;
2293 scopes
= new_scopes
;
2294 if (oldscope
!= default_scopes
)
2295 free ((void *) oldscope
);
2297 gaiconf_mtime
= st
.st_mtim
;
2302 free_prefixlist (labellist
);
2303 free_prefixlist (precedencelist
);
2304 free_scopelist (scopelist
);
2306 /* If we previously read the file but it is gone now, free the
2307 old data and use the builtin one. Leave the reload flag
2315 gaiconf_reload (void)
2318 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2319 || memcmp (&st
.st_mtim
, &gaiconf_mtime
, sizeof (gaiconf_mtime
)) != 0)
2325 getaddrinfo (const char *name
, const char *service
,
2326 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2328 int i
= 0, last_i
= 0;
2330 struct addrinfo
*p
= NULL
;
2331 struct gaih_service gaih_service
, *pservice
;
2332 struct addrinfo local_hints
;
2334 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2337 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2340 if (name
== NULL
&& service
== NULL
)
2344 hints
= &default_hints
;
2347 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2349 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2350 |AI_IDN_USE_STD3_ASCII_RULES
2352 |AI_NUMERICSERV
|AI_ALL
))
2353 return EAI_BADFLAGS
;
2355 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2356 return EAI_BADFLAGS
;
2358 struct in6addrinfo
*in6ai
= NULL
;
2359 size_t in6ailen
= 0;
2360 bool seen_ipv4
= false;
2361 bool seen_ipv6
= false;
2362 bool check_pf_called
= false;
2364 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2366 /* We might need information about what interfaces are available.
2367 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2368 cannot cache the results since new interfaces could be added at
2370 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2371 check_pf_called
= true;
2373 /* Now make a decision on what we return, if anything. */
2374 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2376 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2377 narrow down the search. */
2378 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2380 local_hints
= *hints
;
2381 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2382 hints
= &local_hints
;
2385 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2386 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2388 /* We cannot possibly return a valid answer. */
2389 __free_in6ai (in6ai
);
2394 if (service
&& service
[0])
2397 gaih_service
.name
= service
;
2398 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2401 if (hints
->ai_flags
& AI_NUMERICSERV
)
2403 __free_in6ai (in6ai
);
2407 gaih_service
.num
= -1;
2410 pservice
= &gaih_service
;
2415 struct addrinfo
**end
= &p
;
2417 unsigned int naddrs
= 0;
2418 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2419 || hints
->ai_family
== AF_INET6
)
2421 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
);
2425 __free_in6ai (in6ai
);
2427 return -(last_i
& GAIH_EAI
);
2431 end
= &((*end
)->ai_next
);
2437 __free_in6ai (in6ai
);
2443 /* Read the config file. */
2444 __libc_once_define (static, once
);
2445 __typeof (once
) old_once
= once
;
2446 __libc_once (once
, gaiconf_init
);
2447 /* Sort results according to RFC 3484. */
2448 struct sort_result results
[nresults
];
2449 size_t order
[nresults
];
2451 struct addrinfo
*last
= NULL
;
2452 char *canonname
= NULL
;
2454 /* Now we definitely need the interface information. */
2455 if (! check_pf_called
)
2456 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2458 /* If we have information about deprecated and temporary addresses
2459 sort the array now. */
2461 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2466 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2468 results
[i
].dest_addr
= q
;
2469 results
[i
].native
= -1;
2472 /* If we just looked up the address for a different
2473 protocol, reuse the result. */
2474 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2475 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2477 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2478 results
[i
- 1].source_addr_len
);
2479 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2480 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2481 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2482 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2483 results
[i
].index
= results
[i
- 1].index
;
2487 results
[i
].got_source_addr
= false;
2488 results
[i
].source_addr_flags
= 0;
2489 results
[i
].prefixlen
= 0;
2490 results
[i
].index
= 0xffffffffu
;
2492 /* We overwrite the type with SOCK_DGRAM since we do not
2493 want connect() to connect to the other side. If we
2494 cannot determine the source address remember this
2496 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2500 close_not_cancel_no_status (fd
);
2502 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2506 /* Reset the connection. */
2507 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2508 __connect (fd
, &sa
, sizeof (sa
));
2511 socklen_t sl
= sizeof (results
[i
].source_addr
);
2513 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2514 && __getsockname (fd
,
2515 (struct sockaddr
*) &results
[i
].source_addr
,
2518 results
[i
].source_addr_len
= sl
;
2519 results
[i
].got_source_addr
= true;
2523 /* See whether the source address is on the list of
2524 deprecated or temporary addresses. */
2525 struct in6addrinfo tmp
;
2527 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2529 struct sockaddr_in
*sinp
2530 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2533 tmp
.addr
[2] = htonl (0xffff);
2534 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2538 struct sockaddr_in6
*sin6p
2539 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2540 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2543 struct in6addrinfo
*found
2544 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2548 results
[i
].source_addr_flags
= found
->flags
;
2549 results
[i
].prefixlen
= found
->prefixlen
;
2550 results
[i
].index
= found
->index
;
2554 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2556 /* We have to convert the address. The socket is
2557 IPv6 and the request is for IPv4. */
2558 struct sockaddr_in6
*sin6
2559 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2560 struct sockaddr_in
*sin
2561 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2562 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2563 sin
->sin_family
= AF_INET
;
2564 /* We do not have to initialize sin_port since this
2565 fields has the same position and size in the IPv6
2567 assert (offsetof (struct sockaddr_in
, sin_port
)
2568 == offsetof (struct sockaddr_in6
, sin6_port
));
2569 assert (sizeof (sin
->sin_port
)
2570 == sizeof (sin6
->sin6_port
));
2571 memcpy (&sin
->sin_addr
,
2572 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2573 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2576 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2577 && q
->ai_family
== AF_INET
)
2578 /* This could mean IPv6 sockets are IPv6-only. */
2581 /* Just make sure that if we have to process the same
2582 address again we do not copy any memory. */
2583 results
[i
].source_addr_len
= 0;
2586 /* Remember the canonical name. */
2587 if (q
->ai_canonname
!= NULL
)
2589 assert (canonname
== NULL
);
2590 canonname
= q
->ai_canonname
;
2591 q
->ai_canonname
= NULL
;
2596 close_not_cancel_no_status (fd
);
2598 /* We got all the source addresses we can get, now sort using
2600 struct sort_result_combo src
2601 = { .results
= results
, .nresults
= nresults
};
2602 if (__builtin_expect (gaiconf_reload_flag_ever_set
, 0))
2604 __libc_lock_define_initialized (static, lock
);
2606 __libc_lock_lock (lock
);
2607 if (old_once
&& gaiconf_reload_flag
)
2609 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2610 __libc_lock_unlock (lock
);
2613 qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2615 /* Queue the results up as they come out of sorting. */
2616 q
= p
= results
[order
[0]].dest_addr
;
2617 for (i
= 1; i
< nresults
; ++i
)
2618 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2621 /* Fill in the canonical name into the new first entry. */
2622 p
->ai_canonname
= canonname
;
2625 __free_in6ai (in6ai
);
2633 return last_i
? -(last_i
& GAIH_EAI
) : EAI_NONAME
;
2635 libc_hidden_def (getaddrinfo
)
2637 static_link_warning (getaddrinfo
)
2640 freeaddrinfo (struct addrinfo
*ai
)
2648 free (p
->ai_canonname
);
2652 libc_hidden_def (freeaddrinfo
)