1 /* Host and service name lookups using Name Service Switch modules.
2 Copyright (C) 1996-2018 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 <http://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>
64 #include <resolv/res_use_inet6.h>
67 #include <stdio_ext.h>
71 #include <arpa/inet.h>
73 #include <netinet/in.h>
74 #include <sys/socket.h>
76 #include <sys/types.h>
78 #include <sys/utsname.h>
81 #include <libc-lock.h>
82 #include <not-cancel.h>
83 #include <nscd/nscd-client.h>
84 #include <nscd/nscd_proto.h>
85 #include <scratch_buffer.h>
86 #include <inet/net-internal.h>
93 # define feof_unlocked(fp) __feof_unlocked (fp)
102 struct gaih_servtuple
104 struct gaih_servtuple
*next
;
110 static const struct gaih_servtuple nullserv
;
113 struct gaih_typeproto
122 /* Values for `protoflag'. */
123 #define GAI_PROTO_NOSERVICE 1
124 #define GAI_PROTO_PROTOANY 2
126 static const struct gaih_typeproto gaih_inet_typeproto
[] =
128 { 0, 0, 0, false, "" },
129 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
130 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
131 #if defined SOCK_DCCP && defined IPPROTO_DCCP
132 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
134 #ifdef IPPROTO_UDPLITE
135 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
138 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
139 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
141 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
142 { 0, 0, 0, false, "" }
145 static const struct addrinfo default_hints
=
147 .ai_flags
= AI_DEFAULT
,
148 .ai_family
= PF_UNSPEC
,
153 .ai_canonname
= NULL
,
159 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
160 const struct addrinfo
*req
, struct gaih_servtuple
*st
,
161 struct scratch_buffer
*tmpbuf
)
169 r
= __getservbyname_r (servicename
, tp
->name
, &ts
,
170 tmpbuf
->data
, tmpbuf
->length
, &s
);
171 if (r
!= 0 || s
== NULL
)
175 if (!scratch_buffer_grow (tmpbuf
))
185 st
->socktype
= tp
->socktype
;
186 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
187 ? req
->ai_protocol
: tp
->protocol
);
188 st
->port
= s
->s_port
;
193 /* Convert struct hostent to a list of struct gaih_addrtuple objects.
194 h_name is not copied, and the struct hostent object must not be
195 deallocated prematurely. *RESULT must be NULL or a pointer to a
196 linked-list. The new addresses are appended at the end. */
198 convert_hostent_to_gaih_addrtuple (const struct addrinfo
*req
,
201 struct gaih_addrtuple
**result
)
204 result
= &(*result
)->next
;
206 /* Count the number of addresses in h->h_addr_list. */
208 for (char **p
= h
->h_addr_list
; *p
!= NULL
; ++p
)
211 /* Report no data if no addresses are available, or if the incoming
212 address size is larger than what we can store. */
213 if (count
== 0 || h
->h_length
> sizeof (((struct gaih_addrtuple
) {}).addr
))
216 struct gaih_addrtuple
*array
= calloc (count
, sizeof (*array
));
220 for (size_t i
= 0; i
< count
; ++i
)
222 if (family
== AF_INET
&& req
->ai_family
== AF_INET6
)
224 /* Perform address mapping. */
225 array
[i
].family
= AF_INET6
;
226 memcpy(array
[i
].addr
+ 3, h
->h_addr_list
[i
], sizeof (uint32_t));
227 array
[i
].addr
[2] = htonl (0xffff);
231 array
[i
].family
= family
;
232 memcpy (array
[i
].addr
, h
->h_addr_list
[i
], h
->h_length
);
234 array
[i
].next
= array
+ i
+ 1;
236 array
[0].name
= h
->h_name
;
237 array
[count
- 1].next
= NULL
;
243 #define gethosts(_family, _type) \
246 char *localcanon = NULL; \
250 status = DL_CALL_FCT (fct, (name, _family, &th, \
251 tmpbuf->data, tmpbuf->length, \
252 &errno, &h_errno, NULL, &localcanon)); \
253 if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \
254 || errno != ERANGE) \
256 if (!scratch_buffer_grow (tmpbuf)) \
258 __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
259 __resolv_context_put (res_ctx); \
260 result = -EAI_MEMORY; \
261 goto free_and_return; \
264 if (status == NSS_STATUS_NOTFOUND \
265 || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \
267 if (h_errno == NETDB_INTERNAL) \
269 __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
270 __resolv_context_put (res_ctx); \
271 result = -EAI_SYSTEM; \
272 goto free_and_return; \
274 if (h_errno == TRY_AGAIN) \
275 no_data = EAI_AGAIN; \
277 no_data = h_errno == NO_DATA; \
279 else if (status == NSS_STATUS_SUCCESS) \
281 if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
283 __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
284 __resolv_context_put (res_ctx); \
285 result = -EAI_SYSTEM; \
286 goto free_and_return; \
290 if (localcanon != NULL && canon == NULL) \
292 canonbuf = __strdup (localcanon); \
293 if (canonbuf == NULL) \
295 result = -EAI_SYSTEM; \
296 goto free_and_return; \
300 if (_family == AF_INET6 && *pat != NULL) \
306 typedef enum nss_status (*nss_gethostbyname4_r
)
307 (const char *name
, struct gaih_addrtuple
**pat
,
308 char *buffer
, size_t buflen
, int *errnop
,
309 int *h_errnop
, int32_t *ttlp
);
310 typedef enum nss_status (*nss_gethostbyname3_r
)
311 (const char *name
, int af
, struct hostent
*host
,
312 char *buffer
, size_t buflen
, int *errnop
,
313 int *h_errnop
, int32_t *ttlp
, char **canonp
);
314 typedef enum nss_status (*nss_getcanonname_r
)
315 (const char *name
, char *buffer
, size_t buflen
, char **result
,
316 int *errnop
, int *h_errnop
);
318 /* This function is called if a canonical name is requested, but if
319 the service function did not provide it. It tries to obtain the
320 name using getcanonname_r from the same service NIP. If the name
321 cannot be canonicalized, return a copy of NAME. Return NULL on
322 memory allocation failure. The returned string is allocated on the
323 heap; the caller has to free it. */
325 getcanonname (service_user
*nip
, struct gaih_addrtuple
*at
, const char *name
)
327 nss_getcanonname_r cfct
= __nss_lookup_function (nip
, "getcanonname_r");
328 char *s
= (char *) name
;
332 if (DL_CALL_FCT (cfct
, (at
->name
?: name
, buf
, sizeof (buf
),
333 &s
, &errno
, &h_errno
)) != NSS_STATUS_SUCCESS
)
334 /* If the canonical name cannot be determined, use the passed
338 return __strdup (name
);
342 gaih_inet (const char *name
, const struct gaih_service
*service
,
343 const struct addrinfo
*req
, struct addrinfo
**pai
,
344 unsigned int *naddrs
, struct scratch_buffer
*tmpbuf
)
346 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
347 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
348 struct gaih_addrtuple
*at
= NULL
;
349 bool got_ipv6
= false;
350 const char *canon
= NULL
;
351 const char *orig_name
= name
;
353 /* Reserve stack memory for the scratch buffer in the getaddrinfo
355 size_t alloca_used
= sizeof (struct scratch_buffer
);
357 if (req
->ai_protocol
|| req
->ai_socktype
)
362 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
363 || (req
->ai_protocol
!= 0
364 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
365 && req
->ai_protocol
!= tp
->protocol
)))
370 if (req
->ai_socktype
)
371 return -EAI_SOCKTYPE
;
380 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
383 if (service
->num
< 0)
387 st
= (struct gaih_servtuple
*)
388 alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
390 int rc
= gaih_inet_serv (service
->name
, tp
, req
, st
, tmpbuf
);
391 if (__glibc_unlikely (rc
!= 0))
396 struct gaih_servtuple
**pst
= &st
;
397 for (tp
++; tp
->name
[0]; tp
++)
399 struct gaih_servtuple
*newp
;
401 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
404 if (req
->ai_socktype
!= 0
405 && req
->ai_socktype
!= tp
->socktype
)
407 if (req
->ai_protocol
!= 0
408 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
409 && req
->ai_protocol
!= tp
->protocol
)
412 newp
= (struct gaih_servtuple
*)
413 alloca_account (sizeof (struct gaih_servtuple
),
416 if (gaih_inet_serv (service
->name
,
417 tp
, req
, newp
, tmpbuf
) != 0)
423 if (st
== (struct gaih_servtuple
*) &nullserv
)
429 port
= htons (service
->num
);
437 if (req
->ai_socktype
|| req
->ai_protocol
)
439 st
= alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
441 st
->socktype
= tp
->socktype
;
442 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
443 ? req
->ai_protocol
: tp
->protocol
);
448 /* Neither socket type nor protocol is set. Return all socket types
450 struct gaih_servtuple
**lastp
= &st
;
451 for (++tp
; tp
->name
[0]; ++tp
)
454 struct gaih_servtuple
*newp
;
456 newp
= alloca_account (sizeof (struct gaih_servtuple
),
459 newp
->socktype
= tp
->socktype
;
460 newp
->protocol
= tp
->protocol
;
469 bool malloc_name
= false;
470 struct gaih_addrtuple
*addrmem
= NULL
;
471 char *canonbuf
= NULL
;
476 at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
477 at
->family
= AF_UNSPEC
;
482 if (req
->ai_flags
& AI_IDN
)
485 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
486 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
487 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
488 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
491 int rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
492 if (rc
!= IDNA_SUCCESS
)
494 /* No need to jump to free_and_return here. */
495 if (rc
== IDNA_MALLOC_ERROR
)
497 if (rc
== IDNA_DLOPEN_ERROR
)
499 return -EAI_IDN_ENCODE
;
501 /* In case the output string is the same as the input string
502 no new string has been allocated. */
511 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
513 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
514 at
->family
= AF_INET
;
515 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
517 at
->addr
[3] = at
->addr
[0];
518 at
->addr
[2] = htonl (0xffff);
521 at
->family
= AF_INET6
;
525 result
= -EAI_ADDRFAMILY
;
526 goto free_and_return
;
529 if (req
->ai_flags
& AI_CANONNAME
)
532 else if (at
->family
== AF_UNSPEC
)
534 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
536 if (scope_delim
== NULL
)
537 e
= inet_pton (AF_INET6
, name
, at
->addr
);
539 e
= __inet_pton_length (AF_INET6
, name
, scope_delim
- name
,
543 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
544 at
->family
= AF_INET6
;
545 else if (req
->ai_family
== AF_INET
546 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
548 at
->addr
[0] = at
->addr
[3];
549 at
->family
= AF_INET
;
553 result
= -EAI_ADDRFAMILY
;
554 goto free_and_return
;
557 if (scope_delim
!= NULL
558 && __inet6_scopeid_pton ((struct in6_addr
*) at
->addr
,
562 result
= -EAI_NONAME
;
563 goto free_and_return
;
566 if (req
->ai_flags
& AI_CANONNAME
)
571 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
573 struct gaih_addrtuple
**pat
= &at
;
575 int no_inet6_data
= 0;
577 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
578 enum nss_status status
= NSS_STATUS_UNAVAIL
;
580 struct resolv_context
*res_ctx
= NULL
;
581 bool res_enable_inet6
= false;
583 /* If we do not have to look for IPv6 addresses or the canonical
584 name, use the simple, old functions, which do not support
585 IPv6 scope ids, nor retrieving the canonical name. */
586 if (req
->ai_family
== AF_INET
587 && (req
->ai_flags
& AI_CANONNAME
) == 0)
595 rc
= __gethostbyname2_r (name
, AF_INET
, &th
,
596 tmpbuf
->data
, tmpbuf
->length
,
598 if (rc
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
600 if (!scratch_buffer_grow (tmpbuf
))
602 result
= -EAI_MEMORY
;
603 goto free_and_return
;
611 /* We found data, convert it. */
612 if (!convert_hostent_to_gaih_addrtuple
613 (req
, AF_INET
, h
, &addrmem
))
615 result
= -EAI_MEMORY
;
616 goto free_and_return
;
622 if (h_errno
== NO_DATA
)
623 result
= -EAI_NODATA
;
625 result
= -EAI_NONAME
;
626 goto free_and_return
;
631 if (h_errno
== NETDB_INTERNAL
)
632 result
= -EAI_SYSTEM
;
633 else if (h_errno
== TRY_AGAIN
)
636 /* We made requests but they turned out no data.
637 The name is known, though. */
638 result
= -EAI_NODATA
;
640 goto free_and_return
;
647 if (__nss_not_use_nscd_hosts
> 0
648 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
649 __nss_not_use_nscd_hosts
= 0;
651 if (!__nss_not_use_nscd_hosts
652 && !__nss_database_custom
[NSS_DBSIDX_hosts
])
654 /* Try to use nscd. */
655 struct nscd_ai_result
*air
= NULL
;
656 int err
= __nscd_getai (name
, &air
, &h_errno
);
659 /* Transform into gaih_addrtuple list. */
660 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
661 char *addrs
= air
->addrs
;
663 addrmem
= calloc (air
->naddrs
, sizeof (*addrmem
));
666 result
= -EAI_MEMORY
;
667 goto free_and_return
;
670 struct gaih_addrtuple
*addrfree
= addrmem
;
671 for (int i
= 0; i
< air
->naddrs
; ++i
)
673 socklen_t size
= (air
->family
[i
] == AF_INET
674 ? INADDRSZ
: IN6ADDRSZ
);
676 if (!((air
->family
[i
] == AF_INET
677 && req
->ai_family
== AF_INET6
678 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
679 || req
->ai_family
== AF_UNSPEC
680 || air
->family
[i
] == req
->ai_family
))
682 /* Skip over non-matching result. */
692 uint32_t *pataddr
= (*pat
)->addr
;
694 if (added_canon
|| air
->canon
== NULL
)
696 else if (canonbuf
== NULL
)
698 canonbuf
= __strdup (air
->canon
);
699 if (canonbuf
== NULL
)
701 result
= -EAI_MEMORY
;
702 goto free_and_return
;
704 canon
= (*pat
)->name
= canonbuf
;
707 if (air
->family
[i
] == AF_INET
708 && req
->ai_family
== AF_INET6
709 && (req
->ai_flags
& AI_V4MAPPED
))
711 (*pat
)->family
= AF_INET6
;
712 pataddr
[3] = *(uint32_t *) addrs
;
713 pataddr
[2] = htonl (0xffff);
716 pat
= &((*pat
)->next
);
719 else if (req
->ai_family
== AF_UNSPEC
720 || air
->family
[i
] == req
->ai_family
)
722 (*pat
)->family
= air
->family
[i
];
723 memcpy (pataddr
, addrs
, size
);
724 pat
= &((*pat
)->next
);
726 if (air
->family
[i
] == AF_INET6
)
734 if (at
->family
== AF_UNSPEC
)
736 result
= -EAI_NONAME
;
737 goto free_and_return
;
743 /* The database contains a negative entry. */
744 goto free_and_return
;
745 else if (__nss_not_use_nscd_hosts
== 0)
747 if (h_errno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
748 result
= -EAI_MEMORY
;
749 else if (h_errno
== TRY_AGAIN
)
752 result
= -EAI_SYSTEM
;
754 goto free_and_return
;
759 if (__nss_hosts_database
== NULL
)
760 no_more
= __nss_database_lookup ("hosts", NULL
,
761 "dns [!UNAVAIL=return] files",
762 &__nss_hosts_database
);
765 nip
= __nss_hosts_database
;
767 /* If we are looking for both IPv4 and IPv6 address we don't
768 want the lookup functions to automatically promote IPv4
769 addresses to IPv6 addresses, so we use the no_inet6
771 res_ctx
= __resolv_context_get ();
772 res_enable_inet6
= __resolv_context_disable_inet6 (res_ctx
);
779 nss_gethostbyname4_r fct4
= NULL
;
781 /* gethostbyname4_r sends out parallel A and AAAA queries and
782 is thus only suitable for PF_UNSPEC. */
783 if (req
->ai_family
== PF_UNSPEC
)
784 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
790 status
= DL_CALL_FCT (fct4
, (name
, pat
,
791 tmpbuf
->data
, tmpbuf
->length
,
794 if (status
== NSS_STATUS_SUCCESS
)
796 if (status
!= NSS_STATUS_TRYAGAIN
797 || errno
!= ERANGE
|| h_errno
!= NETDB_INTERNAL
)
799 if (h_errno
== TRY_AGAIN
)
802 no_data
= h_errno
== NO_DATA
;
806 if (!scratch_buffer_grow (tmpbuf
))
808 __resolv_context_enable_inet6
809 (res_ctx
, res_enable_inet6
);
810 __resolv_context_put (res_ctx
);
811 result
= -EAI_MEMORY
;
812 goto free_and_return
;
816 if (status
== NSS_STATUS_SUCCESS
)
821 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
822 canon
= (*pat
)->name
;
826 if ((*pat
)->family
== AF_INET
827 && req
->ai_family
== AF_INET6
828 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
830 uint32_t *pataddr
= (*pat
)->addr
;
831 (*pat
)->family
= AF_INET6
;
832 pataddr
[3] = pataddr
[0];
833 pataddr
[2] = htonl (0xffff);
836 pat
= &((*pat
)->next
);
839 else if (req
->ai_family
== AF_UNSPEC
840 || (*pat
)->family
== req
->ai_family
)
842 pat
= &((*pat
)->next
);
845 if (req
->ai_family
== AF_INET6
)
849 *pat
= ((*pat
)->next
);
853 no_inet6_data
= no_data
;
857 nss_gethostbyname3_r fct
= NULL
;
858 if (req
->ai_flags
& AI_CANONNAME
)
859 /* No need to use this function if we do not look for
860 the canonical name. The function does not exist in
861 all NSS modules and therefore the lookup would
863 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
865 /* We are cheating here. The gethostbyname2_r
866 function does not have the same interface as
867 gethostbyname3_r but the extra arguments the
868 latter takes are added at the end. So the
869 gethostbyname2_r code will just ignore them. */
870 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
874 if (req
->ai_family
== AF_INET6
875 || req
->ai_family
== AF_UNSPEC
)
877 gethosts (AF_INET6
, struct in6_addr
);
878 no_inet6_data
= no_data
;
879 inet6_status
= status
;
881 if (req
->ai_family
== AF_INET
882 || req
->ai_family
== AF_UNSPEC
883 || (req
->ai_family
== AF_INET6
884 && (req
->ai_flags
& AI_V4MAPPED
)
885 /* Avoid generating the mapped addresses if we
886 know we are not going to need them. */
887 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
889 gethosts (AF_INET
, struct in_addr
);
891 if (req
->ai_family
== AF_INET
)
893 no_inet6_data
= no_data
;
894 inet6_status
= status
;
898 /* If we found one address for AF_INET or AF_INET6,
899 don't continue the search. */
900 if (inet6_status
== NSS_STATUS_SUCCESS
901 || status
== NSS_STATUS_SUCCESS
)
903 if ((req
->ai_flags
& AI_CANONNAME
) != 0
906 canonbuf
= getcanonname (nip
, at
, name
);
907 if (canonbuf
== NULL
)
909 __resolv_context_enable_inet6
910 (res_ctx
, res_enable_inet6
);
911 __resolv_context_put (res_ctx
);
912 result
= -EAI_MEMORY
;
913 goto free_and_return
;
917 status
= NSS_STATUS_SUCCESS
;
921 /* We can have different states for AF_INET and
922 AF_INET6. Try to find a useful one for both. */
923 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
924 status
= NSS_STATUS_TRYAGAIN
;
925 else if (status
== NSS_STATUS_UNAVAIL
926 && inet6_status
!= NSS_STATUS_UNAVAIL
)
927 status
= inet6_status
;
932 /* Could not locate any of the lookup functions.
933 The NSS lookup code does not consistently set
934 errno, so we need to supply our own error
935 code here. The root cause could either be a
936 resource allocation failure, or a missing
937 service function in the DSO (so it should not
938 be listed in /etc/nsswitch.conf). Assume the
939 former, and return EBUSY. */
940 status
= NSS_STATUS_UNAVAIL
;
941 __set_h_errno (NETDB_INTERNAL
);
946 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
949 if (nip
->next
== NULL
)
955 __resolv_context_enable_inet6 (res_ctx
, res_enable_inet6
);
956 __resolv_context_put (res_ctx
);
958 /* If we have a failure which sets errno, report it using
960 if ((status
== NSS_STATUS_TRYAGAIN
|| status
== NSS_STATUS_UNAVAIL
)
961 && h_errno
== NETDB_INTERNAL
)
963 result
= -EAI_SYSTEM
;
964 goto free_and_return
;
967 if (no_data
!= 0 && no_inet6_data
!= 0)
969 /* If both requests timed out report this. */
970 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
973 /* We made requests but they turned out no data. The name
975 result
= -EAI_NODATA
;
977 goto free_and_return
;
982 if (at
->family
== AF_UNSPEC
)
984 result
= -EAI_NONAME
;
985 goto free_and_return
;
990 struct gaih_addrtuple
*atr
;
991 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
992 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
994 if (req
->ai_family
== AF_UNSPEC
)
996 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
997 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1000 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1002 at
->family
= AF_INET6
;
1003 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1004 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1008 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1010 atr
->family
= AF_INET
;
1011 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1012 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1017 struct gaih_servtuple
*st2
;
1018 struct gaih_addrtuple
*at2
= at
;
1023 buffer is the size of an unformatted IPv6 address in printable format.
1027 /* Only the first entry gets the canonical name. */
1028 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1031 /* If the canonical name cannot be determined, use
1032 the passed in string. */
1036 if (req
->ai_flags
& AI_CANONIDN
)
1039 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1040 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1041 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1042 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1045 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1046 if (rc
!= IDNA_SUCCESS
)
1048 if (rc
== IDNA_MALLOC_ERROR
)
1049 result
= -EAI_MEMORY
;
1050 else if (rc
== IDNA_DLOPEN_ERROR
)
1051 result
= -EAI_SYSTEM
;
1053 result
= -EAI_IDN_ENCODE
;
1054 goto free_and_return
;
1056 /* In case the output string is the same as the input
1057 string no new string has been allocated and we
1069 if (canonbuf
!= NULL
)
1070 /* We already allocated the string using malloc, but
1071 the buffer is now owned by canon. */
1075 canon
= __strdup (canon
);
1078 result
= -EAI_MEMORY
;
1079 goto free_and_return
;
1085 family
= at2
->family
;
1086 if (family
== AF_INET6
)
1088 socklen
= sizeof (struct sockaddr_in6
);
1090 /* If we looked up IPv4 mapped address discard them here if
1091 the caller isn't interested in all address and we have
1092 found at least one IPv6 address. */
1094 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1095 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1099 socklen
= sizeof (struct sockaddr_in
);
1101 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1103 struct addrinfo
*ai
;
1104 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1107 free ((char *) canon
);
1108 result
= -EAI_MEMORY
;
1109 goto free_and_return
;
1112 ai
->ai_flags
= req
->ai_flags
;
1113 ai
->ai_family
= family
;
1114 ai
->ai_socktype
= st2
->socktype
;
1115 ai
->ai_protocol
= st2
->protocol
;
1116 ai
->ai_addrlen
= socklen
;
1117 ai
->ai_addr
= (void *) (ai
+ 1);
1119 /* We only add the canonical name once. */
1120 ai
->ai_canonname
= (char *) canon
;
1124 ai
->ai_addr
->sa_len
= socklen
;
1125 #endif /* _HAVE_SA_LEN */
1126 ai
->ai_addr
->sa_family
= family
;
1128 /* In case of an allocation error the list must be NULL
1132 if (family
== AF_INET6
)
1134 struct sockaddr_in6
*sin6p
=
1135 (struct sockaddr_in6
*) ai
->ai_addr
;
1137 sin6p
->sin6_port
= st2
->port
;
1138 sin6p
->sin6_flowinfo
= 0;
1139 memcpy (&sin6p
->sin6_addr
,
1140 at2
->addr
, sizeof (struct in6_addr
));
1141 sin6p
->sin6_scope_id
= at2
->scopeid
;
1145 struct sockaddr_in
*sinp
=
1146 (struct sockaddr_in
*) ai
->ai_addr
;
1147 sinp
->sin_port
= st2
->port
;
1148 memcpy (&sinp
->sin_addr
,
1149 at2
->addr
, sizeof (struct in_addr
));
1150 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1153 pai
= &(ai
->ai_next
);
1165 free ((char *) name
);
1175 struct addrinfo
*dest_addr
;
1176 /* Using sockaddr_storage is for now overkill. We only support IPv4
1177 and IPv6 so far. If this changes at some point we can adjust the
1179 struct sockaddr_in6 source_addr
;
1180 uint8_t source_addr_len
;
1181 bool got_source_addr
;
1182 uint8_t source_addr_flags
;
1188 struct sort_result_combo
1190 struct sort_result
*results
;
1195 #if __BYTE_ORDER == __BIG_ENDIAN
1196 # define htonl_c(n) n
1198 # define htonl_c(n) __bswap_constant_32 (n)
1201 static const struct scopeentry
1210 } default_scopes
[] =
1212 /* Link-local addresses: scope 2. */
1213 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1214 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1215 /* Default: scope 14. */
1216 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1219 /* The label table. */
1220 static const struct scopeentry
*scopes
;
1224 get_scope (const struct sockaddr_in6
*in6
)
1227 if (in6
->sin6_family
== PF_INET6
)
1229 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1231 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1232 /* RFC 4291 2.5.3 says that the loopback address is to be
1233 treated like a link-local address. */
1234 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1236 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1239 /* XXX Is this the correct default behavior? */
1243 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1245 else if (in6
->sin6_family
== PF_INET
)
1247 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1252 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1253 == scopes
[cnt
].addr32
)
1254 return scopes
[cnt
].scope
;
1261 /* XXX What is a good default? */
1270 struct in6_addr prefix
;
1276 /* The label table. */
1277 static const struct prefixentry
*labels
;
1279 /* Default labels. */
1280 static const struct prefixentry default_labels
[] =
1282 /* See RFC 3484 for the details. */
1284 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1288 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1292 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1296 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1297 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1299 /* The next two entries differ from RFC 3484. We need to treat
1300 IPv6 site-local addresses special because they are never NATed,
1301 unlike site-locale IPv4 addresses. If this would not happen, on
1302 machines which have only IPv4 and IPv6 site-local addresses, the
1303 sorting would prefer the IPv6 site-local addresses, causing
1304 unnecessary delays when trying to connect to a global IPv6 address
1305 through a site-local IPv6 address. */
1307 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1311 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1314 /* Additional rule for Teredo tunnels. */
1316 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1320 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1326 /* The precedence table. */
1327 static const struct prefixentry
*precedence
;
1329 /* The default precedences. */
1330 static const struct prefixentry default_precedence
[] =
1332 /* See RFC 3484 for the details. */
1334 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1338 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1342 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1343 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1346 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1347 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1350 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1351 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1357 match_prefix (const struct sockaddr_in6
*in6
,
1358 const struct prefixentry
*list
, int default_val
)
1361 struct sockaddr_in6 in6_mem
;
1363 if (in6
->sin6_family
== PF_INET
)
1365 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1367 /* Construct a V4-to-6 mapped address. */
1368 in6_mem
.sin6_family
= PF_INET6
;
1369 in6_mem
.sin6_port
= in
->sin_port
;
1370 in6_mem
.sin6_flowinfo
= 0;
1371 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1372 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1373 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1374 in6_mem
.sin6_scope_id
= 0;
1378 else if (in6
->sin6_family
!= PF_INET6
)
1381 for (idx
= 0; ; ++idx
)
1383 unsigned int bits
= list
[idx
].bits
;
1384 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1385 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1399 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1405 return list
[idx
].val
;
1410 get_label (const struct sockaddr_in6
*in6
)
1412 /* XXX What is a good default value? */
1413 return match_prefix (in6
, labels
, INT_MAX
);
1418 get_precedence (const struct sockaddr_in6
*in6
)
1420 /* XXX What is a good default value? */
1421 return match_prefix (in6
, precedence
, 0);
1425 /* Find last bit set in a word. */
1431 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1432 if ((a
& mask
) != 0)
1439 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1441 const size_t idx1
= *(const size_t *) p1
;
1442 const size_t idx2
= *(const size_t *) p2
;
1443 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1444 struct sort_result
*a1
= &src
->results
[idx1
];
1445 struct sort_result
*a2
= &src
->results
[idx2
];
1447 /* Rule 1: Avoid unusable destinations.
1448 We have the got_source_addr flag set if the destination is reachable. */
1449 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1451 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1455 /* Rule 2: Prefer matching scope. Only interesting if both
1456 destination addresses are IPv6. */
1458 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1461 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1463 if (a1
->got_source_addr
)
1465 int a1_src_scope
= get_scope (&a1
->source_addr
);
1466 int a2_src_scope
= get_scope (&a2
->source_addr
);
1468 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1470 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1475 /* Rule 3: Avoid deprecated addresses. */
1476 if (a1
->got_source_addr
)
1478 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1479 && (a2
->source_addr_flags
& in6ai_deprecated
))
1481 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1482 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1486 /* Rule 4: Prefer home addresses. */
1487 if (a1
->got_source_addr
)
1489 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1490 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1492 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1493 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1497 /* Rule 5: Prefer matching label. */
1498 if (a1
->got_source_addr
)
1501 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1502 int a1_src_label
= get_label (&a1
->source_addr
);
1505 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1506 int a2_src_label
= get_label (&a2
->source_addr
);
1508 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1510 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1515 /* Rule 6: Prefer higher precedence. */
1517 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1519 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1521 if (a1_prec
> a2_prec
)
1523 if (a1_prec
< a2_prec
)
1527 /* Rule 7: Prefer native transport. */
1528 if (a1
->got_source_addr
)
1530 /* The same interface index means the same interface which means
1531 there is no difference in transport. This should catch many
1533 if (a1
->index
!= a2
->index
)
1535 int a1_native
= a1
->native
;
1536 int a2_native
= a2
->native
;
1538 if (a1_native
== -1 || a2_native
== -1)
1541 if (a1_native
== -1)
1543 /* If we do not have the information use 'native' as
1546 a1_index
= a1
->index
;
1549 a1_index
= 0xffffffffu
;
1552 if (a2_native
== -1)
1554 /* If we do not have the information use 'native' as
1557 a2_index
= a2
->index
;
1560 a2_index
= 0xffffffffu
;
1562 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1564 /* Fill in the results in all the records. */
1565 for (int i
= 0; i
< src
->nresults
; ++i
)
1566 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1568 assert (src
->results
[i
].native
== -1
1569 || src
->results
[i
].native
== a1_native
);
1570 src
->results
[i
].native
= a1_native
;
1572 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1574 assert (src
->results
[i
].native
== -1
1575 || src
->results
[i
].native
== a2_native
);
1576 src
->results
[i
].native
= a2_native
;
1580 if (a1_native
&& !a2_native
)
1582 if (!a1_native
&& a2_native
)
1588 /* Rule 8: Prefer smaller scope. */
1589 if (a1_dst_scope
< a2_dst_scope
)
1591 if (a1_dst_scope
> a2_dst_scope
)
1595 /* Rule 9: Use longest matching prefix. */
1596 if (a1
->got_source_addr
1597 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1602 if (a1
->dest_addr
->ai_family
== PF_INET
)
1604 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1605 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1607 /* Outside of subnets, as defined by the network masks,
1608 common address prefixes for IPv4 addresses make no sense.
1609 So, define a non-zero value only if source and
1610 destination address are on the same subnet. */
1611 struct sockaddr_in
*in1_dst
1612 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1613 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1614 struct sockaddr_in
*in1_src
1615 = (struct sockaddr_in
*) &a1
->source_addr
;
1616 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1617 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1619 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1620 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1622 struct sockaddr_in
*in2_dst
1623 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1624 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1625 struct sockaddr_in
*in2_src
1626 = (struct sockaddr_in
*) &a2
->source_addr
;
1627 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1628 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1630 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1631 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1633 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1635 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1636 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1638 struct sockaddr_in6
*in1_dst
;
1639 struct sockaddr_in6
*in1_src
;
1640 struct sockaddr_in6
*in2_dst
;
1641 struct sockaddr_in6
*in2_src
;
1643 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1644 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1645 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1646 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1649 for (i
= 0; i
< 4; ++i
)
1650 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1651 != in1_src
->sin6_addr
.s6_addr32
[i
]
1652 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1653 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1658 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1659 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1660 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1661 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1672 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1673 compare with the value indicating the order in which the entries
1674 have been received from the services. NB: no two entries can have
1675 the same order so the test will never return zero. */
1676 return idx1
< idx2
? -1 : 1;
1681 in6aicmp (const void *p1
, const void *p2
)
1683 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1684 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1686 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1690 /* Name of the config file for RFC 3484 sorting (for now). */
1691 #define GAICONF_FNAME "/etc/gai.conf"
1694 /* Non-zero if we are supposed to reload the config file automatically
1695 whenever it changed. */
1696 static int gaiconf_reload_flag
;
1698 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1699 static int gaiconf_reload_flag_ever_set
;
1701 /* Last modification time. */
1702 #ifdef _STATBUF_ST_NSEC
1704 static struct timespec gaiconf_mtime
;
1707 save_gaiconf_mtime (const struct stat64
*st
)
1709 gaiconf_mtime
= st
->st_mtim
;
1713 check_gaiconf_mtime (const struct stat64
*st
)
1715 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1716 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1721 static time_t gaiconf_mtime
;
1724 save_gaiconf_mtime (const struct stat64
*st
)
1726 gaiconf_mtime
= st
->st_mtime
;
1730 check_gaiconf_mtime (const struct stat64
*st
)
1732 return st
->st_mtime
== gaiconf_mtime
;
1738 libc_freeres_fn(fini
)
1740 if (labels
!= default_labels
)
1742 const struct prefixentry
*old
= labels
;
1743 labels
= default_labels
;
1744 free ((void *) old
);
1747 if (precedence
!= default_precedence
)
1749 const struct prefixentry
*old
= precedence
;
1750 precedence
= default_precedence
;
1751 free ((void *) old
);
1754 if (scopes
!= default_scopes
)
1756 const struct scopeentry
*old
= scopes
;
1757 scopes
= default_scopes
;
1758 free ((void *) old
);
1765 struct prefixentry entry
;
1766 struct prefixlist
*next
;
1772 struct scopeentry entry
;
1773 struct scopelist
*next
;
1778 free_prefixlist (struct prefixlist
*list
)
1780 while (list
!= NULL
)
1782 struct prefixlist
*oldp
= list
;
1790 free_scopelist (struct scopelist
*list
)
1792 while (list
!= NULL
)
1794 struct scopelist
*oldp
= list
;
1802 prefixcmp (const void *p1
, const void *p2
)
1804 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1805 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1807 if (e1
->bits
< e2
->bits
)
1809 if (e1
->bits
== e2
->bits
)
1816 scopecmp (const void *p1
, const void *p2
)
1818 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1819 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1821 if (e1
->netmask
> e2
->netmask
)
1823 if (e1
->netmask
== e2
->netmask
)
1832 struct prefixlist
*labellist
= NULL
;
1833 size_t nlabellist
= 0;
1834 bool labellist_nullbits
= false;
1835 struct prefixlist
*precedencelist
= NULL
;
1836 size_t nprecedencelist
= 0;
1837 bool precedencelist_nullbits
= false;
1838 struct scopelist
*scopelist
= NULL
;
1839 size_t nscopelist
= 0;
1840 bool scopelist_nullbits
= false;
1842 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1846 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1855 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1857 while (!feof_unlocked (fp
))
1859 ssize_t n
= __getline (&line
, &linelen
, fp
);
1863 /* Handle comments. No escaping possible so this is easy. */
1864 char *cp
= strchr (line
, '#');
1869 while (isspace (*cp
))
1873 while (*cp
!= '\0' && !isspace (*cp
))
1875 size_t cmdlen
= cp
- cmd
;
1879 while (isspace (*cp
))
1883 while (*cp
!= '\0' && !isspace (*cp
))
1885 size_t val1len
= cp
- cmd
;
1887 /* We always need at least two values. */
1893 while (isspace (*cp
))
1897 while (*cp
!= '\0' && !isspace (*cp
))
1900 /* Ignore the rest of the line. */
1903 struct prefixlist
**listp
;
1909 if (strcmp (cmd
, "label") == 0)
1911 struct in6_addr prefix
;
1912 unsigned long int bits
;
1913 unsigned long int val
;
1918 nullbitsp
= &labellist_nullbits
;
1923 cp
= strchr (val1
, '/');
1926 if (inet_pton (AF_INET6
, val1
, &prefix
)
1928 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1932 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1937 struct prefixlist
*newp
= malloc (sizeof (*newp
));
1945 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
1946 newp
->entry
.bits
= bits
;
1947 newp
->entry
.val
= val
;
1948 newp
->next
= *listp
;
1951 *nullbitsp
|= bits
== 0;
1957 if (strcmp (cmd
, "reload") == 0)
1959 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
1960 if (gaiconf_reload_flag
)
1961 gaiconf_reload_flag_ever_set
= 1;
1966 if (strcmp (cmd
, "scopev4") == 0)
1968 struct in6_addr prefix
;
1969 unsigned long int bits
;
1970 unsigned long int val
;
1975 cp
= strchr (val1
, '/');
1978 if (inet_pton (AF_INET6
, val1
, &prefix
))
1981 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
1983 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
1988 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
1993 struct scopelist
*newp
;
1995 newp
= malloc (sizeof (*newp
));
2003 newp
->entry
.netmask
= htonl (bits
!= 96
2007 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2008 & newp
->entry
.netmask
);
2009 newp
->entry
.scope
= val
;
2010 newp
->next
= scopelist
;
2013 scopelist_nullbits
|= bits
== 96;
2016 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2018 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2022 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2034 if (strcmp (cmd
, "precedence") == 0)
2036 listp
= &precedencelist
;
2037 lenp
= &nprecedencelist
;
2038 nullbitsp
= &precedencelist_nullbits
;
2049 /* Create the array for the labels. */
2050 struct prefixentry
*new_labels
;
2053 if (!labellist_nullbits
)
2055 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2056 if (new_labels
== NULL
)
2060 if (!labellist_nullbits
)
2063 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2064 new_labels
[i
].bits
= 0;
2065 new_labels
[i
].val
= 1;
2068 struct prefixlist
*l
= labellist
;
2071 new_labels
[i
] = l
->entry
;
2074 free_prefixlist (labellist
);
2076 /* Sort the entries so that the most specific ones are at
2078 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2081 new_labels
= (struct prefixentry
*) default_labels
;
2083 struct prefixentry
*new_precedence
;
2084 if (nprecedencelist
> 0)
2086 if (!precedencelist_nullbits
)
2088 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2089 if (new_precedence
== NULL
)
2091 if (new_labels
!= default_labels
)
2096 int i
= nprecedencelist
;
2097 if (!precedencelist_nullbits
)
2100 memset (&new_precedence
[i
].prefix
, '\0',
2101 sizeof (struct in6_addr
));
2102 new_precedence
[i
].bits
= 0;
2103 new_precedence
[i
].val
= 40;
2106 struct prefixlist
*l
= precedencelist
;
2109 new_precedence
[i
] = l
->entry
;
2112 free_prefixlist (precedencelist
);
2114 /* Sort the entries so that the most specific ones are at
2116 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2120 new_precedence
= (struct prefixentry
*) default_precedence
;
2122 struct scopeentry
*new_scopes
;
2125 if (!scopelist_nullbits
)
2127 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2128 if (new_scopes
== NULL
)
2130 if (new_labels
!= default_labels
)
2132 if (new_precedence
!= default_precedence
)
2133 free (new_precedence
);
2138 if (!scopelist_nullbits
)
2141 new_scopes
[i
].addr32
= 0;
2142 new_scopes
[i
].netmask
= 0;
2143 new_scopes
[i
].scope
= 14;
2146 struct scopelist
*l
= scopelist
;
2149 new_scopes
[i
] = l
->entry
;
2152 free_scopelist (scopelist
);
2154 /* Sort the entries so that the most specific ones are at
2156 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2160 new_scopes
= (struct scopeentry
*) default_scopes
;
2162 /* Now we are ready to replace the values. */
2163 const struct prefixentry
*old
= labels
;
2164 labels
= new_labels
;
2165 if (old
!= default_labels
)
2166 free ((void *) old
);
2169 precedence
= new_precedence
;
2170 if (old
!= default_precedence
)
2171 free ((void *) old
);
2173 const struct scopeentry
*oldscope
= scopes
;
2174 scopes
= new_scopes
;
2175 if (oldscope
!= default_scopes
)
2176 free ((void *) oldscope
);
2178 save_gaiconf_mtime (&st
);
2183 free_prefixlist (labellist
);
2184 free_prefixlist (precedencelist
);
2185 free_scopelist (scopelist
);
2187 /* If we previously read the file but it is gone now, free the
2188 old data and use the builtin one. Leave the reload flag
2196 gaiconf_reload (void)
2199 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2200 || !check_gaiconf_mtime (&st
))
2206 getaddrinfo (const char *name
, const char *service
,
2207 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2209 int i
= 0, last_i
= 0;
2211 struct addrinfo
*p
= NULL
;
2212 struct gaih_service gaih_service
, *pservice
;
2213 struct addrinfo local_hints
;
2215 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2218 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2221 if (name
== NULL
&& service
== NULL
)
2225 hints
= &default_hints
;
2228 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2230 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2231 |AI_IDN_USE_STD3_ASCII_RULES
2233 |AI_NUMERICSERV
|AI_ALL
))
2234 return EAI_BADFLAGS
;
2236 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2237 return EAI_BADFLAGS
;
2239 struct in6addrinfo
*in6ai
= NULL
;
2240 size_t in6ailen
= 0;
2241 bool seen_ipv4
= false;
2242 bool seen_ipv6
= false;
2243 bool check_pf_called
= false;
2245 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2247 /* We might need information about what interfaces are available.
2248 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2249 cannot cache the results since new interfaces could be added at
2251 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2252 check_pf_called
= true;
2254 /* Now make a decision on what we return, if anything. */
2255 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2257 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2258 narrow down the search. */
2259 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2261 local_hints
= *hints
;
2262 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2263 hints
= &local_hints
;
2266 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2267 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2269 /* We cannot possibly return a valid answer. */
2270 __free_in6ai (in6ai
);
2275 if (service
&& service
[0])
2278 gaih_service
.name
= service
;
2279 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2282 if (hints
->ai_flags
& AI_NUMERICSERV
)
2284 __free_in6ai (in6ai
);
2288 gaih_service
.num
= -1;
2291 pservice
= &gaih_service
;
2296 struct addrinfo
**end
= &p
;
2298 unsigned int naddrs
= 0;
2299 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2300 || hints
->ai_family
== AF_INET6
)
2302 struct scratch_buffer tmpbuf
;
2303 scratch_buffer_init (&tmpbuf
);
2304 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
, &tmpbuf
);
2305 scratch_buffer_free (&tmpbuf
);
2310 __free_in6ai (in6ai
);
2316 end
= &((*end
)->ai_next
);
2322 __free_in6ai (in6ai
);
2328 /* Read the config file. */
2329 __libc_once_define (static, once
);
2330 __typeof (once
) old_once
= once
;
2331 __libc_once (once
, gaiconf_init
);
2332 /* Sort results according to RFC 3484. */
2333 struct sort_result
*results
;
2336 struct addrinfo
*last
= NULL
;
2337 char *canonname
= NULL
;
2338 bool malloc_results
;
2339 size_t alloc_size
= nresults
* (sizeof (*results
) + sizeof (size_t));
2342 = !__libc_use_alloca (alloc_size
);
2345 results
= malloc (alloc_size
);
2346 if (results
== NULL
)
2348 __free_in6ai (in6ai
);
2353 results
= alloca (alloc_size
);
2354 order
= (size_t *) (results
+ nresults
);
2356 /* Now we definitely need the interface information. */
2357 if (! check_pf_called
)
2358 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2360 /* If we have information about deprecated and temporary addresses
2361 sort the array now. */
2363 qsort (in6ai
, in6ailen
, sizeof (*in6ai
), in6aicmp
);
2368 for (i
= 0, q
= p
; q
!= NULL
; ++i
, last
= q
, q
= q
->ai_next
)
2370 results
[i
].dest_addr
= q
;
2371 results
[i
].native
= -1;
2374 /* If we just looked up the address for a different
2375 protocol, reuse the result. */
2376 if (last
!= NULL
&& last
->ai_addrlen
== q
->ai_addrlen
2377 && memcmp (last
->ai_addr
, q
->ai_addr
, q
->ai_addrlen
) == 0)
2379 memcpy (&results
[i
].source_addr
, &results
[i
- 1].source_addr
,
2380 results
[i
- 1].source_addr_len
);
2381 results
[i
].source_addr_len
= results
[i
- 1].source_addr_len
;
2382 results
[i
].got_source_addr
= results
[i
- 1].got_source_addr
;
2383 results
[i
].source_addr_flags
= results
[i
- 1].source_addr_flags
;
2384 results
[i
].prefixlen
= results
[i
- 1].prefixlen
;
2385 results
[i
].index
= results
[i
- 1].index
;
2389 results
[i
].got_source_addr
= false;
2390 results
[i
].source_addr_flags
= 0;
2391 results
[i
].prefixlen
= 0;
2392 results
[i
].index
= 0xffffffffu
;
2394 /* We overwrite the type with SOCK_DGRAM since we do not
2395 want connect() to connect to the other side. If we
2396 cannot determine the source address remember this
2398 if (fd
== -1 || (af
== AF_INET
&& q
->ai_family
== AF_INET6
))
2402 __close_nocancel_nostatus (fd
);
2404 fd
= __socket (af
, SOCK_DGRAM
| SOCK_CLOEXEC
, IPPROTO_IP
);
2408 /* Reset the connection. */
2409 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2410 __connect (fd
, &sa
, sizeof (sa
));
2413 socklen_t sl
= sizeof (results
[i
].source_addr
);
2415 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2416 && __getsockname (fd
,
2417 (struct sockaddr
*) &results
[i
].source_addr
,
2420 results
[i
].source_addr_len
= sl
;
2421 results
[i
].got_source_addr
= true;
2425 /* See whether the source address is on the list of
2426 deprecated or temporary addresses. */
2427 struct in6addrinfo tmp
;
2429 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2431 struct sockaddr_in
*sinp
2432 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2435 tmp
.addr
[2] = htonl (0xffff);
2436 /* Special case for lo interface, the source address
2437 being possibly different than the interface
2439 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2441 tmp
.addr
[3] = htonl(0x7f000001);
2443 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2447 struct sockaddr_in6
*sin6p
2448 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2449 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2452 struct in6addrinfo
*found
2453 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2457 results
[i
].source_addr_flags
= found
->flags
;
2458 results
[i
].prefixlen
= found
->prefixlen
;
2459 results
[i
].index
= found
->index
;
2463 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2465 /* We have to convert the address. The socket is
2466 IPv6 and the request is for IPv4. */
2467 struct sockaddr_in6
*sin6
2468 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2469 struct sockaddr_in
*sin
2470 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2471 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2472 sin
->sin_family
= AF_INET
;
2473 /* We do not have to initialize sin_port since this
2474 fields has the same position and size in the IPv6
2476 assert (offsetof (struct sockaddr_in
, sin_port
)
2477 == offsetof (struct sockaddr_in6
, sin6_port
));
2478 assert (sizeof (sin
->sin_port
)
2479 == sizeof (sin6
->sin6_port
));
2480 memcpy (&sin
->sin_addr
,
2481 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2482 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2485 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2486 && q
->ai_family
== AF_INET
)
2487 /* This could mean IPv6 sockets are IPv6-only. */
2490 /* Just make sure that if we have to process the same
2491 address again we do not copy any memory. */
2492 results
[i
].source_addr_len
= 0;
2495 /* Remember the canonical name. */
2496 if (q
->ai_canonname
!= NULL
)
2498 assert (canonname
== NULL
);
2499 canonname
= q
->ai_canonname
;
2500 q
->ai_canonname
= NULL
;
2505 __close_nocancel_nostatus (fd
);
2507 /* We got all the source addresses we can get, now sort using
2509 struct sort_result_combo src
2510 = { .results
= results
, .nresults
= nresults
};
2511 if (__glibc_unlikely (gaiconf_reload_flag_ever_set
))
2513 __libc_lock_define_initialized (static, lock
);
2515 __libc_lock_lock (lock
);
2516 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2518 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2519 __libc_lock_unlock (lock
);
2522 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2524 /* Queue the results up as they come out of sorting. */
2525 q
= p
= results
[order
[0]].dest_addr
;
2526 for (i
= 1; i
< nresults
; ++i
)
2527 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2530 /* Fill in the canonical name into the new first entry. */
2531 p
->ai_canonname
= canonname
;
2537 __free_in6ai (in6ai
);
2545 return last_i
? -last_i
: EAI_NONAME
;
2547 libc_hidden_def (getaddrinfo
)
2549 nss_interface_function (getaddrinfo
)
2552 freeaddrinfo (struct addrinfo
*ai
)
2560 free (p
->ai_canonname
);
2564 libc_hidden_def (freeaddrinfo
)