1 /* Host and service name lookups using Name Service Switch modules.
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* The Inner Net License, Version 2.00
21 The author(s) grant permission for redistribution and use in source and
22 binary forms, with or without modification, of the software and documentation
23 provided that the following conditions are met:
25 0. If you receive a version of the software that is specifically labelled
26 as not being for redistribution (check the version message and/or README),
27 you are not permitted to redistribute that version of the software in any
29 1. All terms of the all other applicable copyrights and licenses must be
31 2. Redistributions of source code must retain the authors' copyright
32 notice(s), this list of conditions, and the following disclaimer.
33 3. Redistributions in binary form must reproduce the authors' copyright
34 notice(s), this list of conditions, and the following disclaimer in the
35 documentation and/or other materials provided with the distribution.
36 4. [The copyright holder has authorized the removal of this clause.]
37 5. Neither the name(s) of the author(s) nor the names of its contributors
38 may be used to endorse or promote products derived from this software
39 without specific prior written permission.
41 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
42 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
43 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
45 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
46 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
48 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 If these license terms cause you a real problem, contact the author. */
54 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
62 #include <resolv/resolv-internal.h>
63 #include <resolv/resolv_context.h>
66 #include <stdio_ext.h>
70 #include <arpa/inet.h>
72 #include <netinet/in.h>
73 #include <sys/socket.h>
75 #include <sys/types.h>
77 #include <sys/utsname.h>
80 #include <libc-lock.h>
81 #include <not-cancel.h>
82 #include <nscd/nscd-client.h>
83 #include <nscd/nscd_proto.h>
84 #include <scratch_buffer.h>
85 #include <inet/net-internal.h>
87 /* Former AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
88 flags, now ignored. */
89 #define DEPRECATED_AI_IDN 0x300
92 # define feof_unlocked(fp) __feof_unlocked (fp)
101 struct gaih_servtuple
110 struct gaih_typeproto
121 struct gaih_addrtuple
*at
;
128 /* Values for `protoflag'. */
129 #define GAI_PROTO_NOSERVICE 1
130 #define GAI_PROTO_PROTOANY 2
132 static const struct gaih_typeproto gaih_inet_typeproto
[] =
134 { 0, 0, 0, false, "" },
135 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
136 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
137 #if defined SOCK_DCCP && defined IPPROTO_DCCP
138 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
140 #ifdef IPPROTO_UDPLITE
141 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
144 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
145 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
147 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
148 { 0, 0, 0, false, "" }
151 static const struct addrinfo default_hints
=
153 .ai_flags
= AI_DEFAULT
,
154 .ai_family
= PF_UNSPEC
,
159 .ai_canonname
= NULL
,
164 gaih_result_reset (struct gaih_result
*res
)
170 memset (res
, 0, sizeof (*res
));
174 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
175 const struct addrinfo
*req
, struct gaih_servtuple
*st
,
176 struct scratch_buffer
*tmpbuf
)
184 r
= __getservbyname_r (servicename
, tp
->name
, &ts
,
185 tmpbuf
->data
, tmpbuf
->length
, &s
);
186 if (r
!= 0 || s
== NULL
)
190 if (!scratch_buffer_grow (tmpbuf
))
199 st
->socktype
= tp
->socktype
;
200 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
201 ? req
->ai_protocol
: tp
->protocol
);
202 st
->port
= s
->s_port
;
208 /* Convert struct hostent to a list of struct gaih_addrtuple objects. The new
209 addresses are appended to the tuple array in RES. */
211 convert_hostent_to_gaih_addrtuple (const struct addrinfo
*req
, int family
,
212 struct hostent
*h
, struct gaih_result
*res
)
214 /* Count the number of addresses in h->h_addr_list. */
216 for (char **p
= h
->h_addr_list
; *p
!= NULL
; ++p
)
219 /* Report no data if no addresses are available, or if the incoming
220 address size is larger than what we can store. */
221 if (count
== 0 || h
->h_length
> sizeof (((struct gaih_addrtuple
) {}).addr
))
224 struct gaih_addrtuple
*array
= res
->at
;
227 while (array
!= NULL
)
233 array
= realloc (res
->at
, (old
+ count
) * sizeof (*array
));
238 res
->got_ipv6
= family
== AF_INET6
;
242 /* Duplicate h_name because it may get reclaimed when the underlying storage
244 if (res
->h_name
== NULL
)
246 res
->h_name
= __strdup (h
->h_name
);
247 if (res
->h_name
== NULL
)
251 /* Update the next pointers on reallocation. */
252 for (size_t i
= 0; i
< old
; i
++)
253 array
[i
].next
= array
+ i
+ 1;
257 memset (array
, 0, count
* sizeof (*array
));
259 for (size_t i
= 0; i
< count
; ++i
)
261 if (family
== AF_INET
&& req
->ai_family
== AF_INET6
)
263 /* Perform address mapping. */
264 array
[i
].family
= AF_INET6
;
265 memcpy(array
[i
].addr
+ 3, h
->h_addr_list
[i
], sizeof (uint32_t));
266 array
[i
].addr
[2] = htonl (0xffff);
270 array
[i
].family
= family
;
271 memcpy (array
[i
].addr
, h
->h_addr_list
[i
], h
->h_length
);
273 array
[i
].next
= array
+ i
+ 1;
275 array
[count
- 1].next
= NULL
;
281 gethosts (nss_gethostbyname3_r fct
, int family
, const char *name
,
282 const struct addrinfo
*req
, struct scratch_buffer
*tmpbuf
,
283 struct gaih_result
*res
, enum nss_status
*statusp
, int *no_datap
)
286 char *localcanon
= NULL
;
287 enum nss_status status
;
292 *statusp
= status
= DL_CALL_FCT (fct
, (name
, family
, &th
,
293 tmpbuf
->data
, tmpbuf
->length
,
294 &errno
, &h_errno
, NULL
,
296 if (status
!= NSS_STATUS_TRYAGAIN
|| h_errno
!= NETDB_INTERNAL
299 if (!scratch_buffer_grow (tmpbuf
))
302 if (status
== NSS_STATUS_NOTFOUND
303 || status
== NSS_STATUS_TRYAGAIN
|| status
== NSS_STATUS_UNAVAIL
)
305 if (h_errno
== NETDB_INTERNAL
)
307 if (h_errno
== TRY_AGAIN
)
308 *no_datap
= EAI_AGAIN
;
310 *no_datap
= h_errno
== NO_DATA
;
312 else if (status
== NSS_STATUS_SUCCESS
)
314 if (!convert_hostent_to_gaih_addrtuple (req
, family
, &th
, res
))
317 if (localcanon
!= NULL
&& res
->canon
== NULL
)
319 char *canonbuf
= __strdup (localcanon
);
320 if (canonbuf
== NULL
)
322 res
->canon
= canonbuf
;
329 /* This function is called if a canonical name is requested, but if
330 the service function did not provide it. It tries to obtain the
331 name using getcanonname_r from the same service NIP. If the name
332 cannot be canonicalized, return a copy of NAME. Return NULL on
333 memory allocation failure. The returned string is allocated on the
334 heap; the caller has to free it. */
336 getcanonname (nss_action_list nip
, const char *hname
, const char *name
)
338 nss_getcanonname_r
*cfct
= __nss_lookup_function (nip
, "getcanonname_r");
339 char *s
= (char *) name
;
343 if (DL_CALL_FCT (cfct
, (hname
?: name
, buf
, sizeof (buf
), &s
, &errno
,
344 &h_errno
)) != NSS_STATUS_SUCCESS
)
345 /* If the canonical name cannot be determined, use the passed
352 /* Process looked up canonical name and if necessary, decode to IDNA. Result
353 is a new string written to CANONP and the earlier string is freed. */
356 process_canonname (const struct addrinfo
*req
, const char *orig_name
,
357 struct gaih_result
*res
)
359 char *canon
= res
->canon
;
361 if ((req
->ai_flags
& AI_CANONNAME
) != 0)
363 bool do_idn
= req
->ai_flags
& AI_CANONIDN
;
367 int rc
= __idna_from_dns_encoding (canon
?: orig_name
, &out
);
373 else if (rc
== EAI_IDN_ENCODE
)
374 /* Use the punycode name as a fallback. */
379 if (!do_idn
&& canon
== NULL
&& (canon
= __strdup (orig_name
)) == NULL
)
388 get_servtuples (const struct gaih_service
*service
, const struct addrinfo
*req
,
389 struct gaih_servtuple
*st
, struct scratch_buffer
*tmpbuf
)
392 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
394 if (req
->ai_protocol
|| req
->ai_socktype
)
399 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
400 || (req
->ai_protocol
!= 0
401 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
402 && req
->ai_protocol
!= tp
->protocol
)))
407 if (req
->ai_socktype
)
408 return -EAI_SOCKTYPE
;
414 if (service
!= NULL
&& (tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
417 if (service
== NULL
|| service
->num
>= 0)
419 int port
= service
!= NULL
? htons (service
->num
) : 0;
421 if (req
->ai_socktype
|| req
->ai_protocol
)
423 st
[0].socktype
= tp
->socktype
;
424 st
[0].protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
425 ? req
->ai_protocol
: tp
->protocol
);
432 /* Neither socket type nor protocol is set. Return all socket types
434 for (i
= 0, ++tp
; tp
->name
[0]; ++tp
)
437 st
[i
].socktype
= tp
->socktype
;
438 st
[i
].protocol
= tp
->protocol
;
447 return gaih_inet_serv (service
->name
, tp
, req
, st
, tmpbuf
);
449 for (i
= 0, tp
++; tp
->name
[0]; tp
++)
451 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
454 if (req
->ai_socktype
!= 0
455 && req
->ai_socktype
!= tp
->socktype
)
457 if (req
->ai_protocol
!= 0
458 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
459 && req
->ai_protocol
!= tp
->protocol
)
462 if (gaih_inet_serv (service
->name
,
463 tp
, req
, &st
[i
], tmpbuf
) != 0)
476 /* Query addresses from nscd cache, returning a non-zero value on error.
477 RES members have the lookup result; RES->AT is NULL if there were no errors
478 but also no results. */
481 get_nscd_addresses (const char *name
, const struct addrinfo
*req
,
482 struct gaih_result
*res
)
484 if (__nss_not_use_nscd_hosts
> 0
485 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
486 __nss_not_use_nscd_hosts
= 0;
490 if (__nss_not_use_nscd_hosts
|| __nss_database_custom
[NSS_DBSIDX_hosts
])
493 /* Try to use nscd. */
494 struct nscd_ai_result
*air
= NULL
;
495 int err
= __nscd_getai (name
, &air
, &h_errno
);
497 if (__glibc_unlikely (air
== NULL
))
499 /* The database contains a negative entry. */
502 if (__nss_not_use_nscd_hosts
== 0)
504 if (h_errno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
506 if (h_errno
== TRY_AGAIN
)
513 /* Transform into gaih_addrtuple list. */
515 char *addrs
= air
->addrs
;
517 struct gaih_addrtuple
*at
= calloc (air
->naddrs
, sizeof (*at
));
520 result
= -EAI_MEMORY
;
527 for (int i
= 0; i
< air
->naddrs
; ++i
)
529 socklen_t size
= (air
->family
[i
] == AF_INET
530 ? INADDRSZ
: IN6ADDRSZ
);
532 if (!((air
->family
[i
] == AF_INET
533 && req
->ai_family
== AF_INET6
534 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
535 || req
->ai_family
== AF_UNSPEC
536 || air
->family
[i
] == req
->ai_family
))
538 /* Skip over non-matching result. */
543 if (air
->family
[i
] == AF_INET
&& req
->ai_family
== AF_INET6
544 && (req
->ai_flags
& AI_V4MAPPED
))
546 at
[count
].family
= AF_INET6
;
547 at
[count
].addr
[3] = *(uint32_t *) addrs
;
548 at
[count
].addr
[2] = htonl (0xffff);
550 else if (req
->ai_family
== AF_UNSPEC
551 || air
->family
[i
] == req
->ai_family
)
553 at
[count
].family
= air
->family
[i
];
554 memcpy (at
[count
].addr
, addrs
, size
);
555 if (air
->family
[i
] == AF_INET6
)
556 res
->got_ipv6
= true;
558 at
[count
].next
= at
+ count
+ 1;
563 if ((req
->ai_flags
& AI_CANONNAME
) && air
->canon
!= NULL
)
565 char *canonbuf
= __strdup (air
->canon
);
566 if (canonbuf
== NULL
)
568 result
= -EAI_MEMORY
;
571 res
->canon
= canonbuf
;
576 result
= -EAI_NONAME
;
580 at
[count
- 1].next
= NULL
;
589 res
->free_at
= false;
597 get_nss_addresses (const char *name
, const struct addrinfo
*req
,
598 struct scratch_buffer
*tmpbuf
, struct gaih_result
*res
)
601 int no_inet6_data
= 0;
603 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
604 enum nss_status status
= NSS_STATUS_UNAVAIL
;
606 struct resolv_context
*res_ctx
= NULL
;
607 bool do_merge
= false;
610 no_more
= !__nss_database_get (nss_database_hosts
, &nip
);
612 /* If we are looking for both IPv4 and IPv6 address we don't
613 want the lookup functions to automatically promote IPv4
614 addresses to IPv6 addresses, so we use the no_inet6
616 res_ctx
= __resolv_context_get ();
621 result
= -EAI_MEMORY
;
629 /* Always start afresh; continue should discard previous results
630 and the hosts database does not support merge. */
631 gaih_result_reset (res
);
635 __set_h_errno (NETDB_INTERNAL
);
641 nss_gethostbyname4_r
*fct4
= NULL
;
643 /* gethostbyname4_r sends out parallel A and AAAA queries and
644 is thus only suitable for PF_UNSPEC. */
645 if (req
->ai_family
== PF_UNSPEC
)
646 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
652 status
= DL_CALL_FCT (fct4
, (name
, &res
->at
,
653 tmpbuf
->data
, tmpbuf
->length
,
656 if (status
== NSS_STATUS_SUCCESS
)
658 /* gethostbyname4_r may write into AT, so reset it. */
660 if (status
!= NSS_STATUS_TRYAGAIN
661 || errno
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
663 if (h_errno
== TRY_AGAIN
)
666 no_data
= h_errno
== NO_DATA
;
670 if (!scratch_buffer_grow (tmpbuf
))
672 __resolv_context_put (res_ctx
);
673 result
= -EAI_MEMORY
;
678 if (status
== NSS_STATUS_SUCCESS
)
683 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && res
->canon
== NULL
)
685 char *canonbuf
= __strdup (res
->at
->name
);
686 if (canonbuf
== NULL
)
688 __resolv_context_put (res_ctx
);
689 result
= -EAI_MEMORY
;
692 res
->canon
= canonbuf
;
695 struct gaih_addrtuple
**pat
= &res
->at
;
699 if ((*pat
)->family
== AF_INET
700 && req
->ai_family
== AF_INET6
701 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
703 uint32_t *pataddr
= (*pat
)->addr
;
704 (*pat
)->family
= AF_INET6
;
705 pataddr
[3] = pataddr
[0];
706 pataddr
[2] = htonl (0xffff);
709 pat
= &((*pat
)->next
);
712 else if (req
->ai_family
== AF_UNSPEC
713 || (*pat
)->family
== req
->ai_family
)
715 pat
= &((*pat
)->next
);
718 if (req
->ai_family
== AF_INET6
)
719 res
->got_ipv6
= true;
722 *pat
= ((*pat
)->next
);
726 no_inet6_data
= no_data
;
730 nss_gethostbyname3_r
*fct
= NULL
;
731 if (req
->ai_flags
& AI_CANONNAME
)
732 /* No need to use this function if we do not look for
733 the canonical name. The function does not exist in
734 all NSS modules and therefore the lookup would
736 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
738 /* We are cheating here. The gethostbyname2_r
739 function does not have the same interface as
740 gethostbyname3_r but the extra arguments the
741 latter takes are added at the end. So the
742 gethostbyname2_r code will just ignore them. */
743 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
747 if (req
->ai_family
== AF_INET6
748 || req
->ai_family
== AF_UNSPEC
)
750 if ((result
= gethosts (fct
, AF_INET6
, name
, req
, tmpbuf
,
751 res
, &status
, &no_data
)) != 0)
753 __resolv_context_put (res_ctx
);
756 no_inet6_data
= no_data
;
757 inet6_status
= status
;
759 if (req
->ai_family
== AF_INET
760 || req
->ai_family
== AF_UNSPEC
761 || (req
->ai_family
== AF_INET6
762 && (req
->ai_flags
& AI_V4MAPPED
)
763 /* Avoid generating the mapped addresses if we
764 know we are not going to need them. */
765 && ((req
->ai_flags
& AI_ALL
) || !res
->got_ipv6
)))
767 if ((result
= gethosts (fct
, AF_INET
, name
, req
, tmpbuf
,
768 res
, &status
, &no_data
)) != 0)
770 __resolv_context_put (res_ctx
);
774 if (req
->ai_family
== AF_INET
)
776 no_inet6_data
= no_data
;
777 inet6_status
= status
;
781 /* If we found one address for AF_INET or AF_INET6,
782 don't continue the search. */
783 if (inet6_status
== NSS_STATUS_SUCCESS
784 || status
== NSS_STATUS_SUCCESS
)
786 if ((req
->ai_flags
& AI_CANONNAME
) != 0
787 && res
->canon
== NULL
)
789 char *canonbuf
= getcanonname (nip
, res
->h_name
, name
);
790 if (canonbuf
== NULL
)
792 __resolv_context_put (res_ctx
);
793 result
= -EAI_MEMORY
;
796 res
->canon
= canonbuf
;
798 status
= NSS_STATUS_SUCCESS
;
802 /* We can have different states for AF_INET and
803 AF_INET6. Try to find a useful one for both. */
804 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
805 status
= NSS_STATUS_TRYAGAIN
;
806 else if (status
== NSS_STATUS_UNAVAIL
807 && inet6_status
!= NSS_STATUS_UNAVAIL
)
808 status
= inet6_status
;
813 /* Could not locate any of the lookup functions.
814 The NSS lookup code does not consistently set
815 errno, so we need to supply our own error
816 code here. The root cause could either be a
817 resource allocation failure, or a missing
818 service function in the DSO (so it should not
819 be listed in /etc/nsswitch.conf). Assume the
820 former, and return EBUSY. */
821 status
= NSS_STATUS_UNAVAIL
;
822 __set_h_errno (NETDB_INTERNAL
);
827 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
830 /* The hosts database does not support MERGE. */
831 if (nss_next_action (nip
, status
) == NSS_ACTION_MERGE
)
835 if (nip
->module
== NULL
)
839 __resolv_context_put (res_ctx
);
841 /* If we have a failure which sets errno, report it using
843 if ((status
== NSS_STATUS_TRYAGAIN
|| status
== NSS_STATUS_UNAVAIL
)
844 && h_errno
== NETDB_INTERNAL
)
846 result
= -EAI_SYSTEM
;
850 if (no_data
!= 0 && no_inet6_data
!= 0)
852 /* If both requests timed out report this. */
853 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
856 /* We made requests but they turned out no data. The name
858 result
= -EAI_NODATA
;
863 gaih_result_reset (res
);
867 /* Convert numeric addresses to binary into RES. On failure, RES->AT is set to
868 NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and
869 the function cannot determine a result, RES->AT is set to NULL and 0
873 text_to_binary_address (const char *name
, const struct addrinfo
*req
,
874 struct gaih_result
*res
)
876 struct gaih_addrtuple
*at
= res
->at
;
881 memset (at
->addr
, 0, sizeof (at
->addr
));
882 if (__inet_aton_exact (name
, (struct in_addr
*) at
->addr
) != 0)
884 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
885 at
->family
= AF_INET
;
886 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
888 at
->addr
[3] = at
->addr
[0];
889 at
->addr
[2] = htonl (0xffff);
892 at
->family
= AF_INET6
;
896 result
= -EAI_ADDRFAMILY
;
900 if (req
->ai_flags
& AI_CANONNAME
)
902 char *canonbuf
= __strdup (name
);
903 if (canonbuf
== NULL
)
905 result
= -EAI_MEMORY
;
908 res
->canon
= canonbuf
;
913 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
916 if (scope_delim
== NULL
)
917 e
= inet_pton (AF_INET6
, name
, at
->addr
);
919 e
= __inet_pton_length (AF_INET6
, name
, scope_delim
- name
, at
->addr
);
923 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
924 at
->family
= AF_INET6
;
925 else if (req
->ai_family
== AF_INET
926 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
928 at
->addr
[0] = at
->addr
[3];
929 at
->family
= AF_INET
;
933 result
= -EAI_ADDRFAMILY
;
937 if (scope_delim
!= NULL
938 && __inet6_scopeid_pton ((struct in6_addr
*) at
->addr
,
939 scope_delim
+ 1, &at
->scopeid
) != 0)
941 result
= -EAI_NONAME
;
945 if (req
->ai_flags
& AI_CANONNAME
)
947 char *canonbuf
= __strdup (name
);
948 if (canonbuf
== NULL
)
950 result
= -EAI_MEMORY
;
953 res
->canon
= canonbuf
;
958 if ((req
->ai_flags
& AI_NUMERICHOST
))
959 result
= -EAI_NONAME
;
966 /* If possible, call the simple, old functions, which do not support IPv6 scope
967 ids, nor retrieving the canonical name. */
970 try_simple_gethostbyname (const char *name
, const struct addrinfo
*req
,
971 struct scratch_buffer
*tmpbuf
,
972 struct gaih_result
*res
)
976 if (req
->ai_family
!= AF_INET
|| (req
->ai_flags
& AI_CANONNAME
) != 0)
985 rc
= __gethostbyname2_r (name
, AF_INET
, &th
, tmpbuf
->data
,
986 tmpbuf
->length
, &h
, &h_errno
);
987 if (rc
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
989 if (!scratch_buffer_grow (tmpbuf
))
997 /* We found data, convert it. RES->AT from the conversion will
998 either be an allocated block or NULL, both of which are safe to
1000 if (!convert_hostent_to_gaih_addrtuple (req
, AF_INET
, h
, res
))
1003 res
->free_at
= true;
1006 if (h_errno
== NO_DATA
)
1012 if (h_errno
== NETDB_INTERNAL
)
1014 if (h_errno
== TRY_AGAIN
)
1017 /* We made requests but they turned out no data.
1018 The name is known, though. */
1022 /* Add local address information into RES. RES->AT is assumed to have enough
1023 space for two tuples and is zeroed out. */
1026 get_local_addresses (const struct addrinfo
*req
, struct gaih_result
*res
)
1028 struct gaih_addrtuple
*atr
= res
->at
;
1029 if (req
->ai_family
== AF_UNSPEC
)
1030 res
->at
->next
= res
->at
+ 1;
1032 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1034 res
->at
->family
= AF_INET6
;
1035 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1036 memcpy (res
->at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1037 atr
= res
->at
->next
;
1040 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1042 atr
->family
= AF_INET
;
1043 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1044 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1048 /* Generate results in PAI and its count in NADDRS. Return 0 on success or an
1049 error code on failure. */
1052 generate_addrinfo (const struct addrinfo
*req
, struct gaih_result
*res
,
1053 const struct gaih_servtuple
*st
, struct addrinfo
**pai
,
1054 unsigned int *naddrs
)
1059 /* Buffer is the size of an unformatted IPv6 address in printable format. */
1060 for (struct gaih_addrtuple
*at
= res
->at
; at
!= NULL
; at
= at
->next
)
1062 family
= at
->family
;
1063 if (family
== AF_INET6
)
1065 socklen
= sizeof (struct sockaddr_in6
);
1067 /* If we looked up IPv4 mapped address discard them here if
1068 the caller isn't interested in all address and we have
1069 found at least one IPv6 address. */
1071 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1072 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
1076 socklen
= sizeof (struct sockaddr_in
);
1078 for (int i
= 0; st
[i
].set
; i
++)
1080 struct addrinfo
*ai
;
1081 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1085 ai
->ai_flags
= req
->ai_flags
;
1086 ai
->ai_family
= family
;
1087 ai
->ai_socktype
= st
[i
].socktype
;
1088 ai
->ai_protocol
= st
[i
].protocol
;
1089 ai
->ai_addrlen
= socklen
;
1090 ai
->ai_addr
= (void *) (ai
+ 1);
1092 /* We only add the canonical name once. */
1093 ai
->ai_canonname
= res
->canon
;
1097 ai
->ai_addr
->sa_len
= socklen
;
1098 #endif /* _HAVE_SA_LEN */
1099 ai
->ai_addr
->sa_family
= family
;
1101 /* In case of an allocation error the list must be NULL
1105 if (family
== AF_INET6
)
1107 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*) ai
->ai_addr
;
1108 sin6p
->sin6_port
= st
[i
].port
;
1109 sin6p
->sin6_flowinfo
= 0;
1110 memcpy (&sin6p
->sin6_addr
, at
->addr
, sizeof (struct in6_addr
));
1111 sin6p
->sin6_scope_id
= at
->scopeid
;
1115 struct sockaddr_in
*sinp
= (struct sockaddr_in
*) ai
->ai_addr
;
1116 sinp
->sin_port
= st
[i
].port
;
1117 memcpy (&sinp
->sin_addr
, at
->addr
, sizeof (struct in_addr
));
1118 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1121 pai
= &(ai
->ai_next
);
1130 gaih_inet (const char *name
, const struct gaih_service
*service
,
1131 const struct addrinfo
*req
, struct addrinfo
**pai
,
1132 unsigned int *naddrs
, struct scratch_buffer
*tmpbuf
)
1134 struct gaih_servtuple st
[sizeof (gaih_inet_typeproto
)
1135 / sizeof (struct gaih_typeproto
)] = {0};
1137 const char *orig_name
= name
;
1140 if ((rc
= get_servtuples (service
, req
, st
, tmpbuf
)) != 0)
1143 bool malloc_name
= false;
1144 struct gaih_addrtuple
*addrmem
= NULL
;
1147 struct gaih_result res
= {0};
1148 struct gaih_addrtuple local_at
[2] = {0};
1152 if (__glibc_unlikely (name
== NULL
))
1154 get_local_addresses (req
, &res
);
1158 if (req
->ai_flags
& AI_IDN
)
1161 result
= __idna_to_dns_encoding (name
, &out
);
1168 if ((result
= text_to_binary_address (name
, req
, &res
)) != 0)
1169 goto free_and_return
;
1170 else if (res
.at
!= NULL
)
1173 if ((result
= try_simple_gethostbyname (name
, req
, tmpbuf
, &res
)) != 0)
1174 goto free_and_return
;
1175 else if (res
.at
!= NULL
)
1179 if ((result
= get_nscd_addresses (name
, req
, &res
)) != 0)
1180 goto free_and_return
;
1181 else if (res
.at
!= NULL
)
1185 if ((result
= get_nss_addresses (name
, req
, tmpbuf
, &res
)) != 0)
1186 goto free_and_return
;
1187 else if (res
.at
!= NULL
)
1190 /* None of the lookups worked, so name not found. */
1191 result
= -EAI_NONAME
;
1192 goto free_and_return
;
1195 /* Set up the canonical name if we need it. */
1196 if ((result
= process_canonname (req
, orig_name
, &res
)) != 0)
1197 goto free_and_return
;
1199 result
= generate_addrinfo (req
, &res
, st
, pai
, naddrs
);
1203 free ((char *) name
);
1205 gaih_result_reset (&res
);
1213 struct addrinfo
*dest_addr
;
1214 /* Using sockaddr_storage is for now overkill. We only support IPv4
1215 and IPv6 so far. If this changes at some point we can adjust the
1217 struct sockaddr_in6 source_addr
;
1218 uint8_t source_addr_len
;
1219 bool got_source_addr
;
1220 uint8_t source_addr_flags
;
1226 struct sort_result_combo
1228 struct sort_result
*results
;
1233 #if __BYTE_ORDER == __BIG_ENDIAN
1234 # define htonl_c(n) n
1236 # define htonl_c(n) __bswap_constant_32 (n)
1239 static const struct scopeentry
1248 } default_scopes
[] =
1250 /* Link-local addresses: scope 2. */
1251 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1252 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1253 /* Default: scope 14. */
1254 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1257 /* The label table. */
1258 static const struct scopeentry
*scopes
;
1262 get_scope (const struct sockaddr_in6
*in6
)
1265 if (in6
->sin6_family
== PF_INET6
)
1267 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1269 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1270 /* RFC 4291 2.5.3 says that the loopback address is to be
1271 treated like a link-local address. */
1272 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1274 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1277 /* XXX Is this the correct default behavior? */
1281 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1283 else if (in6
->sin6_family
== PF_INET
)
1285 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1290 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1291 == scopes
[cnt
].addr32
)
1292 return scopes
[cnt
].scope
;
1299 /* XXX What is a good default? */
1308 struct in6_addr prefix
;
1314 /* The label table. */
1315 static const struct prefixentry
*labels
;
1317 /* Default labels. */
1318 static const struct prefixentry default_labels
[] =
1320 /* See RFC 3484 for the details. */
1322 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1326 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1330 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1334 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1337 /* The next two entries differ from RFC 3484. We need to treat
1338 IPv6 site-local addresses special because they are never NATed,
1339 unlike site-locale IPv4 addresses. If this would not happen, on
1340 machines which have only IPv4 and IPv6 site-local addresses, the
1341 sorting would prefer the IPv6 site-local addresses, causing
1342 unnecessary delays when trying to connect to a global IPv6 address
1343 through a site-local IPv6 address. */
1345 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1349 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1352 /* Additional rule for Teredo tunnels. */
1354 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1358 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1364 /* The precedence table. */
1365 static const struct prefixentry
*precedence
;
1367 /* The default precedences. */
1368 static const struct prefixentry default_precedence
[] =
1370 /* See RFC 3484 for the details. */
1372 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1376 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1380 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1384 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1385 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1388 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1395 match_prefix (const struct sockaddr_in6
*in6
,
1396 const struct prefixentry
*list
, int default_val
)
1399 struct sockaddr_in6 in6_mem
;
1401 if (in6
->sin6_family
== PF_INET
)
1403 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1405 /* Construct a V4-to-6 mapped address. */
1406 in6_mem
.sin6_family
= PF_INET6
;
1407 in6_mem
.sin6_port
= in
->sin_port
;
1408 in6_mem
.sin6_flowinfo
= 0;
1409 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1410 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1411 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1412 in6_mem
.sin6_scope_id
= 0;
1416 else if (in6
->sin6_family
!= PF_INET6
)
1419 for (idx
= 0; ; ++idx
)
1421 unsigned int bits
= list
[idx
].bits
;
1422 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1423 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1437 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1443 return list
[idx
].val
;
1448 get_label (const struct sockaddr_in6
*in6
)
1450 /* XXX What is a good default value? */
1451 return match_prefix (in6
, labels
, INT_MAX
);
1456 get_precedence (const struct sockaddr_in6
*in6
)
1458 /* XXX What is a good default value? */
1459 return match_prefix (in6
, precedence
, 0);
1463 /* Find last bit set in a word. */
1469 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1470 if ((a
& mask
) != 0)
1477 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1479 const size_t idx1
= *(const size_t *) p1
;
1480 const size_t idx2
= *(const size_t *) p2
;
1481 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1482 struct sort_result
*a1
= &src
->results
[idx1
];
1483 struct sort_result
*a2
= &src
->results
[idx2
];
1485 /* Rule 1: Avoid unusable destinations.
1486 We have the got_source_addr flag set if the destination is reachable. */
1487 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1489 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1493 /* Rule 2: Prefer matching scope. Only interesting if both
1494 destination addresses are IPv6. */
1496 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1499 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1501 if (a1
->got_source_addr
)
1503 int a1_src_scope
= get_scope (&a1
->source_addr
);
1504 int a2_src_scope
= get_scope (&a2
->source_addr
);
1506 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1508 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1513 /* Rule 3: Avoid deprecated addresses. */
1514 if (a1
->got_source_addr
)
1516 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1517 && (a2
->source_addr_flags
& in6ai_deprecated
))
1519 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1520 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1524 /* Rule 4: Prefer home addresses. */
1525 if (a1
->got_source_addr
)
1527 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1528 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1530 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1531 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1535 /* Rule 5: Prefer matching label. */
1536 if (a1
->got_source_addr
)
1539 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1540 int a1_src_label
= get_label (&a1
->source_addr
);
1543 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1544 int a2_src_label
= get_label (&a2
->source_addr
);
1546 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1548 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1553 /* Rule 6: Prefer higher precedence. */
1555 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1557 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1559 if (a1_prec
> a2_prec
)
1561 if (a1_prec
< a2_prec
)
1565 /* Rule 7: Prefer native transport. */
1566 if (a1
->got_source_addr
)
1568 /* The same interface index means the same interface which means
1569 there is no difference in transport. This should catch many
1571 if (a1
->index
!= a2
->index
)
1573 int a1_native
= a1
->native
;
1574 int a2_native
= a2
->native
;
1576 if (a1_native
== -1 || a2_native
== -1)
1579 if (a1_native
== -1)
1581 /* If we do not have the information use 'native' as
1584 a1_index
= a1
->index
;
1587 a1_index
= 0xffffffffu
;
1590 if (a2_native
== -1)
1592 /* If we do not have the information use 'native' as
1595 a2_index
= a2
->index
;
1598 a2_index
= 0xffffffffu
;
1600 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1602 /* Fill in the results in all the records. */
1603 for (int i
= 0; i
< src
->nresults
; ++i
)
1604 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1606 assert (src
->results
[i
].native
== -1
1607 || src
->results
[i
].native
== a1_native
);
1608 src
->results
[i
].native
= a1_native
;
1610 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1612 assert (src
->results
[i
].native
== -1
1613 || src
->results
[i
].native
== a2_native
);
1614 src
->results
[i
].native
= a2_native
;
1618 if (a1_native
&& !a2_native
)
1620 if (!a1_native
&& a2_native
)
1626 /* Rule 8: Prefer smaller scope. */
1627 if (a1_dst_scope
< a2_dst_scope
)
1629 if (a1_dst_scope
> a2_dst_scope
)
1633 /* Rule 9: Use longest matching prefix. */
1634 if (a1
->got_source_addr
1635 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1640 if (a1
->dest_addr
->ai_family
== PF_INET
)
1642 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1643 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1645 /* Outside of subnets, as defined by the network masks,
1646 common address prefixes for IPv4 addresses make no sense.
1647 So, define a non-zero value only if source and
1648 destination address are on the same subnet. */
1649 struct sockaddr_in
*in1_dst
1650 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1651 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1652 struct sockaddr_in
*in1_src
1653 = (struct sockaddr_in
*) &a1
->source_addr
;
1654 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1655 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1657 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1658 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1660 struct sockaddr_in
*in2_dst
1661 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1662 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1663 struct sockaddr_in
*in2_src
1664 = (struct sockaddr_in
*) &a2
->source_addr
;
1665 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1666 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1668 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1669 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1671 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1673 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1674 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1676 struct sockaddr_in6
*in1_dst
;
1677 struct sockaddr_in6
*in1_src
;
1678 struct sockaddr_in6
*in2_dst
;
1679 struct sockaddr_in6
*in2_src
;
1681 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1682 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1683 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1684 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1687 for (i
= 0; i
< 4; ++i
)
1688 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1689 != in1_src
->sin6_addr
.s6_addr32
[i
]
1690 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1691 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1696 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1697 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1698 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1699 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1710 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1711 compare with the value indicating the order in which the entries
1712 have been received from the services. NB: no two entries can have
1713 the same order so the test will never return zero. */
1714 return idx1
< idx2
? -1 : 1;
1719 in6aicmp (const void *p1
, const void *p2
)
1721 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1722 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1724 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1728 /* Name of the config file for RFC 3484 sorting (for now). */
1729 #define GAICONF_FNAME "/etc/gai.conf"
1732 /* Non-zero if we are supposed to reload the config file automatically
1733 whenever it changed. */
1734 static int gaiconf_reload_flag
;
1736 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1737 static int gaiconf_reload_flag_ever_set
;
1739 /* Last modification time. */
1740 #ifdef _STATBUF_ST_NSEC
1742 static struct __timespec64 gaiconf_mtime
;
1745 save_gaiconf_mtime (const struct __stat64_t64
*st
)
1747 gaiconf_mtime
= (struct __timespec64
) { st
->st_mtim
.tv_sec
,
1748 st
->st_mtim
.tv_nsec
};
1752 check_gaiconf_mtime (const struct __stat64_t64
*st
)
1754 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1755 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1760 static time_t gaiconf_mtime
;
1763 save_gaiconf_mtime (const struct __stat64_t64
*st
)
1765 gaiconf_mtime
= st
->st_mtime
;
1769 check_gaiconf_mtime (const struct __stat64_t64
*st
)
1771 return st
->st_mtime
== gaiconf_mtime
;
1778 __libc_getaddrinfo_freemem (void)
1780 if (labels
!= default_labels
)
1782 const struct prefixentry
*old
= labels
;
1783 labels
= default_labels
;
1784 free ((void *) old
);
1787 if (precedence
!= default_precedence
)
1789 const struct prefixentry
*old
= precedence
;
1790 precedence
= default_precedence
;
1791 free ((void *) old
);
1794 if (scopes
!= default_scopes
)
1796 const struct scopeentry
*old
= scopes
;
1797 scopes
= default_scopes
;
1798 free ((void *) old
);
1805 struct prefixentry entry
;
1806 struct prefixlist
*next
;
1812 struct scopeentry entry
;
1813 struct scopelist
*next
;
1818 free_prefixlist (struct prefixlist
*list
)
1820 while (list
!= NULL
)
1822 struct prefixlist
*oldp
= list
;
1830 free_scopelist (struct scopelist
*list
)
1832 while (list
!= NULL
)
1834 struct scopelist
*oldp
= list
;
1842 prefixcmp (const void *p1
, const void *p2
)
1844 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1845 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1847 if (e1
->bits
< e2
->bits
)
1849 if (e1
->bits
== e2
->bits
)
1856 scopecmp (const void *p1
, const void *p2
)
1858 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1859 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1861 if (e1
->netmask
> e2
->netmask
)
1863 if (e1
->netmask
== e2
->netmask
)
1869 add_prefixlist (struct prefixlist
**listp
, size_t *lenp
, bool *nullbitsp
,
1870 char *val1
, char *val2
, char **pos
)
1872 struct in6_addr prefix
;
1873 unsigned long int bits
;
1874 unsigned long int val
;
1879 char *cp
= strchr (val1
, '/');
1883 if (inet_pton (AF_INET6
, val1
, &prefix
)
1885 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1889 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1894 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1898 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1899 newp
->entry
.bits
= bits
;
1900 newp
->entry
.val
= val
;
1901 newp
->next
= *listp
;
1904 *nullbitsp
|= bits
== 0;
1910 add_scopelist (struct scopelist
**listp
, size_t *lenp
, bool *nullbitsp
,
1911 const struct in6_addr
*prefixp
, unsigned long int bits
,
1912 unsigned long int val
)
1914 struct scopelist
*newp
= malloc (sizeof (*newp
));
1918 newp
->entry
.netmask
= htonl (bits
!= 96 ? (0xffffffff << (128 - bits
)) : 0);
1919 newp
->entry
.addr32
= (prefixp
->s6_addr32
[3] & newp
->entry
.netmask
);
1920 newp
->entry
.scope
= val
;
1921 newp
->next
= *listp
;
1924 *nullbitsp
|= bits
== 96;
1932 struct prefixlist
*labellist
= NULL
;
1933 size_t nlabellist
= 0;
1934 bool labellist_nullbits
= false;
1935 struct prefixlist
*precedencelist
= NULL
;
1936 size_t nprecedencelist
= 0;
1937 bool precedencelist_nullbits
= false;
1938 struct scopelist
*scopelist
= NULL
;
1939 size_t nscopelist
= 0;
1940 bool scopelist_nullbits
= false;
1942 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1946 struct __stat64_t64 st
;
1947 if (__fstat64_time64 (fileno (fp
), &st
) != 0)
1956 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1958 while (!feof_unlocked (fp
))
1960 ssize_t n
= __getline (&line
, &linelen
, fp
);
1964 /* Handle comments. No escaping possible so this is easy. */
1965 char *cp
= strchr (line
, '#');
1970 while (isspace (*cp
))
1974 while (*cp
!= '\0' && !isspace (*cp
))
1976 size_t cmdlen
= cp
- cmd
;
1980 while (isspace (*cp
))
1984 while (*cp
!= '\0' && !isspace (*cp
))
1986 size_t val1len
= cp
- cmd
;
1988 /* We always need at least two values. */
1994 while (isspace (*cp
))
1998 while (*cp
!= '\0' && !isspace (*cp
))
2001 /* Ignore the rest of the line. */
2007 if (strcmp (cmd
, "label") == 0)
2009 if (!add_prefixlist (&labellist
, &nlabellist
,
2010 &labellist_nullbits
, val1
, val2
, &cp
))
2020 if (strcmp (cmd
, "reload") == 0)
2022 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2023 if (gaiconf_reload_flag
)
2024 gaiconf_reload_flag_ever_set
= 1;
2029 if (strcmp (cmd
, "scopev4") == 0)
2031 struct in6_addr prefix
;
2032 unsigned long int bits
;
2033 unsigned long int val
;
2038 cp
= strchr (val1
, '/');
2041 if (inet_pton (AF_INET6
, val1
, &prefix
))
2044 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2046 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2051 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2056 if (!add_scopelist (&scopelist
, &nscopelist
,
2057 &scopelist_nullbits
, &prefix
,
2066 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2068 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2072 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2077 if (!add_scopelist (&scopelist
, &nscopelist
,
2078 &scopelist_nullbits
, &prefix
,
2090 if (strcmp (cmd
, "precedence") == 0)
2092 if (!add_prefixlist (&precedencelist
, &nprecedencelist
,
2093 &precedencelist_nullbits
, val1
, val2
,
2109 /* Create the array for the labels. */
2110 struct prefixentry
*new_labels
;
2113 if (!labellist_nullbits
)
2115 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2116 if (new_labels
== NULL
)
2120 if (!labellist_nullbits
)
2123 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2124 new_labels
[i
].bits
= 0;
2125 new_labels
[i
].val
= 1;
2128 struct prefixlist
*l
= labellist
;
2131 new_labels
[i
] = l
->entry
;
2134 free_prefixlist (labellist
);
2137 /* Sort the entries so that the most specific ones are at
2139 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2142 new_labels
= (struct prefixentry
*) default_labels
;
2144 struct prefixentry
*new_precedence
;
2145 if (nprecedencelist
> 0)
2147 if (!precedencelist_nullbits
)
2149 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2150 if (new_precedence
== NULL
)
2152 if (new_labels
!= default_labels
)
2157 int i
= nprecedencelist
;
2158 if (!precedencelist_nullbits
)
2161 memset (&new_precedence
[i
].prefix
, '\0',
2162 sizeof (struct in6_addr
));
2163 new_precedence
[i
].bits
= 0;
2164 new_precedence
[i
].val
= 40;
2167 struct prefixlist
*l
= precedencelist
;
2170 new_precedence
[i
] = l
->entry
;
2173 free_prefixlist (precedencelist
);
2174 precedencelist
= NULL
;
2176 /* Sort the entries so that the most specific ones are at
2178 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2182 new_precedence
= (struct prefixentry
*) default_precedence
;
2184 struct scopeentry
*new_scopes
;
2187 if (!scopelist_nullbits
)
2189 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2190 if (new_scopes
== NULL
)
2192 if (new_labels
!= default_labels
)
2194 if (new_precedence
!= default_precedence
)
2195 free (new_precedence
);
2200 if (!scopelist_nullbits
)
2203 new_scopes
[i
].addr32
= 0;
2204 new_scopes
[i
].netmask
= 0;
2205 new_scopes
[i
].scope
= 14;
2208 struct scopelist
*l
= scopelist
;
2211 new_scopes
[i
] = l
->entry
;
2214 free_scopelist (scopelist
);
2216 /* Sort the entries so that the most specific ones are at
2218 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2222 new_scopes
= (struct scopeentry
*) default_scopes
;
2224 /* Now we are ready to replace the values. */
2225 const struct prefixentry
*old
= labels
;
2226 labels
= new_labels
;
2227 if (old
!= default_labels
)
2228 free ((void *) old
);
2231 precedence
= new_precedence
;
2232 if (old
!= default_precedence
)
2233 free ((void *) old
);
2235 const struct scopeentry
*oldscope
= scopes
;
2236 scopes
= new_scopes
;
2237 if (oldscope
!= default_scopes
)
2238 free ((void *) oldscope
);
2240 save_gaiconf_mtime (&st
);
2244 free_prefixlist (labellist
);
2245 free_prefixlist (precedencelist
);
2246 free_scopelist (scopelist
);
2248 /* If we previously read the file but it is gone now, free the old data and
2249 use the builtin one. Leave the reload flag alone. */
2250 __libc_getaddrinfo_freemem ();
2255 gaiconf_reload (void)
2257 struct __stat64_t64 st
;
2258 if (__stat64_time64 (GAICONF_FNAME
, &st
) != 0
2259 || !check_gaiconf_mtime (&st
))
2264 try_connect (int *fdp
, int *afp
, struct sockaddr_in6
*source_addrp
,
2265 const struct sockaddr
*addr
, socklen_t addrlen
, int family
)
2269 socklen_t sl
= sizeof (*source_addrp
);
2273 if (fd
!= -1 && __connect (fd
, addr
, addrlen
) == 0
2274 && __getsockname (fd
, (struct sockaddr
*) source_addrp
, &sl
) == 0)
2277 if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
&& family
== AF_INET
)
2279 /* This could mean IPv6 sockets are IPv6-only. */
2281 __close_nocancel_nostatus (fd
);
2282 *afp
= af
= AF_INET
;
2283 *fdp
= fd
= __socket (AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
,
2291 __builtin_unreachable ();
2295 getaddrinfo (const char *name
, const char *service
,
2296 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2298 int i
= 0, last_i
= 0;
2300 struct addrinfo
*p
= NULL
;
2301 struct gaih_service gaih_service
, *pservice
;
2302 struct addrinfo local_hints
;
2304 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2307 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2310 if (name
== NULL
&& service
== NULL
)
2314 hints
= &default_hints
;
2317 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2318 |AI_IDN
|AI_CANONIDN
|DEPRECATED_AI_IDN
2319 |AI_NUMERICSERV
|AI_ALL
))
2320 return EAI_BADFLAGS
;
2322 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2323 return EAI_BADFLAGS
;
2325 if (hints
->ai_family
!= AF_UNSPEC
&& hints
->ai_family
!= AF_INET
2326 && hints
->ai_family
!= AF_INET6
)
2329 struct in6addrinfo
*in6ai
= NULL
;
2330 size_t in6ailen
= 0;
2331 bool seen_ipv4
= false;
2332 bool seen_ipv6
= false;
2333 bool check_pf_called
= false;
2335 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2337 /* We might need information about what interfaces are available.
2338 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2339 cannot cache the results since new interfaces could be added at
2341 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2342 check_pf_called
= true;
2344 /* Now make a decision on what we return, if anything. */
2345 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2347 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2348 narrow down the search. */
2349 if (seen_ipv4
!= seen_ipv6
)
2351 local_hints
= *hints
;
2352 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2353 hints
= &local_hints
;
2356 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2357 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2359 /* We cannot possibly return a valid answer. */
2360 __free_in6ai (in6ai
);
2365 if (service
&& service
[0])
2368 gaih_service
.name
= service
;
2369 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2372 if (hints
->ai_flags
& AI_NUMERICSERV
)
2374 __free_in6ai (in6ai
);
2378 gaih_service
.num
= -1;
2381 pservice
= &gaih_service
;
2386 struct addrinfo
**end
= &p
;
2387 unsigned int naddrs
= 0;
2388 struct scratch_buffer tmpbuf
;
2390 scratch_buffer_init (&tmpbuf
);
2391 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
, &tmpbuf
);
2392 scratch_buffer_free (&tmpbuf
);
2397 __free_in6ai (in6ai
);
2404 end
= &((*end
)->ai_next
);
2410 /* Read the config file. */
2411 __libc_once_define (static, once
);
2412 __typeof (once
) old_once
= once
;
2413 __libc_once (once
, gaiconf_init
);
2414 /* Sort results according to RFC 3484. */
2415 struct sort_result
*results
;
2418 struct addrinfo
*last
= NULL
;
2419 char *canonname
= NULL
;
2420 struct scratch_buffer buf
;
2421 scratch_buffer_init (&buf
);
2423 if (!scratch_buffer_set_array_size (&buf
, nresults
,
2424 sizeof (*results
) + sizeof (size_t)))
2426 __free_in6ai (in6ai
);
2431 order
= (size_t *) (results
+ nresults
);
2433 /* Now we definitely need the interface information. */
2434 if (! check_pf_called
)
2435 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2437 /* If we have information about deprecated and temporary addresses
2438 sort the array now. */
2440 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2445 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2447 results
[i
].dest_addr
= q
;
2448 results
[i
].native
= -1;
2451 /* If we just looked up the address for a different
2452 protocol, reuse the result. */
2453 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2454 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2456 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2457 results
[i
- 1].source_addr_len
);
2458 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2459 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2460 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2461 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2462 results
[i
].index
= results
[i
- 1].index
;
2466 results
[i
].got_source_addr
= false;
2467 results
[i
].source_addr_flags
= 0;
2468 results
[i
].prefixlen
= 0;
2469 results
[i
].index
= 0xffffffffu
;
2471 /* We overwrite the type with SOCK_DGRAM since we do not
2472 want connect() to connect to the other side. If we
2473 cannot determine the source address remember this
2475 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2478 __close_nocancel_nostatus (fd
);
2480 fd
= __socket (af
, SOCK_DGRAM
| SOCK_CLOEXEC
, IPPROTO_IP
);
2484 /* Reset the connection. */
2485 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2486 __connect (fd
, &sa
, sizeof (sa
));
2489 if (try_connect (&fd
, &af
, &results
[i
].source_addr
, q
->ai_addr
,
2490 q
->ai_addrlen
, q
->ai_family
))
2492 results
[i
].source_addr_len
= sizeof (results
[i
].source_addr
);
2493 results
[i
].got_source_addr
= true;
2497 /* See whether the source address is on the list of
2498 deprecated or temporary addresses. */
2499 struct in6addrinfo tmp
;
2501 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2503 struct sockaddr_in
*sinp
2504 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2507 tmp
.addr
[2] = htonl (0xffff);
2508 /* Special case for lo interface, the source address
2509 being possibly different than the interface
2511 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2513 tmp
.addr
[3] = htonl(0x7f000001);
2515 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2519 struct sockaddr_in6
*sin6p
2520 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2521 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2524 struct in6addrinfo
*found
2525 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2529 results
[i
].source_addr_flags
= found
->flags
;
2530 results
[i
].prefixlen
= found
->prefixlen
;
2531 results
[i
].index
= found
->index
;
2535 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2537 /* We have to convert the address. The socket is
2538 IPv6 and the request is for IPv4. */
2539 struct sockaddr_in6
*sin6
2540 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2541 struct sockaddr_in
*sin
2542 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2543 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2544 sin
->sin_family
= AF_INET
;
2545 /* We do not have to initialize sin_port since this
2546 fields has the same position and size in the IPv6
2548 assert (offsetof (struct sockaddr_in
, sin_port
)
2549 == offsetof (struct sockaddr_in6
, sin6_port
));
2550 assert (sizeof (sin
->sin_port
)
2551 == sizeof (sin6
->sin6_port
));
2552 memcpy (&sin
->sin_addr
,
2553 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2554 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2558 /* Just make sure that if we have to process the same
2559 address again we do not copy any memory. */
2560 results
[i
].source_addr_len
= 0;
2563 /* Remember the canonical name. */
2564 if (q
->ai_canonname
!= NULL
)
2566 assert (canonname
== NULL
);
2567 canonname
= q
->ai_canonname
;
2568 q
->ai_canonname
= NULL
;
2573 __close_nocancel_nostatus (fd
);
2575 /* We got all the source addresses we can get, now sort using
2577 struct sort_result_combo src
2578 = { .results
= results
, .nresults
= nresults
};
2579 if (__glibc_unlikely (gaiconf_reload_flag_ever_set
))
2581 __libc_lock_define_initialized (static, lock
);
2583 __libc_lock_lock (lock
);
2584 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2586 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2587 __libc_lock_unlock (lock
);
2590 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2592 /* Queue the results up as they come out of sorting. */
2593 q
= p
= results
[order
[0]].dest_addr
;
2594 for (i
= 1; i
< nresults
; ++i
)
2595 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2598 /* Fill in the canonical name into the new first entry. */
2599 p
->ai_canonname
= canonname
;
2601 scratch_buffer_free (&buf
);
2604 __free_in6ai (in6ai
);
2612 return last_i
? -last_i
: EAI_NONAME
;
2614 libc_hidden_def (getaddrinfo
)
2616 nss_interface_function (getaddrinfo
)
2619 freeaddrinfo (struct addrinfo
*ai
)
2627 free (p
->ai_canonname
);
2631 libc_hidden_def (freeaddrinfo
)