1 /* Host and service name lookups using Name Service Switch modules.
2 Copyright (C) 1996-2023 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
*addrfree
= calloc (air
->naddrs
, sizeof (*addrfree
));
518 struct gaih_addrtuple
*at
= calloc (air
->naddrs
, sizeof (*at
));
521 result
= -EAI_MEMORY
;
528 for (int i
= 0; i
< air
->naddrs
; ++i
)
530 socklen_t size
= (air
->family
[i
] == AF_INET
531 ? INADDRSZ
: IN6ADDRSZ
);
533 if (!((air
->family
[i
] == AF_INET
534 && req
->ai_family
== AF_INET6
535 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
536 || req
->ai_family
== AF_UNSPEC
537 || air
->family
[i
] == req
->ai_family
))
539 /* Skip over non-matching result. */
544 if (air
->family
[i
] == AF_INET
&& req
->ai_family
== AF_INET6
545 && (req
->ai_flags
& AI_V4MAPPED
))
547 at
[count
].family
= AF_INET6
;
548 at
[count
].addr
[3] = *(uint32_t *) addrs
;
549 at
[count
].addr
[2] = htonl (0xffff);
551 else if (req
->ai_family
== AF_UNSPEC
552 || air
->family
[i
] == req
->ai_family
)
554 at
[count
].family
= air
->family
[i
];
555 memcpy (at
[count
].addr
, addrs
, size
);
556 if (air
->family
[i
] == AF_INET6
)
557 res
->got_ipv6
= true;
559 at
[count
].next
= at
+ count
+ 1;
564 if ((req
->ai_flags
& AI_CANONNAME
) && air
->canon
!= NULL
)
566 char *canonbuf
= __strdup (air
->canon
);
567 if (canonbuf
== NULL
)
569 result
= -EAI_MEMORY
;
572 res
->canon
= canonbuf
;
577 result
= -EAI_NONAME
;
581 at
[count
- 1].next
= NULL
;
590 res
->free_at
= false;
598 get_nss_addresses (const char *name
, const struct addrinfo
*req
,
599 struct scratch_buffer
*tmpbuf
, struct gaih_result
*res
)
602 int no_inet6_data
= 0;
604 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
605 enum nss_status status
= NSS_STATUS_UNAVAIL
;
607 struct resolv_context
*res_ctx
= NULL
;
608 bool do_merge
= false;
611 no_more
= !__nss_database_get (nss_database_hosts
, &nip
);
613 /* If we are looking for both IPv4 and IPv6 address we don't
614 want the lookup functions to automatically promote IPv4
615 addresses to IPv6 addresses, so we use the no_inet6
617 res_ctx
= __resolv_context_get ();
623 /* Always start afresh; continue should discard previous results
624 and the hosts database does not support merge. */
625 gaih_result_reset (res
);
629 __set_h_errno (NETDB_INTERNAL
);
635 nss_gethostbyname4_r
*fct4
= NULL
;
637 /* gethostbyname4_r sends out parallel A and AAAA queries and
638 is thus only suitable for PF_UNSPEC. */
639 if (req
->ai_family
== PF_UNSPEC
)
640 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
646 status
= DL_CALL_FCT (fct4
, (name
, &res
->at
,
647 tmpbuf
->data
, tmpbuf
->length
,
650 if (status
== NSS_STATUS_SUCCESS
)
652 /* gethostbyname4_r may write into AT, so reset it. */
654 if (status
!= NSS_STATUS_TRYAGAIN
655 || errno
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
657 if (h_errno
== TRY_AGAIN
)
660 no_data
= h_errno
== NO_DATA
;
664 if (!scratch_buffer_grow (tmpbuf
))
666 __resolv_context_put (res_ctx
);
667 result
= -EAI_MEMORY
;
672 if (status
== NSS_STATUS_SUCCESS
)
677 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && res
->canon
== NULL
)
679 char *canonbuf
= __strdup (res
->at
->name
);
680 if (canonbuf
== NULL
)
682 __resolv_context_put (res_ctx
);
683 result
= -EAI_MEMORY
;
686 res
->canon
= canonbuf
;
689 struct gaih_addrtuple
**pat
= &res
->at
;
693 if ((*pat
)->family
== AF_INET
694 && req
->ai_family
== AF_INET6
695 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
697 uint32_t *pataddr
= (*pat
)->addr
;
698 (*pat
)->family
= AF_INET6
;
699 pataddr
[3] = pataddr
[0];
700 pataddr
[2] = htonl (0xffff);
703 pat
= &((*pat
)->next
);
706 else if (req
->ai_family
== AF_UNSPEC
707 || (*pat
)->family
== req
->ai_family
)
709 pat
= &((*pat
)->next
);
712 if (req
->ai_family
== AF_INET6
)
713 res
->got_ipv6
= true;
716 *pat
= ((*pat
)->next
);
720 no_inet6_data
= no_data
;
724 nss_gethostbyname3_r
*fct
= NULL
;
725 if (req
->ai_flags
& AI_CANONNAME
)
726 /* No need to use this function if we do not look for
727 the canonical name. The function does not exist in
728 all NSS modules and therefore the lookup would
730 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
732 /* We are cheating here. The gethostbyname2_r
733 function does not have the same interface as
734 gethostbyname3_r but the extra arguments the
735 latter takes are added at the end. So the
736 gethostbyname2_r code will just ignore them. */
737 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
741 if (req
->ai_family
== AF_INET6
742 || req
->ai_family
== AF_UNSPEC
)
744 if ((result
= gethosts (fct
, AF_INET6
, name
, req
, tmpbuf
,
745 res
, &status
, &no_data
)) != 0)
747 __resolv_context_put (res_ctx
);
750 no_inet6_data
= no_data
;
751 inet6_status
= status
;
753 if (req
->ai_family
== AF_INET
754 || req
->ai_family
== AF_UNSPEC
755 || (req
->ai_family
== AF_INET6
756 && (req
->ai_flags
& AI_V4MAPPED
)
757 /* Avoid generating the mapped addresses if we
758 know we are not going to need them. */
759 && ((req
->ai_flags
& AI_ALL
) || !res
->got_ipv6
)))
761 if ((result
= gethosts (fct
, AF_INET
, name
, req
, tmpbuf
,
762 res
, &status
, &no_data
)) != 0)
764 __resolv_context_put (res_ctx
);
768 if (req
->ai_family
== AF_INET
)
770 no_inet6_data
= no_data
;
771 inet6_status
= status
;
775 /* If we found one address for AF_INET or AF_INET6,
776 don't continue the search. */
777 if (inet6_status
== NSS_STATUS_SUCCESS
778 || status
== NSS_STATUS_SUCCESS
)
780 if ((req
->ai_flags
& AI_CANONNAME
) != 0
781 && res
->canon
== NULL
)
783 char *canonbuf
= getcanonname (nip
, res
->h_name
, name
);
784 if (canonbuf
== NULL
)
786 __resolv_context_put (res_ctx
);
787 result
= -EAI_MEMORY
;
790 res
->canon
= canonbuf
;
792 status
= NSS_STATUS_SUCCESS
;
796 /* We can have different states for AF_INET and
797 AF_INET6. Try to find a useful one for both. */
798 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
799 status
= NSS_STATUS_TRYAGAIN
;
800 else if (status
== NSS_STATUS_UNAVAIL
801 && inet6_status
!= NSS_STATUS_UNAVAIL
)
802 status
= inet6_status
;
807 /* Could not locate any of the lookup functions.
808 The NSS lookup code does not consistently set
809 errno, so we need to supply our own error
810 code here. The root cause could either be a
811 resource allocation failure, or a missing
812 service function in the DSO (so it should not
813 be listed in /etc/nsswitch.conf). Assume the
814 former, and return EBUSY. */
815 status
= NSS_STATUS_UNAVAIL
;
816 __set_h_errno (NETDB_INTERNAL
);
821 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
824 /* The hosts database does not support MERGE. */
825 if (nss_next_action (nip
, status
) == NSS_ACTION_MERGE
)
829 if (nip
->module
== NULL
)
833 __resolv_context_put (res_ctx
);
835 /* If we have a failure which sets errno, report it using
837 if ((status
== NSS_STATUS_TRYAGAIN
|| status
== NSS_STATUS_UNAVAIL
)
838 && h_errno
== NETDB_INTERNAL
)
840 result
= -EAI_SYSTEM
;
844 if (no_data
!= 0 && no_inet6_data
!= 0)
846 /* If both requests timed out report this. */
847 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
850 /* We made requests but they turned out no data. The name
852 result
= -EAI_NODATA
;
857 gaih_result_reset (res
);
861 /* Convert numeric addresses to binary into RES. On failure, RES->AT is set to
862 NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and
863 the function cannot determine a result, RES->AT is set to NULL and 0
867 text_to_binary_address (const char *name
, const struct addrinfo
*req
,
868 struct gaih_result
*res
)
870 struct gaih_addrtuple
*at
= res
->at
;
875 memset (at
->addr
, 0, sizeof (at
->addr
));
876 if (__inet_aton_exact (name
, (struct in_addr
*) at
->addr
) != 0)
878 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
879 at
->family
= AF_INET
;
880 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
882 at
->addr
[3] = at
->addr
[0];
883 at
->addr
[2] = htonl (0xffff);
886 at
->family
= AF_INET6
;
890 result
= -EAI_ADDRFAMILY
;
894 if (req
->ai_flags
& AI_CANONNAME
)
896 char *canonbuf
= __strdup (name
);
897 if (canonbuf
== NULL
)
899 result
= -EAI_MEMORY
;
902 res
->canon
= canonbuf
;
907 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
910 if (scope_delim
== NULL
)
911 e
= inet_pton (AF_INET6
, name
, at
->addr
);
913 e
= __inet_pton_length (AF_INET6
, name
, scope_delim
- name
, at
->addr
);
917 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
918 at
->family
= AF_INET6
;
919 else if (req
->ai_family
== AF_INET
920 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
922 at
->addr
[0] = at
->addr
[3];
923 at
->family
= AF_INET
;
927 result
= -EAI_ADDRFAMILY
;
931 if (scope_delim
!= NULL
932 && __inet6_scopeid_pton ((struct in6_addr
*) at
->addr
,
933 scope_delim
+ 1, &at
->scopeid
) != 0)
935 result
= -EAI_NONAME
;
939 if (req
->ai_flags
& AI_CANONNAME
)
941 char *canonbuf
= __strdup (name
);
942 if (canonbuf
== NULL
)
944 result
= -EAI_MEMORY
;
947 res
->canon
= canonbuf
;
952 if ((req
->ai_flags
& AI_NUMERICHOST
))
953 result
= -EAI_NONAME
;
960 /* If possible, call the simple, old functions, which do not support IPv6 scope
961 ids, nor retrieving the canonical name. */
964 try_simple_gethostbyname (const char *name
, const struct addrinfo
*req
,
965 struct scratch_buffer
*tmpbuf
,
966 struct gaih_result
*res
)
970 if (req
->ai_family
!= AF_INET
|| (req
->ai_flags
& AI_CANONNAME
) != 0)
979 rc
= __gethostbyname2_r (name
, AF_INET
, &th
, tmpbuf
->data
,
980 tmpbuf
->length
, &h
, &h_errno
);
981 if (rc
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
983 if (!scratch_buffer_grow (tmpbuf
))
991 /* We found data, convert it. RES->AT from the conversion will
992 either be an allocated block or NULL, both of which are safe to
994 if (!convert_hostent_to_gaih_addrtuple (req
, AF_INET
, h
, res
))
1000 if (h_errno
== NO_DATA
)
1006 if (h_errno
== NETDB_INTERNAL
)
1008 if (h_errno
== TRY_AGAIN
)
1011 /* We made requests but they turned out no data.
1012 The name is known, though. */
1016 /* Add local address information into RES. RES->AT is assumed to have enough
1017 space for two tuples and is zeroed out. */
1020 get_local_addresses (const struct addrinfo
*req
, struct gaih_result
*res
)
1022 struct gaih_addrtuple
*atr
= res
->at
;
1023 if (req
->ai_family
== AF_UNSPEC
)
1024 res
->at
->next
= res
->at
+ 1;
1026 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1028 res
->at
->family
= AF_INET6
;
1029 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1030 memcpy (res
->at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1031 atr
= res
->at
->next
;
1034 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1036 atr
->family
= AF_INET
;
1037 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1038 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1042 /* Generate results in PAI and its count in NADDRS. Return 0 on success or an
1043 error code on failure. */
1046 generate_addrinfo (const struct addrinfo
*req
, struct gaih_result
*res
,
1047 const struct gaih_servtuple
*st
, struct addrinfo
**pai
,
1048 unsigned int *naddrs
)
1053 /* Buffer is the size of an unformatted IPv6 address in printable format. */
1054 for (struct gaih_addrtuple
*at
= res
->at
; at
!= NULL
; at
= at
->next
)
1056 family
= at
->family
;
1057 if (family
== AF_INET6
)
1059 socklen
= sizeof (struct sockaddr_in6
);
1061 /* If we looked up IPv4 mapped address discard them here if
1062 the caller isn't interested in all address and we have
1063 found at least one IPv6 address. */
1065 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1066 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
1070 socklen
= sizeof (struct sockaddr_in
);
1072 for (int i
= 0; st
[i
].set
; i
++)
1074 struct addrinfo
*ai
;
1075 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1079 ai
->ai_flags
= req
->ai_flags
;
1080 ai
->ai_family
= family
;
1081 ai
->ai_socktype
= st
[i
].socktype
;
1082 ai
->ai_protocol
= st
[i
].protocol
;
1083 ai
->ai_addrlen
= socklen
;
1084 ai
->ai_addr
= (void *) (ai
+ 1);
1086 /* We only add the canonical name once. */
1087 ai
->ai_canonname
= res
->canon
;
1091 ai
->ai_addr
->sa_len
= socklen
;
1092 #endif /* _HAVE_SA_LEN */
1093 ai
->ai_addr
->sa_family
= family
;
1095 /* In case of an allocation error the list must be NULL
1099 if (family
== AF_INET6
)
1101 struct sockaddr_in6
*sin6p
= (struct sockaddr_in6
*) ai
->ai_addr
;
1102 sin6p
->sin6_port
= st
[i
].port
;
1103 sin6p
->sin6_flowinfo
= 0;
1104 memcpy (&sin6p
->sin6_addr
, at
->addr
, sizeof (struct in6_addr
));
1105 sin6p
->sin6_scope_id
= at
->scopeid
;
1109 struct sockaddr_in
*sinp
= (struct sockaddr_in
*) ai
->ai_addr
;
1110 sinp
->sin_port
= st
[i
].port
;
1111 memcpy (&sinp
->sin_addr
, at
->addr
, sizeof (struct in_addr
));
1112 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1115 pai
= &(ai
->ai_next
);
1124 gaih_inet (const char *name
, const struct gaih_service
*service
,
1125 const struct addrinfo
*req
, struct addrinfo
**pai
,
1126 unsigned int *naddrs
, struct scratch_buffer
*tmpbuf
)
1128 struct gaih_servtuple st
[sizeof (gaih_inet_typeproto
)
1129 / sizeof (struct gaih_typeproto
)] = {0};
1131 const char *orig_name
= name
;
1134 if ((rc
= get_servtuples (service
, req
, st
, tmpbuf
)) != 0)
1137 bool malloc_name
= false;
1138 struct gaih_addrtuple
*addrmem
= NULL
;
1141 struct gaih_result res
= {0};
1142 struct gaih_addrtuple local_at
[2] = {0};
1146 if (__glibc_unlikely (name
== NULL
))
1148 get_local_addresses (req
, &res
);
1152 if (req
->ai_flags
& AI_IDN
)
1155 result
= __idna_to_dns_encoding (name
, &out
);
1162 if ((result
= text_to_binary_address (name
, req
, &res
)) != 0)
1163 goto free_and_return
;
1164 else if (res
.at
!= NULL
)
1167 if ((result
= try_simple_gethostbyname (name
, req
, tmpbuf
, &res
)) != 0)
1168 goto free_and_return
;
1169 else if (res
.at
!= NULL
)
1173 if ((result
= get_nscd_addresses (name
, req
, &res
)) != 0)
1174 goto free_and_return
;
1175 else if (res
.at
!= NULL
)
1179 if ((result
= get_nss_addresses (name
, req
, tmpbuf
, &res
)) != 0)
1180 goto free_and_return
;
1181 else if (res
.at
!= NULL
)
1184 /* None of the lookups worked, so name not found. */
1185 result
= -EAI_NONAME
;
1186 goto free_and_return
;
1189 /* Set up the canonical name if we need it. */
1190 if ((result
= process_canonname (req
, orig_name
, &res
)) != 0)
1191 goto free_and_return
;
1193 result
= generate_addrinfo (req
, &res
, st
, pai
, naddrs
);
1197 free ((char *) name
);
1199 gaih_result_reset (&res
);
1207 struct addrinfo
*dest_addr
;
1208 /* Using sockaddr_storage is for now overkill. We only support IPv4
1209 and IPv6 so far. If this changes at some point we can adjust the
1211 struct sockaddr_in6 source_addr
;
1212 uint8_t source_addr_len
;
1213 bool got_source_addr
;
1214 uint8_t source_addr_flags
;
1220 struct sort_result_combo
1222 struct sort_result
*results
;
1227 #if __BYTE_ORDER == __BIG_ENDIAN
1228 # define htonl_c(n) n
1230 # define htonl_c(n) __bswap_constant_32 (n)
1233 static const struct scopeentry
1242 } default_scopes
[] =
1244 /* Link-local addresses: scope 2. */
1245 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1246 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1247 /* Default: scope 14. */
1248 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1251 /* The label table. */
1252 static const struct scopeentry
*scopes
;
1256 get_scope (const struct sockaddr_in6
*in6
)
1259 if (in6
->sin6_family
== PF_INET6
)
1261 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1263 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1264 /* RFC 4291 2.5.3 says that the loopback address is to be
1265 treated like a link-local address. */
1266 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1268 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1271 /* XXX Is this the correct default behavior? */
1275 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1277 else if (in6
->sin6_family
== PF_INET
)
1279 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1284 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1285 == scopes
[cnt
].addr32
)
1286 return scopes
[cnt
].scope
;
1293 /* XXX What is a good default? */
1302 struct in6_addr prefix
;
1308 /* The label table. */
1309 static const struct prefixentry
*labels
;
1311 /* Default labels. */
1312 static const struct prefixentry default_labels
[] =
1314 /* See RFC 3484 for the details. */
1316 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1320 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1324 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1328 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1329 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1331 /* The next two entries differ from RFC 3484. We need to treat
1332 IPv6 site-local addresses special because they are never NATed,
1333 unlike site-locale IPv4 addresses. If this would not happen, on
1334 machines which have only IPv4 and IPv6 site-local addresses, the
1335 sorting would prefer the IPv6 site-local addresses, causing
1336 unnecessary delays when trying to connect to a global IPv6 address
1337 through a site-local IPv6 address. */
1339 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1343 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1346 /* Additional rule for Teredo tunnels. */
1348 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1349 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1352 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1358 /* The precedence table. */
1359 static const struct prefixentry
*precedence
;
1361 /* The default precedences. */
1362 static const struct prefixentry default_precedence
[] =
1364 /* See RFC 3484 for the details. */
1366 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1370 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1374 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1378 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1382 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1389 match_prefix (const struct sockaddr_in6
*in6
,
1390 const struct prefixentry
*list
, int default_val
)
1393 struct sockaddr_in6 in6_mem
;
1395 if (in6
->sin6_family
== PF_INET
)
1397 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1399 /* Construct a V4-to-6 mapped address. */
1400 in6_mem
.sin6_family
= PF_INET6
;
1401 in6_mem
.sin6_port
= in
->sin_port
;
1402 in6_mem
.sin6_flowinfo
= 0;
1403 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1404 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1405 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1406 in6_mem
.sin6_scope_id
= 0;
1410 else if (in6
->sin6_family
!= PF_INET6
)
1413 for (idx
= 0; ; ++idx
)
1415 unsigned int bits
= list
[idx
].bits
;
1416 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1417 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1431 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1437 return list
[idx
].val
;
1442 get_label (const struct sockaddr_in6
*in6
)
1444 /* XXX What is a good default value? */
1445 return match_prefix (in6
, labels
, INT_MAX
);
1450 get_precedence (const struct sockaddr_in6
*in6
)
1452 /* XXX What is a good default value? */
1453 return match_prefix (in6
, precedence
, 0);
1457 /* Find last bit set in a word. */
1463 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1464 if ((a
& mask
) != 0)
1471 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1473 const size_t idx1
= *(const size_t *) p1
;
1474 const size_t idx2
= *(const size_t *) p2
;
1475 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1476 struct sort_result
*a1
= &src
->results
[idx1
];
1477 struct sort_result
*a2
= &src
->results
[idx2
];
1479 /* Rule 1: Avoid unusable destinations.
1480 We have the got_source_addr flag set if the destination is reachable. */
1481 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1483 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1487 /* Rule 2: Prefer matching scope. Only interesting if both
1488 destination addresses are IPv6. */
1490 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1493 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1495 if (a1
->got_source_addr
)
1497 int a1_src_scope
= get_scope (&a1
->source_addr
);
1498 int a2_src_scope
= get_scope (&a2
->source_addr
);
1500 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1502 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1507 /* Rule 3: Avoid deprecated addresses. */
1508 if (a1
->got_source_addr
)
1510 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1511 && (a2
->source_addr_flags
& in6ai_deprecated
))
1513 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1514 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1518 /* Rule 4: Prefer home addresses. */
1519 if (a1
->got_source_addr
)
1521 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1522 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1524 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1525 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1529 /* Rule 5: Prefer matching label. */
1530 if (a1
->got_source_addr
)
1533 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1534 int a1_src_label
= get_label (&a1
->source_addr
);
1537 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1538 int a2_src_label
= get_label (&a2
->source_addr
);
1540 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1542 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1547 /* Rule 6: Prefer higher precedence. */
1549 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1551 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1553 if (a1_prec
> a2_prec
)
1555 if (a1_prec
< a2_prec
)
1559 /* Rule 7: Prefer native transport. */
1560 if (a1
->got_source_addr
)
1562 /* The same interface index means the same interface which means
1563 there is no difference in transport. This should catch many
1565 if (a1
->index
!= a2
->index
)
1567 int a1_native
= a1
->native
;
1568 int a2_native
= a2
->native
;
1570 if (a1_native
== -1 || a2_native
== -1)
1573 if (a1_native
== -1)
1575 /* If we do not have the information use 'native' as
1578 a1_index
= a1
->index
;
1581 a1_index
= 0xffffffffu
;
1584 if (a2_native
== -1)
1586 /* If we do not have the information use 'native' as
1589 a2_index
= a2
->index
;
1592 a2_index
= 0xffffffffu
;
1594 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1596 /* Fill in the results in all the records. */
1597 for (int i
= 0; i
< src
->nresults
; ++i
)
1598 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1600 assert (src
->results
[i
].native
== -1
1601 || src
->results
[i
].native
== a1_native
);
1602 src
->results
[i
].native
= a1_native
;
1604 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1606 assert (src
->results
[i
].native
== -1
1607 || src
->results
[i
].native
== a2_native
);
1608 src
->results
[i
].native
= a2_native
;
1612 if (a1_native
&& !a2_native
)
1614 if (!a1_native
&& a2_native
)
1620 /* Rule 8: Prefer smaller scope. */
1621 if (a1_dst_scope
< a2_dst_scope
)
1623 if (a1_dst_scope
> a2_dst_scope
)
1627 /* Rule 9: Use longest matching prefix. */
1628 if (a1
->got_source_addr
1629 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1634 if (a1
->dest_addr
->ai_family
== PF_INET
)
1636 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1637 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1639 /* Outside of subnets, as defined by the network masks,
1640 common address prefixes for IPv4 addresses make no sense.
1641 So, define a non-zero value only if source and
1642 destination address are on the same subnet. */
1643 struct sockaddr_in
*in1_dst
1644 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1645 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1646 struct sockaddr_in
*in1_src
1647 = (struct sockaddr_in
*) &a1
->source_addr
;
1648 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1649 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1651 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1652 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1654 struct sockaddr_in
*in2_dst
1655 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1656 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1657 struct sockaddr_in
*in2_src
1658 = (struct sockaddr_in
*) &a2
->source_addr
;
1659 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1660 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1662 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1663 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1665 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1667 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1668 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1670 struct sockaddr_in6
*in1_dst
;
1671 struct sockaddr_in6
*in1_src
;
1672 struct sockaddr_in6
*in2_dst
;
1673 struct sockaddr_in6
*in2_src
;
1675 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1676 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1677 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1678 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1681 for (i
= 0; i
< 4; ++i
)
1682 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1683 != in1_src
->sin6_addr
.s6_addr32
[i
]
1684 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1685 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1690 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1691 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1692 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1693 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1704 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1705 compare with the value indicating the order in which the entries
1706 have been received from the services. NB: no two entries can have
1707 the same order so the test will never return zero. */
1708 return idx1
< idx2
? -1 : 1;
1713 in6aicmp (const void *p1
, const void *p2
)
1715 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1716 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1718 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1722 /* Name of the config file for RFC 3484 sorting (for now). */
1723 #define GAICONF_FNAME "/etc/gai.conf"
1726 /* Non-zero if we are supposed to reload the config file automatically
1727 whenever it changed. */
1728 static int gaiconf_reload_flag
;
1730 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1731 static int gaiconf_reload_flag_ever_set
;
1733 /* Last modification time. */
1734 #ifdef _STATBUF_ST_NSEC
1736 static struct __timespec64 gaiconf_mtime
;
1739 save_gaiconf_mtime (const struct __stat64_t64
*st
)
1741 gaiconf_mtime
= (struct __timespec64
) { st
->st_mtim
.tv_sec
,
1742 st
->st_mtim
.tv_nsec
};
1746 check_gaiconf_mtime (const struct __stat64_t64
*st
)
1748 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1749 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1754 static time_t gaiconf_mtime
;
1757 save_gaiconf_mtime (const struct __stat64_t64
*st
)
1759 gaiconf_mtime
= st
->st_mtime
;
1763 check_gaiconf_mtime (const struct __stat64_t64
*st
)
1765 return st
->st_mtime
== gaiconf_mtime
;
1772 __libc_getaddrinfo_freemem (void)
1774 if (labels
!= default_labels
)
1776 const struct prefixentry
*old
= labels
;
1777 labels
= default_labels
;
1778 free ((void *) old
);
1781 if (precedence
!= default_precedence
)
1783 const struct prefixentry
*old
= precedence
;
1784 precedence
= default_precedence
;
1785 free ((void *) old
);
1788 if (scopes
!= default_scopes
)
1790 const struct scopeentry
*old
= scopes
;
1791 scopes
= default_scopes
;
1792 free ((void *) old
);
1799 struct prefixentry entry
;
1800 struct prefixlist
*next
;
1806 struct scopeentry entry
;
1807 struct scopelist
*next
;
1812 free_prefixlist (struct prefixlist
*list
)
1814 while (list
!= NULL
)
1816 struct prefixlist
*oldp
= list
;
1824 free_scopelist (struct scopelist
*list
)
1826 while (list
!= NULL
)
1828 struct scopelist
*oldp
= list
;
1836 prefixcmp (const void *p1
, const void *p2
)
1838 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1839 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1841 if (e1
->bits
< e2
->bits
)
1843 if (e1
->bits
== e2
->bits
)
1850 scopecmp (const void *p1
, const void *p2
)
1852 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1853 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1855 if (e1
->netmask
> e2
->netmask
)
1857 if (e1
->netmask
== e2
->netmask
)
1863 add_prefixlist (struct prefixlist
**listp
, size_t *lenp
, bool *nullbitsp
,
1864 char *val1
, char *val2
, char **pos
)
1866 struct in6_addr prefix
;
1867 unsigned long int bits
;
1868 unsigned long int val
;
1873 char *cp
= strchr (val1
, '/');
1877 if (inet_pton (AF_INET6
, val1
, &prefix
)
1879 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1883 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1888 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1892 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1893 newp
->entry
.bits
= bits
;
1894 newp
->entry
.val
= val
;
1895 newp
->next
= *listp
;
1898 *nullbitsp
|= bits
== 0;
1904 add_scopelist (struct scopelist
**listp
, size_t *lenp
, bool *nullbitsp
,
1905 const struct in6_addr
*prefixp
, unsigned long int bits
,
1906 unsigned long int val
)
1908 struct scopelist
*newp
= malloc (sizeof (*newp
));
1912 newp
->entry
.netmask
= htonl (bits
!= 96 ? (0xffffffff << (128 - bits
)) : 0);
1913 newp
->entry
.addr32
= (prefixp
->s6_addr32
[3] & newp
->entry
.netmask
);
1914 newp
->entry
.scope
= val
;
1915 newp
->next
= *listp
;
1918 *nullbitsp
|= bits
== 96;
1926 struct prefixlist
*labellist
= NULL
;
1927 size_t nlabellist
= 0;
1928 bool labellist_nullbits
= false;
1929 struct prefixlist
*precedencelist
= NULL
;
1930 size_t nprecedencelist
= 0;
1931 bool precedencelist_nullbits
= false;
1932 struct scopelist
*scopelist
= NULL
;
1933 size_t nscopelist
= 0;
1934 bool scopelist_nullbits
= false;
1936 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1940 struct __stat64_t64 st
;
1941 if (__fstat64_time64 (fileno (fp
), &st
) != 0)
1950 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1952 while (!feof_unlocked (fp
))
1954 ssize_t n
= __getline (&line
, &linelen
, fp
);
1958 /* Handle comments. No escaping possible so this is easy. */
1959 char *cp
= strchr (line
, '#');
1964 while (isspace (*cp
))
1968 while (*cp
!= '\0' && !isspace (*cp
))
1970 size_t cmdlen
= cp
- cmd
;
1974 while (isspace (*cp
))
1978 while (*cp
!= '\0' && !isspace (*cp
))
1980 size_t val1len
= cp
- cmd
;
1982 /* We always need at least two values. */
1988 while (isspace (*cp
))
1992 while (*cp
!= '\0' && !isspace (*cp
))
1995 /* Ignore the rest of the line. */
2001 if (strcmp (cmd
, "label") == 0)
2003 if (!add_prefixlist (&labellist
, &nlabellist
,
2004 &labellist_nullbits
, val1
, val2
, &cp
))
2014 if (strcmp (cmd
, "reload") == 0)
2016 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2017 if (gaiconf_reload_flag
)
2018 gaiconf_reload_flag_ever_set
= 1;
2023 if (strcmp (cmd
, "scopev4") == 0)
2025 struct in6_addr prefix
;
2026 unsigned long int bits
;
2027 unsigned long int val
;
2032 cp
= strchr (val1
, '/');
2035 if (inet_pton (AF_INET6
, val1
, &prefix
))
2038 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2040 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2045 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2050 if (!add_scopelist (&scopelist
, &nscopelist
,
2051 &scopelist_nullbits
, &prefix
,
2060 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2062 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2066 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2071 if (!add_scopelist (&scopelist
, &nscopelist
,
2072 &scopelist_nullbits
, &prefix
,
2084 if (strcmp (cmd
, "precedence") == 0)
2086 if (!add_prefixlist (&precedencelist
, &nprecedencelist
,
2087 &precedencelist_nullbits
, val1
, val2
,
2103 /* Create the array for the labels. */
2104 struct prefixentry
*new_labels
;
2107 if (!labellist_nullbits
)
2109 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2110 if (new_labels
== NULL
)
2114 if (!labellist_nullbits
)
2117 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2118 new_labels
[i
].bits
= 0;
2119 new_labels
[i
].val
= 1;
2122 struct prefixlist
*l
= labellist
;
2125 new_labels
[i
] = l
->entry
;
2128 free_prefixlist (labellist
);
2131 /* Sort the entries so that the most specific ones are at
2133 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2136 new_labels
= (struct prefixentry
*) default_labels
;
2138 struct prefixentry
*new_precedence
;
2139 if (nprecedencelist
> 0)
2141 if (!precedencelist_nullbits
)
2143 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2144 if (new_precedence
== NULL
)
2146 if (new_labels
!= default_labels
)
2151 int i
= nprecedencelist
;
2152 if (!precedencelist_nullbits
)
2155 memset (&new_precedence
[i
].prefix
, '\0',
2156 sizeof (struct in6_addr
));
2157 new_precedence
[i
].bits
= 0;
2158 new_precedence
[i
].val
= 40;
2161 struct prefixlist
*l
= precedencelist
;
2164 new_precedence
[i
] = l
->entry
;
2167 free_prefixlist (precedencelist
);
2168 precedencelist
= NULL
;
2170 /* Sort the entries so that the most specific ones are at
2172 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2176 new_precedence
= (struct prefixentry
*) default_precedence
;
2178 struct scopeentry
*new_scopes
;
2181 if (!scopelist_nullbits
)
2183 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2184 if (new_scopes
== NULL
)
2186 if (new_labels
!= default_labels
)
2188 if (new_precedence
!= default_precedence
)
2189 free (new_precedence
);
2194 if (!scopelist_nullbits
)
2197 new_scopes
[i
].addr32
= 0;
2198 new_scopes
[i
].netmask
= 0;
2199 new_scopes
[i
].scope
= 14;
2202 struct scopelist
*l
= scopelist
;
2205 new_scopes
[i
] = l
->entry
;
2208 free_scopelist (scopelist
);
2210 /* Sort the entries so that the most specific ones are at
2212 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2216 new_scopes
= (struct scopeentry
*) default_scopes
;
2218 /* Now we are ready to replace the values. */
2219 const struct prefixentry
*old
= labels
;
2220 labels
= new_labels
;
2221 if (old
!= default_labels
)
2222 free ((void *) old
);
2225 precedence
= new_precedence
;
2226 if (old
!= default_precedence
)
2227 free ((void *) old
);
2229 const struct scopeentry
*oldscope
= scopes
;
2230 scopes
= new_scopes
;
2231 if (oldscope
!= default_scopes
)
2232 free ((void *) oldscope
);
2234 save_gaiconf_mtime (&st
);
2238 free_prefixlist (labellist
);
2239 free_prefixlist (precedencelist
);
2240 free_scopelist (scopelist
);
2242 /* If we previously read the file but it is gone now, free the old data and
2243 use the builtin one. Leave the reload flag alone. */
2244 __libc_getaddrinfo_freemem ();
2249 gaiconf_reload (void)
2251 struct __stat64_t64 st
;
2252 if (__stat64_time64 (GAICONF_FNAME
, &st
) != 0
2253 || !check_gaiconf_mtime (&st
))
2258 try_connect (int *fdp
, int *afp
, struct sockaddr_in6
*source_addrp
,
2259 const struct sockaddr
*addr
, socklen_t addrlen
, int family
)
2263 socklen_t sl
= sizeof (*source_addrp
);
2267 if (fd
!= -1 && __connect (fd
, addr
, addrlen
) == 0
2268 && __getsockname (fd
, (struct sockaddr
*) source_addrp
, &sl
) == 0)
2271 if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
&& family
== AF_INET
)
2273 /* This could mean IPv6 sockets are IPv6-only. */
2275 __close_nocancel_nostatus (fd
);
2276 *afp
= af
= AF_INET
;
2277 *fdp
= fd
= __socket (AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
,
2285 __builtin_unreachable ();
2289 getaddrinfo (const char *name
, const char *service
,
2290 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2292 int i
= 0, last_i
= 0;
2294 struct addrinfo
*p
= NULL
;
2295 struct gaih_service gaih_service
, *pservice
;
2296 struct addrinfo local_hints
;
2298 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2301 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2304 if (name
== NULL
&& service
== NULL
)
2308 hints
= &default_hints
;
2311 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2312 |AI_IDN
|AI_CANONIDN
|DEPRECATED_AI_IDN
2313 |AI_NUMERICSERV
|AI_ALL
))
2314 return EAI_BADFLAGS
;
2316 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2317 return EAI_BADFLAGS
;
2319 if (hints
->ai_family
!= AF_UNSPEC
&& hints
->ai_family
!= AF_INET
2320 && hints
->ai_family
!= AF_INET6
)
2323 struct in6addrinfo
*in6ai
= NULL
;
2324 size_t in6ailen
= 0;
2325 bool seen_ipv4
= false;
2326 bool seen_ipv6
= false;
2327 bool check_pf_called
= false;
2329 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2331 /* We might need information about what interfaces are available.
2332 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2333 cannot cache the results since new interfaces could be added at
2335 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2336 check_pf_called
= true;
2338 /* Now make a decision on what we return, if anything. */
2339 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2341 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2342 narrow down the search. */
2343 if (seen_ipv4
!= seen_ipv6
)
2345 local_hints
= *hints
;
2346 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2347 hints
= &local_hints
;
2350 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2351 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2353 /* We cannot possibly return a valid answer. */
2354 __free_in6ai (in6ai
);
2359 if (service
&& service
[0])
2362 gaih_service
.name
= service
;
2363 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2366 if (hints
->ai_flags
& AI_NUMERICSERV
)
2368 __free_in6ai (in6ai
);
2372 gaih_service
.num
= -1;
2375 pservice
= &gaih_service
;
2380 struct addrinfo
**end
= &p
;
2381 unsigned int naddrs
= 0;
2382 struct scratch_buffer tmpbuf
;
2384 scratch_buffer_init (&tmpbuf
);
2385 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
, &tmpbuf
);
2386 scratch_buffer_free (&tmpbuf
);
2391 __free_in6ai (in6ai
);
2398 end
= &((*end
)->ai_next
);
2404 /* Read the config file. */
2405 __libc_once_define (static, once
);
2406 __typeof (once
) old_once
= once
;
2407 __libc_once (once
, gaiconf_init
);
2408 /* Sort results according to RFC 3484. */
2409 struct sort_result
*results
;
2412 struct addrinfo
*last
= NULL
;
2413 char *canonname
= NULL
;
2414 struct scratch_buffer buf
;
2415 scratch_buffer_init (&buf
);
2417 if (!scratch_buffer_set_array_size (&buf
, nresults
,
2418 sizeof (*results
) + sizeof (size_t)))
2420 __free_in6ai (in6ai
);
2425 order
= (size_t *) (results
+ nresults
);
2427 /* Now we definitely need the interface information. */
2428 if (! check_pf_called
)
2429 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2431 /* If we have information about deprecated and temporary addresses
2432 sort the array now. */
2434 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2439 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2441 results
[i
].dest_addr
= q
;
2442 results
[i
].native
= -1;
2445 /* If we just looked up the address for a different
2446 protocol, reuse the result. */
2447 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2448 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2450 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2451 results
[i
- 1].source_addr_len
);
2452 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2453 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2454 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2455 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2456 results
[i
].index
= results
[i
- 1].index
;
2460 results
[i
].got_source_addr
= false;
2461 results
[i
].source_addr_flags
= 0;
2462 results
[i
].prefixlen
= 0;
2463 results
[i
].index
= 0xffffffffu
;
2465 /* We overwrite the type with SOCK_DGRAM since we do not
2466 want connect() to connect to the other side. If we
2467 cannot determine the source address remember this
2469 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2472 __close_nocancel_nostatus (fd
);
2474 fd
= __socket (af
, SOCK_DGRAM
| SOCK_CLOEXEC
, IPPROTO_IP
);
2478 /* Reset the connection. */
2479 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2480 __connect (fd
, &sa
, sizeof (sa
));
2483 if (try_connect (&fd
, &af
, &results
[i
].source_addr
, q
->ai_addr
,
2484 q
->ai_addrlen
, q
->ai_family
))
2486 results
[i
].source_addr_len
= sizeof (results
[i
].source_addr
);
2487 results
[i
].got_source_addr
= true;
2491 /* See whether the source address is on the list of
2492 deprecated or temporary addresses. */
2493 struct in6addrinfo tmp
;
2495 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2497 struct sockaddr_in
*sinp
2498 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2501 tmp
.addr
[2] = htonl (0xffff);
2502 /* Special case for lo interface, the source address
2503 being possibly different than the interface
2505 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2507 tmp
.addr
[3] = htonl(0x7f000001);
2509 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2513 struct sockaddr_in6
*sin6p
2514 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2515 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2518 struct in6addrinfo
*found
2519 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2523 results
[i
].source_addr_flags
= found
->flags
;
2524 results
[i
].prefixlen
= found
->prefixlen
;
2525 results
[i
].index
= found
->index
;
2529 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2531 /* We have to convert the address. The socket is
2532 IPv6 and the request is for IPv4. */
2533 struct sockaddr_in6
*sin6
2534 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2535 struct sockaddr_in
*sin
2536 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2537 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2538 sin
->sin_family
= AF_INET
;
2539 /* We do not have to initialize sin_port since this
2540 fields has the same position and size in the IPv6
2542 assert (offsetof (struct sockaddr_in
, sin_port
)
2543 == offsetof (struct sockaddr_in6
, sin6_port
));
2544 assert (sizeof (sin
->sin_port
)
2545 == sizeof (sin6
->sin6_port
));
2546 memcpy (&sin
->sin_addr
,
2547 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2548 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2552 /* Just make sure that if we have to process the same
2553 address again we do not copy any memory. */
2554 results
[i
].source_addr_len
= 0;
2557 /* Remember the canonical name. */
2558 if (q
->ai_canonname
!= NULL
)
2560 assert (canonname
== NULL
);
2561 canonname
= q
->ai_canonname
;
2562 q
->ai_canonname
= NULL
;
2567 __close_nocancel_nostatus (fd
);
2569 /* We got all the source addresses we can get, now sort using
2571 struct sort_result_combo src
2572 = { .results
= results
, .nresults
= nresults
};
2573 if (__glibc_unlikely (gaiconf_reload_flag_ever_set
))
2575 __libc_lock_define_initialized (static, lock
);
2577 __libc_lock_lock (lock
);
2578 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2580 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2581 __libc_lock_unlock (lock
);
2584 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2586 /* Queue the results up as they come out of sorting. */
2587 q
= p
= results
[order
[0]].dest_addr
;
2588 for (i
= 1; i
< nresults
; ++i
)
2589 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2592 /* Fill in the canonical name into the new first entry. */
2593 p
->ai_canonname
= canonname
;
2595 scratch_buffer_free (&buf
);
2598 __free_in6ai (in6ai
);
2606 return last_i
? -last_i
: EAI_NONAME
;
2608 libc_hidden_def (getaddrinfo
)
2610 nss_interface_function (getaddrinfo
)
2613 freeaddrinfo (struct addrinfo
*ai
)
2621 free (p
->ai_canonname
);
2625 libc_hidden_def (freeaddrinfo
)