1 /* Host and service name lookups using Name Service Switch modules.
2 Copyright (C) 1996-2017 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>
65 #include <stdio_ext.h>
69 #include <arpa/inet.h>
71 #include <netinet/in.h>
72 #include <sys/socket.h>
74 #include <sys/types.h>
76 #include <sys/utsname.h>
79 #include <libc-lock.h>
80 #include <not-cancel.h>
81 #include <nscd/nscd-client.h>
82 #include <nscd/nscd_proto.h>
83 #include <resolv/res_hconf.h>
84 #include <scratch_buffer.h>
85 #include <inet/net-internal.h>
88 extern int __idna_to_ascii_lz (const char *input
, char **output
, int flags
);
89 extern int __idna_to_unicode_lzlz (const char *input
, char **output
,
91 # include <libidn/idna.h>
100 struct gaih_servtuple
102 struct gaih_servtuple
*next
;
108 static const struct gaih_servtuple nullserv
;
111 struct gaih_typeproto
120 /* Values for `protoflag'. */
121 #define GAI_PROTO_NOSERVICE 1
122 #define GAI_PROTO_PROTOANY 2
124 static const struct gaih_typeproto gaih_inet_typeproto
[] =
126 { 0, 0, 0, false, "" },
127 { SOCK_STREAM
, IPPROTO_TCP
, 0, true, "tcp" },
128 { SOCK_DGRAM
, IPPROTO_UDP
, 0, true, "udp" },
129 #if defined SOCK_DCCP && defined IPPROTO_DCCP
130 { SOCK_DCCP
, IPPROTO_DCCP
, 0, false, "dccp" },
132 #ifdef IPPROTO_UDPLITE
133 { SOCK_DGRAM
, IPPROTO_UDPLITE
, 0, false, "udplite" },
136 { SOCK_STREAM
, IPPROTO_SCTP
, 0, false, "sctp" },
137 { SOCK_SEQPACKET
, IPPROTO_SCTP
, 0, false, "sctp" },
139 { SOCK_RAW
, 0, GAI_PROTO_PROTOANY
|GAI_PROTO_NOSERVICE
, true, "raw" },
140 { 0, 0, 0, false, "" }
143 static const struct addrinfo default_hints
=
145 .ai_flags
= AI_DEFAULT
,
146 .ai_family
= PF_UNSPEC
,
151 .ai_canonname
= NULL
,
157 gaih_inet_serv (const char *servicename
, const struct gaih_typeproto
*tp
,
158 const struct addrinfo
*req
, struct gaih_servtuple
*st
,
159 struct scratch_buffer
*tmpbuf
)
167 r
= __getservbyname_r (servicename
, tp
->name
, &ts
,
168 tmpbuf
->data
, tmpbuf
->length
, &s
);
169 if (r
!= 0 || s
== NULL
)
173 if (!scratch_buffer_grow (tmpbuf
))
183 st
->socktype
= tp
->socktype
;
184 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
185 ? req
->ai_protocol
: tp
->protocol
);
186 st
->port
= s
->s_port
;
191 /* Convert struct hostent to a list of struct gaih_addrtuple objects.
192 h_name is not copied, and the struct hostent object must not be
193 deallocated prematurely. *RESULT must be NULL or a pointer to an
194 object allocated using malloc, which is freed. */
196 convert_hostent_to_gaih_addrtuple (const struct addrinfo
*req
,
199 struct gaih_addrtuple
**result
)
204 /* Count the number of addresses in h->h_addr_list. */
206 for (char **p
= h
->h_addr_list
; *p
!= NULL
; ++p
)
209 /* Report no data if no addresses are available, or if the incoming
210 address size is larger than what we can store. */
211 if (count
== 0 || h
->h_length
> sizeof (((struct gaih_addrtuple
) {}).addr
))
214 struct gaih_addrtuple
*array
= calloc (count
, sizeof (*array
));
218 for (size_t i
= 0; i
< count
; ++i
)
220 if (family
== AF_INET
&& req
->ai_family
== AF_INET6
)
222 /* Perform address mapping. */
223 array
[i
].family
= AF_INET6
;
224 memcpy(array
[i
].addr
+ 3, h
->h_addr_list
[i
], sizeof (uint32_t));
225 array
[i
].addr
[2] = htonl (0xffff);
229 array
[i
].family
= family
;
230 memcpy (array
[i
].addr
, h
->h_addr_list
[i
], h
->h_length
);
232 array
[i
].next
= array
+ i
+ 1;
234 array
[0].name
= h
->h_name
;
235 array
[count
- 1].next
= NULL
;
241 #define gethosts(_family, _type) \
246 char *localcanon = NULL; \
250 status = DL_CALL_FCT (fct, (name, _family, &th, \
251 tmpbuf->data, tmpbuf->length, \
252 &rc, &herrno, NULL, &localcanon)); \
253 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
255 if (!scratch_buffer_grow (tmpbuf)) \
257 result = -EAI_MEMORY; \
258 goto free_and_return; \
261 if (status == NSS_STATUS_SUCCESS && rc == 0) \
267 if (herrno == NETDB_INTERNAL) \
269 __set_h_errno (herrno); \
270 _res.options |= old_res_options & DEPRECATED_RES_USE_INET6; \
271 result = -EAI_SYSTEM; \
272 goto free_and_return; \
274 if (herrno == TRY_AGAIN) \
275 no_data = EAI_AGAIN; \
277 no_data = herrno == NO_DATA; \
279 else if (h != NULL) \
281 /* Make sure that addrmem can be freed. */ \
282 if (!malloc_addrmem) \
284 if (!convert_hostent_to_gaih_addrtuple (req, _family,h, &addrmem)) \
286 _res.options |= old_res_options & DEPRECATED_RES_USE_INET6; \
287 result = -EAI_SYSTEM; \
288 goto free_and_return; \
291 /* The conversion uses malloc unconditionally. */ \
292 malloc_addrmem = true; \
294 if (localcanon != NULL && canon == NULL) \
295 canon = strdupa (localcanon); \
297 if (_family == AF_INET6 && *pat != NULL) \
303 typedef enum nss_status (*nss_gethostbyname4_r
)
304 (const char *name
, struct gaih_addrtuple
**pat
,
305 char *buffer
, size_t buflen
, int *errnop
,
306 int *h_errnop
, int32_t *ttlp
);
307 typedef enum nss_status (*nss_gethostbyname3_r
)
308 (const char *name
, int af
, struct hostent
*host
,
309 char *buffer
, size_t buflen
, int *errnop
,
310 int *h_errnop
, int32_t *ttlp
, char **canonp
);
311 typedef enum nss_status (*nss_getcanonname_r
)
312 (const char *name
, char *buffer
, size_t buflen
, char **result
,
313 int *errnop
, int *h_errnop
);
314 extern service_user
*__nss_hosts_database attribute_hidden
;
318 gaih_inet (const char *name
, const struct gaih_service
*service
,
319 const struct addrinfo
*req
, struct addrinfo
**pai
,
320 unsigned int *naddrs
, struct scratch_buffer
*tmpbuf
)
322 const struct gaih_typeproto
*tp
= gaih_inet_typeproto
;
323 struct gaih_servtuple
*st
= (struct gaih_servtuple
*) &nullserv
;
324 struct gaih_addrtuple
*at
= NULL
;
326 bool got_ipv6
= false;
327 const char *canon
= NULL
;
328 const char *orig_name
= name
;
330 /* Reserve stack memory for the scratch buffer in the getaddrinfo
332 size_t alloca_used
= sizeof (struct scratch_buffer
);
334 if (req
->ai_protocol
|| req
->ai_socktype
)
339 && ((req
->ai_socktype
!= 0 && req
->ai_socktype
!= tp
->socktype
)
340 || (req
->ai_protocol
!= 0
341 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
342 && req
->ai_protocol
!= tp
->protocol
)))
347 if (req
->ai_socktype
)
348 return -EAI_SOCKTYPE
;
357 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
360 if (service
->num
< 0)
364 st
= (struct gaih_servtuple
*)
365 alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
367 if ((rc
= gaih_inet_serv (service
->name
, tp
, req
, st
, tmpbuf
)))
372 struct gaih_servtuple
**pst
= &st
;
373 for (tp
++; tp
->name
[0]; tp
++)
375 struct gaih_servtuple
*newp
;
377 if ((tp
->protoflag
& GAI_PROTO_NOSERVICE
) != 0)
380 if (req
->ai_socktype
!= 0
381 && req
->ai_socktype
!= tp
->socktype
)
383 if (req
->ai_protocol
!= 0
384 && !(tp
->protoflag
& GAI_PROTO_PROTOANY
)
385 && req
->ai_protocol
!= tp
->protocol
)
388 newp
= (struct gaih_servtuple
*)
389 alloca_account (sizeof (struct gaih_servtuple
),
392 if ((rc
= gaih_inet_serv (service
->name
,
393 tp
, req
, newp
, tmpbuf
)))
403 if (st
== (struct gaih_servtuple
*) &nullserv
)
409 port
= htons (service
->num
);
417 if (req
->ai_socktype
|| req
->ai_protocol
)
419 st
= alloca_account (sizeof (struct gaih_servtuple
), alloca_used
);
421 st
->socktype
= tp
->socktype
;
422 st
->protocol
= ((tp
->protoflag
& GAI_PROTO_PROTOANY
)
423 ? req
->ai_protocol
: tp
->protocol
);
428 /* Neither socket type nor protocol is set. Return all socket types
430 struct gaih_servtuple
**lastp
= &st
;
431 for (++tp
; tp
->name
[0]; ++tp
)
434 struct gaih_servtuple
*newp
;
436 newp
= alloca_account (sizeof (struct gaih_servtuple
),
439 newp
->socktype
= tp
->socktype
;
440 newp
->protocol
= tp
->protocol
;
449 bool malloc_name
= false;
450 bool malloc_addrmem
= false;
451 struct gaih_addrtuple
*addrmem
= NULL
;
452 bool malloc_canonbuf
= false;
453 char *canonbuf
= NULL
;
458 at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
459 at
->family
= AF_UNSPEC
;
464 if (req
->ai_flags
& AI_IDN
)
467 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
468 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
469 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
470 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
473 rc
= __idna_to_ascii_lz (name
, &p
, idn_flags
);
474 if (rc
!= IDNA_SUCCESS
)
476 /* No need to jump to free_and_return here. */
477 if (rc
== IDNA_MALLOC_ERROR
)
479 if (rc
== IDNA_DLOPEN_ERROR
)
481 return -EAI_IDN_ENCODE
;
483 /* In case the output string is the same as the input string
484 no new string has been allocated. */
493 if (__inet_aton (name
, (struct in_addr
*) at
->addr
) != 0)
495 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
496 at
->family
= AF_INET
;
497 else if (req
->ai_family
== AF_INET6
&& (req
->ai_flags
& AI_V4MAPPED
))
499 at
->addr
[3] = at
->addr
[0];
500 at
->addr
[2] = htonl (0xffff);
503 at
->family
= AF_INET6
;
507 result
= -EAI_ADDRFAMILY
;
508 goto free_and_return
;
511 if (req
->ai_flags
& AI_CANONNAME
)
514 else if (at
->family
== AF_UNSPEC
)
516 char *scope_delim
= strchr (name
, SCOPE_DELIMITER
);
520 bool malloc_namebuf
= false;
521 char *namebuf
= (char *) name
;
523 if (__glibc_unlikely (scope_delim
!= NULL
))
529 if (__libc_use_alloca (alloca_used
530 + scope_delim
- name
+ 1))
532 namebuf
= alloca_account (scope_delim
- name
+ 1,
534 *((char *) __mempcpy (namebuf
, name
,
535 scope_delim
- name
)) = '\0';
539 namebuf
= __strndup (name
, scope_delim
- name
);
542 assert (!malloc_name
);
545 malloc_namebuf
= true;
550 e
= inet_pton (AF_INET6
, namebuf
, at
->addr
);
554 else if (scope_delim
!= NULL
&& malloc_name
)
555 /* Undo what we did above. */
556 *scope_delim
= SCOPE_DELIMITER
;
560 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
561 at
->family
= AF_INET6
;
562 else if (req
->ai_family
== AF_INET
563 && IN6_IS_ADDR_V4MAPPED (at
->addr
))
565 at
->addr
[0] = at
->addr
[3];
566 at
->family
= AF_INET
;
570 result
= -EAI_ADDRFAMILY
;
571 goto free_and_return
;
574 if (scope_delim
!= NULL
575 && __inet6_scopeid_pton ((struct in6_addr
*) at
->addr
,
579 result
= -EAI_NONAME
;
580 goto free_and_return
;
583 if (req
->ai_flags
& AI_CANONNAME
)
588 if (at
->family
== AF_UNSPEC
&& (req
->ai_flags
& AI_NUMERICHOST
) == 0)
590 struct gaih_addrtuple
**pat
= &at
;
592 int no_inet6_data
= 0;
594 enum nss_status inet6_status
= NSS_STATUS_UNAVAIL
;
595 enum nss_status status
= NSS_STATUS_UNAVAIL
;
599 /* If we do not have to look for IPv6 addresses or the canonical
600 name, use the simple, old functions, which do not support
601 IPv6 scope ids, nor retrieving the canonical name. */
602 if (req
->ai_family
== AF_INET
603 && (req
->ai_flags
& AI_CANONNAME
) == 0)
612 rc
= __gethostbyname2_r (name
, AF_INET
, &th
,
613 tmpbuf
->data
, tmpbuf
->length
,
615 if (rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
617 if (!scratch_buffer_grow (tmpbuf
))
619 result
= -EAI_MEMORY
;
620 goto free_and_return
;
628 /* We found data, convert it. */
629 if (!convert_hostent_to_gaih_addrtuple
630 (req
, AF_INET
, h
, &addrmem
))
632 result
= -EAI_MEMORY
;
633 goto free_and_return
;
636 /* The conversion uses malloc unconditionally. */
637 malloc_addrmem
= true;
642 if (herrno
== NETDB_INTERNAL
)
644 __set_h_errno (herrno
);
645 result
= -EAI_SYSTEM
;
647 else if (herrno
== TRY_AGAIN
)
650 /* We made requests but they turned out no data.
651 The name is known, though. */
652 result
= -EAI_NODATA
;
654 goto free_and_return
;
661 if (__nss_not_use_nscd_hosts
> 0
662 && ++__nss_not_use_nscd_hosts
> NSS_NSCD_RETRY
)
663 __nss_not_use_nscd_hosts
= 0;
665 if (!__nss_not_use_nscd_hosts
666 && !__nss_database_custom
[NSS_DBSIDX_hosts
])
668 /* Try to use nscd. */
669 struct nscd_ai_result
*air
= NULL
;
671 int err
= __nscd_getai (name
, &air
, &herrno
);
674 /* Transform into gaih_addrtuple list. */
675 bool added_canon
= (req
->ai_flags
& AI_CANONNAME
) == 0;
676 char *addrs
= air
->addrs
;
678 if (__libc_use_alloca (alloca_used
679 + air
->naddrs
* sizeof (struct gaih_addrtuple
)))
680 addrmem
= alloca_account (air
->naddrs
681 * sizeof (struct gaih_addrtuple
),
685 addrmem
= malloc (air
->naddrs
686 * sizeof (struct gaih_addrtuple
));
689 result
= -EAI_MEMORY
;
690 goto free_and_return
;
692 malloc_addrmem
= true;
695 struct gaih_addrtuple
*addrfree
= addrmem
;
696 for (int i
= 0; i
< air
->naddrs
; ++i
)
698 socklen_t size
= (air
->family
[i
] == AF_INET
699 ? INADDRSZ
: IN6ADDRSZ
);
701 if (!((air
->family
[i
] == AF_INET
702 && req
->ai_family
== AF_INET6
703 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
704 || req
->ai_family
== AF_UNSPEC
705 || air
->family
[i
] == req
->ai_family
))
707 /* Skip over non-matching result. */
717 uint32_t *pataddr
= (*pat
)->addr
;
719 if (added_canon
|| air
->canon
== NULL
)
721 else if (canonbuf
== NULL
)
723 size_t canonlen
= strlen (air
->canon
) + 1;
724 if ((req
->ai_flags
& AI_CANONIDN
) != 0
725 && __libc_use_alloca (alloca_used
+ canonlen
))
726 canonbuf
= alloca_account (canonlen
, alloca_used
);
729 canonbuf
= malloc (canonlen
);
730 if (canonbuf
== NULL
)
732 result
= -EAI_MEMORY
;
733 goto free_and_return
;
735 malloc_canonbuf
= true;
737 canon
= (*pat
)->name
= memcpy (canonbuf
, air
->canon
,
741 if (air
->family
[i
] == AF_INET
742 && req
->ai_family
== AF_INET6
743 && (req
->ai_flags
& AI_V4MAPPED
))
745 (*pat
)->family
= AF_INET6
;
746 pataddr
[3] = *(uint32_t *) addrs
;
747 pataddr
[2] = htonl (0xffff);
750 pat
= &((*pat
)->next
);
753 else if (req
->ai_family
== AF_UNSPEC
754 || air
->family
[i
] == req
->ai_family
)
756 (*pat
)->family
= air
->family
[i
];
757 memcpy (pataddr
, addrs
, size
);
758 pat
= &((*pat
)->next
);
760 if (air
->family
[i
] == AF_INET6
)
768 if (at
->family
== AF_UNSPEC
)
770 result
= -EAI_NONAME
;
771 goto free_and_return
;
777 /* The database contains a negative entry. */
778 goto free_and_return
;
779 else if (__nss_not_use_nscd_hosts
== 0)
781 if (herrno
== NETDB_INTERNAL
&& errno
== ENOMEM
)
782 result
= -EAI_MEMORY
;
783 else if (herrno
== TRY_AGAIN
)
786 result
= -EAI_SYSTEM
;
788 goto free_and_return
;
793 if (__nss_hosts_database
== NULL
)
794 no_more
= __nss_database_lookup ("hosts", NULL
,
795 "dns [!UNAVAIL=return] files",
796 &__nss_hosts_database
);
799 nip
= __nss_hosts_database
;
801 /* Initialize configurations. */
803 if (__res_maybe_init (&_res
, 0) == -1)
806 /* If we are looking for both IPv4 and IPv6 address we don't
807 want the lookup functions to automatically promote IPv4
808 addresses to IPv6 addresses. Currently this is decided
809 by setting the RES_USE_INET6 bit in _res.options. */
810 old_res_options
= _res
.options
;
811 _res
.options
&= ~DEPRECATED_RES_USE_INET6
;
816 nss_gethostbyname4_r fct4
= NULL
;
818 /* gethostbyname4_r sends out parallel A and AAAA queries and
819 is thus only suitable for PF_UNSPEC. */
820 if (req
->ai_family
== PF_UNSPEC
)
821 fct4
= __nss_lookup_function (nip
, "gethostbyname4_r");
830 status
= DL_CALL_FCT (fct4
, (name
, pat
,
831 tmpbuf
->data
, tmpbuf
->length
,
834 if (status
== NSS_STATUS_SUCCESS
)
836 if (status
!= NSS_STATUS_TRYAGAIN
837 || rc
!= ERANGE
|| herrno
!= NETDB_INTERNAL
)
839 if (herrno
== TRY_AGAIN
)
842 no_data
= herrno
== NO_DATA
;
846 if (!scratch_buffer_grow (tmpbuf
))
849 |= old_res_options
& DEPRECATED_RES_USE_INET6
;
850 result
= -EAI_MEMORY
;
851 goto free_and_return
;
855 if (status
== NSS_STATUS_SUCCESS
)
860 if ((req
->ai_flags
& AI_CANONNAME
) != 0 && canon
== NULL
)
861 canon
= (*pat
)->name
;
865 if ((*pat
)->family
== AF_INET
866 && req
->ai_family
== AF_INET6
867 && (req
->ai_flags
& AI_V4MAPPED
) != 0)
869 uint32_t *pataddr
= (*pat
)->addr
;
870 (*pat
)->family
= AF_INET6
;
871 pataddr
[3] = pataddr
[0];
872 pataddr
[2] = htonl (0xffff);
875 pat
= &((*pat
)->next
);
878 else if (req
->ai_family
== AF_UNSPEC
879 || (*pat
)->family
== req
->ai_family
)
881 pat
= &((*pat
)->next
);
884 if (req
->ai_family
== AF_INET6
)
888 *pat
= ((*pat
)->next
);
892 no_inet6_data
= no_data
;
896 nss_gethostbyname3_r fct
= NULL
;
897 if (req
->ai_flags
& AI_CANONNAME
)
898 /* No need to use this function if we do not look for
899 the canonical name. The function does not exist in
900 all NSS modules and therefore the lookup would
902 fct
= __nss_lookup_function (nip
, "gethostbyname3_r");
904 /* We are cheating here. The gethostbyname2_r
905 function does not have the same interface as
906 gethostbyname3_r but the extra arguments the
907 latter takes are added at the end. So the
908 gethostbyname2_r code will just ignore them. */
909 fct
= __nss_lookup_function (nip
, "gethostbyname2_r");
913 if (req
->ai_family
== AF_INET6
914 || req
->ai_family
== AF_UNSPEC
)
916 gethosts (AF_INET6
, struct in6_addr
);
917 no_inet6_data
= no_data
;
918 inet6_status
= status
;
920 if (req
->ai_family
== AF_INET
921 || req
->ai_family
== AF_UNSPEC
922 || (req
->ai_family
== AF_INET6
923 && (req
->ai_flags
& AI_V4MAPPED
)
924 /* Avoid generating the mapped addresses if we
925 know we are not going to need them. */
926 && ((req
->ai_flags
& AI_ALL
) || !got_ipv6
)))
928 gethosts (AF_INET
, struct in_addr
);
930 if (req
->ai_family
== AF_INET
)
932 no_inet6_data
= no_data
;
933 inet6_status
= status
;
937 /* If we found one address for AF_INET or AF_INET6,
938 don't continue the search. */
939 if (inet6_status
== NSS_STATUS_SUCCESS
940 || status
== NSS_STATUS_SUCCESS
)
942 if ((req
->ai_flags
& AI_CANONNAME
) != 0
945 /* If we need the canonical name, get it
946 from the same service as the result. */
947 nss_getcanonname_r cfct
;
950 cfct
= __nss_lookup_function (nip
,
954 const size_t max_fqdn_len
= 256;
955 if ((req
->ai_flags
& AI_CANONIDN
) != 0
956 && __libc_use_alloca (alloca_used
958 canonbuf
= alloca_account (max_fqdn_len
,
962 canonbuf
= malloc (max_fqdn_len
);
963 if (canonbuf
== NULL
)
967 & DEPRECATED_RES_USE_INET6
;
968 result
= -EAI_MEMORY
;
969 goto free_and_return
;
971 malloc_canonbuf
= true;
975 if (DL_CALL_FCT (cfct
, (at
->name
?: name
,
979 == NSS_STATUS_SUCCESS
)
983 /* If the canonical name cannot be
984 determined, use the passed in
989 malloc_canonbuf
= false;
995 status
= NSS_STATUS_SUCCESS
;
999 /* We can have different states for AF_INET and
1000 AF_INET6. Try to find a useful one for both. */
1001 if (inet6_status
== NSS_STATUS_TRYAGAIN
)
1002 status
= NSS_STATUS_TRYAGAIN
;
1003 else if (status
== NSS_STATUS_UNAVAIL
1004 && inet6_status
!= NSS_STATUS_UNAVAIL
)
1005 status
= inet6_status
;
1010 status
= NSS_STATUS_UNAVAIL
;
1011 /* Could not load any of the lookup functions. Indicate
1012 an internal error if the failure was due to a system
1013 error other than the file not being found. We use the
1014 errno from the last failed callback. */
1015 if (errno
!= 0 && errno
!= ENOENT
)
1016 __set_h_errno (NETDB_INTERNAL
);
1020 if (nss_next_action (nip
, status
) == NSS_ACTION_RETURN
)
1023 if (nip
->next
== NULL
)
1029 _res
.options
|= old_res_options
& DEPRECATED_RES_USE_INET6
;
1031 if (h_errno
== NETDB_INTERNAL
)
1033 result
= -EAI_SYSTEM
;
1034 goto free_and_return
;
1037 if (no_data
!= 0 && no_inet6_data
!= 0)
1039 /* If both requests timed out report this. */
1040 if (no_data
== EAI_AGAIN
&& no_inet6_data
== EAI_AGAIN
)
1041 result
= -EAI_AGAIN
;
1043 /* We made requests but they turned out no data. The name
1044 is known, though. */
1045 result
= -EAI_NODATA
;
1047 goto free_and_return
;
1052 if (at
->family
== AF_UNSPEC
)
1054 result
= -EAI_NONAME
;
1055 goto free_and_return
;
1060 struct gaih_addrtuple
*atr
;
1061 atr
= at
= alloca_account (sizeof (struct gaih_addrtuple
), alloca_used
);
1062 memset (at
, '\0', sizeof (struct gaih_addrtuple
));
1064 if (req
->ai_family
== AF_UNSPEC
)
1066 at
->next
= __alloca (sizeof (struct gaih_addrtuple
));
1067 memset (at
->next
, '\0', sizeof (struct gaih_addrtuple
));
1070 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET6
)
1072 at
->family
= AF_INET6
;
1073 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1074 memcpy (at
->addr
, &in6addr_loopback
, sizeof (struct in6_addr
));
1078 if (req
->ai_family
== AF_UNSPEC
|| req
->ai_family
== AF_INET
)
1080 atr
->family
= AF_INET
;
1081 if ((req
->ai_flags
& AI_PASSIVE
) == 0)
1082 atr
->addr
[0] = htonl (INADDR_LOOPBACK
);
1087 struct gaih_servtuple
*st2
;
1088 struct gaih_addrtuple
*at2
= at
;
1093 buffer is the size of an unformatted IPv6 address in printable format.
1097 /* Only the first entry gets the canonical name. */
1098 if (at2
== at
&& (req
->ai_flags
& AI_CANONNAME
) != 0)
1101 /* If the canonical name cannot be determined, use
1102 the passed in string. */
1106 if (req
->ai_flags
& AI_CANONIDN
)
1109 if (req
->ai_flags
& AI_IDN_ALLOW_UNASSIGNED
)
1110 idn_flags
|= IDNA_ALLOW_UNASSIGNED
;
1111 if (req
->ai_flags
& AI_IDN_USE_STD3_ASCII_RULES
)
1112 idn_flags
|= IDNA_USE_STD3_ASCII_RULES
;
1115 int rc
= __idna_to_unicode_lzlz (canon
, &out
, idn_flags
);
1116 if (rc
!= IDNA_SUCCESS
)
1118 if (rc
== IDNA_MALLOC_ERROR
)
1119 result
= -EAI_MEMORY
;
1120 else if (rc
== IDNA_DLOPEN_ERROR
)
1121 result
= -EAI_SYSTEM
;
1123 result
= -EAI_IDN_ENCODE
;
1124 goto free_and_return
;
1126 /* In case the output string is the same as the input
1127 string no new string has been allocated and we
1139 if (malloc_canonbuf
)
1140 /* We already allocated the string using malloc. */
1141 malloc_canonbuf
= false;
1144 canon
= __strdup (canon
);
1147 result
= -EAI_MEMORY
;
1148 goto free_and_return
;
1154 family
= at2
->family
;
1155 if (family
== AF_INET6
)
1157 socklen
= sizeof (struct sockaddr_in6
);
1159 /* If we looked up IPv4 mapped address discard them here if
1160 the caller isn't interested in all address and we have
1161 found at least one IPv6 address. */
1163 && (req
->ai_flags
& (AI_V4MAPPED
|AI_ALL
)) == AI_V4MAPPED
1164 && IN6_IS_ADDR_V4MAPPED (at2
->addr
))
1168 socklen
= sizeof (struct sockaddr_in
);
1170 for (st2
= st
; st2
!= NULL
; st2
= st2
->next
)
1172 struct addrinfo
*ai
;
1173 ai
= *pai
= malloc (sizeof (struct addrinfo
) + socklen
);
1176 free ((char *) canon
);
1177 result
= -EAI_MEMORY
;
1178 goto free_and_return
;
1181 ai
->ai_flags
= req
->ai_flags
;
1182 ai
->ai_family
= family
;
1183 ai
->ai_socktype
= st2
->socktype
;
1184 ai
->ai_protocol
= st2
->protocol
;
1185 ai
->ai_addrlen
= socklen
;
1186 ai
->ai_addr
= (void *) (ai
+ 1);
1188 /* We only add the canonical name once. */
1189 ai
->ai_canonname
= (char *) canon
;
1193 ai
->ai_addr
->sa_len
= socklen
;
1194 #endif /* _HAVE_SA_LEN */
1195 ai
->ai_addr
->sa_family
= family
;
1197 /* In case of an allocation error the list must be NULL
1201 if (family
== AF_INET6
)
1203 struct sockaddr_in6
*sin6p
=
1204 (struct sockaddr_in6
*) ai
->ai_addr
;
1206 sin6p
->sin6_port
= st2
->port
;
1207 sin6p
->sin6_flowinfo
= 0;
1208 memcpy (&sin6p
->sin6_addr
,
1209 at2
->addr
, sizeof (struct in6_addr
));
1210 sin6p
->sin6_scope_id
= at2
->scopeid
;
1214 struct sockaddr_in
*sinp
=
1215 (struct sockaddr_in
*) ai
->ai_addr
;
1216 sinp
->sin_port
= st2
->port
;
1217 memcpy (&sinp
->sin_addr
,
1218 at2
->addr
, sizeof (struct in_addr
));
1219 memset (sinp
->sin_zero
, '\0', sizeof (sinp
->sin_zero
));
1222 pai
= &(ai
->ai_next
);
1234 free ((char *) name
);
1237 if (malloc_canonbuf
)
1246 struct addrinfo
*dest_addr
;
1247 /* Using sockaddr_storage is for now overkill. We only support IPv4
1248 and IPv6 so far. If this changes at some point we can adjust the
1250 struct sockaddr_in6 source_addr
;
1251 uint8_t source_addr_len
;
1252 bool got_source_addr
;
1253 uint8_t source_addr_flags
;
1259 struct sort_result_combo
1261 struct sort_result
*results
;
1266 #if __BYTE_ORDER == __BIG_ENDIAN
1267 # define htonl_c(n) n
1269 # define htonl_c(n) __bswap_constant_32 (n)
1272 static const struct scopeentry
1281 } default_scopes
[] =
1283 /* Link-local addresses: scope 2. */
1284 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1285 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1286 /* Default: scope 14. */
1287 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1290 /* The label table. */
1291 static const struct scopeentry
*scopes
;
1295 get_scope (const struct sockaddr_in6
*in6
)
1298 if (in6
->sin6_family
== PF_INET6
)
1300 if (! IN6_IS_ADDR_MULTICAST (&in6
->sin6_addr
))
1302 if (IN6_IS_ADDR_LINKLOCAL (&in6
->sin6_addr
)
1303 /* RFC 4291 2.5.3 says that the loopback address is to be
1304 treated like a link-local address. */
1305 || IN6_IS_ADDR_LOOPBACK (&in6
->sin6_addr
))
1307 else if (IN6_IS_ADDR_SITELOCAL (&in6
->sin6_addr
))
1310 /* XXX Is this the correct default behavior? */
1314 scope
= in6
->sin6_addr
.s6_addr
[1] & 0xf;
1316 else if (in6
->sin6_family
== PF_INET
)
1318 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1323 if ((in
->sin_addr
.s_addr
& scopes
[cnt
].netmask
)
1324 == scopes
[cnt
].addr32
)
1325 return scopes
[cnt
].scope
;
1332 /* XXX What is a good default? */
1341 struct in6_addr prefix
;
1347 /* The label table. */
1348 static const struct prefixentry
*labels
;
1350 /* Default labels. */
1351 static const struct prefixentry default_labels
[] =
1353 /* See RFC 3484 for the details. */
1355 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1359 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1360 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1363 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1367 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1368 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1370 /* The next two entries differ from RFC 3484. We need to treat
1371 IPv6 site-local addresses special because they are never NATed,
1372 unlike site-locale IPv4 addresses. If this would not happen, on
1373 machines which have only IPv4 and IPv6 site-local addresses, the
1374 sorting would prefer the IPv6 site-local addresses, causing
1375 unnecessary delays when trying to connect to a global IPv6 address
1376 through a site-local IPv6 address. */
1378 = { .__u6_addr8
= { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1382 = { .__u6_addr8
= { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1385 /* Additional rule for Teredo tunnels. */
1387 = { .__u6_addr8
= { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1391 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1397 /* The precedence table. */
1398 static const struct prefixentry
*precedence
;
1400 /* The default precedences. */
1401 static const struct prefixentry default_precedence
[] =
1403 /* See RFC 3484 for the details. */
1405 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1409 = { .__u6_addr8
= { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1413 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1414 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1417 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1418 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1421 = { .__u6_addr8
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1428 match_prefix (const struct sockaddr_in6
*in6
,
1429 const struct prefixentry
*list
, int default_val
)
1432 struct sockaddr_in6 in6_mem
;
1434 if (in6
->sin6_family
== PF_INET
)
1436 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) in6
;
1438 /* Construct a V4-to-6 mapped address. */
1439 in6_mem
.sin6_family
= PF_INET6
;
1440 in6_mem
.sin6_port
= in
->sin_port
;
1441 in6_mem
.sin6_flowinfo
= 0;
1442 memset (&in6_mem
.sin6_addr
, '\0', sizeof (in6_mem
.sin6_addr
));
1443 in6_mem
.sin6_addr
.s6_addr16
[5] = 0xffff;
1444 in6_mem
.sin6_addr
.s6_addr32
[3] = in
->sin_addr
.s_addr
;
1445 in6_mem
.sin6_scope_id
= 0;
1449 else if (in6
->sin6_family
!= PF_INET6
)
1452 for (idx
= 0; ; ++idx
)
1454 unsigned int bits
= list
[idx
].bits
;
1455 const uint8_t *mask
= list
[idx
].prefix
.s6_addr
;
1456 const uint8_t *val
= in6
->sin6_addr
.s6_addr
;
1470 if ((*mask
& (0xff00 >> bits
)) == (*val
& (0xff00 >> bits
)))
1476 return list
[idx
].val
;
1481 get_label (const struct sockaddr_in6
*in6
)
1483 /* XXX What is a good default value? */
1484 return match_prefix (in6
, labels
, INT_MAX
);
1489 get_precedence (const struct sockaddr_in6
*in6
)
1491 /* XXX What is a good default value? */
1492 return match_prefix (in6
, precedence
, 0);
1496 /* Find last bit set in a word. */
1502 for (n
= 0, mask
= 1 << 31; n
< 32; mask
>>= 1, ++n
)
1503 if ((a
& mask
) != 0)
1510 rfc3484_sort (const void *p1
, const void *p2
, void *arg
)
1512 const size_t idx1
= *(const size_t *) p1
;
1513 const size_t idx2
= *(const size_t *) p2
;
1514 struct sort_result_combo
*src
= (struct sort_result_combo
*) arg
;
1515 struct sort_result
*a1
= &src
->results
[idx1
];
1516 struct sort_result
*a2
= &src
->results
[idx2
];
1518 /* Rule 1: Avoid unusable destinations.
1519 We have the got_source_addr flag set if the destination is reachable. */
1520 if (a1
->got_source_addr
&& ! a2
->got_source_addr
)
1522 if (! a1
->got_source_addr
&& a2
->got_source_addr
)
1526 /* Rule 2: Prefer matching scope. Only interesting if both
1527 destination addresses are IPv6. */
1529 = get_scope ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1532 = get_scope ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1534 if (a1
->got_source_addr
)
1536 int a1_src_scope
= get_scope (&a1
->source_addr
);
1537 int a2_src_scope
= get_scope (&a2
->source_addr
);
1539 if (a1_dst_scope
== a1_src_scope
&& a2_dst_scope
!= a2_src_scope
)
1541 if (a1_dst_scope
!= a1_src_scope
&& a2_dst_scope
== a2_src_scope
)
1546 /* Rule 3: Avoid deprecated addresses. */
1547 if (a1
->got_source_addr
)
1549 if (!(a1
->source_addr_flags
& in6ai_deprecated
)
1550 && (a2
->source_addr_flags
& in6ai_deprecated
))
1552 if ((a1
->source_addr_flags
& in6ai_deprecated
)
1553 && !(a2
->source_addr_flags
& in6ai_deprecated
))
1557 /* Rule 4: Prefer home addresses. */
1558 if (a1
->got_source_addr
)
1560 if (!(a1
->source_addr_flags
& in6ai_homeaddress
)
1561 && (a2
->source_addr_flags
& in6ai_homeaddress
))
1563 if ((a1
->source_addr_flags
& in6ai_homeaddress
)
1564 && !(a2
->source_addr_flags
& in6ai_homeaddress
))
1568 /* Rule 5: Prefer matching label. */
1569 if (a1
->got_source_addr
)
1572 = get_label ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1573 int a1_src_label
= get_label (&a1
->source_addr
);
1576 = get_label ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1577 int a2_src_label
= get_label (&a2
->source_addr
);
1579 if (a1_dst_label
== a1_src_label
&& a2_dst_label
!= a2_src_label
)
1581 if (a1_dst_label
!= a1_src_label
&& a2_dst_label
== a2_src_label
)
1586 /* Rule 6: Prefer higher precedence. */
1588 = get_precedence ((struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
);
1590 = get_precedence ((struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
);
1592 if (a1_prec
> a2_prec
)
1594 if (a1_prec
< a2_prec
)
1598 /* Rule 7: Prefer native transport. */
1599 if (a1
->got_source_addr
)
1601 /* The same interface index means the same interface which means
1602 there is no difference in transport. This should catch many
1604 if (a1
->index
!= a2
->index
)
1606 int a1_native
= a1
->native
;
1607 int a2_native
= a2
->native
;
1609 if (a1_native
== -1 || a2_native
== -1)
1612 if (a1_native
== -1)
1614 /* If we do not have the information use 'native' as
1617 a1_index
= a1
->index
;
1620 a1_index
= 0xffffffffu
;
1623 if (a2_native
== -1)
1625 /* If we do not have the information use 'native' as
1628 a2_index
= a2
->index
;
1631 a2_index
= 0xffffffffu
;
1633 __check_native (a1_index
, &a1_native
, a2_index
, &a2_native
);
1635 /* Fill in the results in all the records. */
1636 for (int i
= 0; i
< src
->nresults
; ++i
)
1637 if (a1_index
!= -1 && src
->results
[i
].index
== a1_index
)
1639 assert (src
->results
[i
].native
== -1
1640 || src
->results
[i
].native
== a1_native
);
1641 src
->results
[i
].native
= a1_native
;
1643 else if (a2_index
!= -1 && src
->results
[i
].index
== a2_index
)
1645 assert (src
->results
[i
].native
== -1
1646 || src
->results
[i
].native
== a2_native
);
1647 src
->results
[i
].native
= a2_native
;
1651 if (a1_native
&& !a2_native
)
1653 if (!a1_native
&& a2_native
)
1659 /* Rule 8: Prefer smaller scope. */
1660 if (a1_dst_scope
< a2_dst_scope
)
1662 if (a1_dst_scope
> a2_dst_scope
)
1666 /* Rule 9: Use longest matching prefix. */
1667 if (a1
->got_source_addr
1668 && a1
->dest_addr
->ai_family
== a2
->dest_addr
->ai_family
)
1673 if (a1
->dest_addr
->ai_family
== PF_INET
)
1675 assert (a1
->source_addr
.sin6_family
== PF_INET
);
1676 assert (a2
->source_addr
.sin6_family
== PF_INET
);
1678 /* Outside of subnets, as defined by the network masks,
1679 common address prefixes for IPv4 addresses make no sense.
1680 So, define a non-zero value only if source and
1681 destination address are on the same subnet. */
1682 struct sockaddr_in
*in1_dst
1683 = (struct sockaddr_in
*) a1
->dest_addr
->ai_addr
;
1684 in_addr_t in1_dst_addr
= ntohl (in1_dst
->sin_addr
.s_addr
);
1685 struct sockaddr_in
*in1_src
1686 = (struct sockaddr_in
*) &a1
->source_addr
;
1687 in_addr_t in1_src_addr
= ntohl (in1_src
->sin_addr
.s_addr
);
1688 in_addr_t netmask1
= 0xffffffffu
<< (32 - a1
->prefixlen
);
1690 if ((in1_src_addr
& netmask1
) == (in1_dst_addr
& netmask1
))
1691 bit1
= fls (in1_dst_addr
^ in1_src_addr
);
1693 struct sockaddr_in
*in2_dst
1694 = (struct sockaddr_in
*) a2
->dest_addr
->ai_addr
;
1695 in_addr_t in2_dst_addr
= ntohl (in2_dst
->sin_addr
.s_addr
);
1696 struct sockaddr_in
*in2_src
1697 = (struct sockaddr_in
*) &a2
->source_addr
;
1698 in_addr_t in2_src_addr
= ntohl (in2_src
->sin_addr
.s_addr
);
1699 in_addr_t netmask2
= 0xffffffffu
<< (32 - a2
->prefixlen
);
1701 if ((in2_src_addr
& netmask2
) == (in2_dst_addr
& netmask2
))
1702 bit2
= fls (in2_dst_addr
^ in2_src_addr
);
1704 else if (a1
->dest_addr
->ai_family
== PF_INET6
)
1706 assert (a1
->source_addr
.sin6_family
== PF_INET6
);
1707 assert (a2
->source_addr
.sin6_family
== PF_INET6
);
1709 struct sockaddr_in6
*in1_dst
;
1710 struct sockaddr_in6
*in1_src
;
1711 struct sockaddr_in6
*in2_dst
;
1712 struct sockaddr_in6
*in2_src
;
1714 in1_dst
= (struct sockaddr_in6
*) a1
->dest_addr
->ai_addr
;
1715 in1_src
= (struct sockaddr_in6
*) &a1
->source_addr
;
1716 in2_dst
= (struct sockaddr_in6
*) a2
->dest_addr
->ai_addr
;
1717 in2_src
= (struct sockaddr_in6
*) &a2
->source_addr
;
1720 for (i
= 0; i
< 4; ++i
)
1721 if (in1_dst
->sin6_addr
.s6_addr32
[i
]
1722 != in1_src
->sin6_addr
.s6_addr32
[i
]
1723 || (in2_dst
->sin6_addr
.s6_addr32
[i
]
1724 != in2_src
->sin6_addr
.s6_addr32
[i
]))
1729 bit1
= fls (ntohl (in1_dst
->sin6_addr
.s6_addr32
[i
]
1730 ^ in1_src
->sin6_addr
.s6_addr32
[i
]));
1731 bit2
= fls (ntohl (in2_dst
->sin6_addr
.s6_addr32
[i
]
1732 ^ in2_src
->sin6_addr
.s6_addr32
[i
]));
1743 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1744 compare with the value indicating the order in which the entries
1745 have been received from the services. NB: no two entries can have
1746 the same order so the test will never return zero. */
1747 return idx1
< idx2
? -1 : 1;
1752 in6aicmp (const void *p1
, const void *p2
)
1754 struct in6addrinfo
*a1
= (struct in6addrinfo
*) p1
;
1755 struct in6addrinfo
*a2
= (struct in6addrinfo
*) p2
;
1757 return memcmp (a1
->addr
, a2
->addr
, sizeof (a1
->addr
));
1761 /* Name of the config file for RFC 3484 sorting (for now). */
1762 #define GAICONF_FNAME "/etc/gai.conf"
1765 /* Non-zero if we are supposed to reload the config file automatically
1766 whenever it changed. */
1767 static int gaiconf_reload_flag
;
1769 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1770 static int gaiconf_reload_flag_ever_set
;
1772 /* Last modification time. */
1773 #ifdef _STATBUF_ST_NSEC
1775 static struct timespec gaiconf_mtime
;
1778 save_gaiconf_mtime (const struct stat64
*st
)
1780 gaiconf_mtime
= st
->st_mtim
;
1784 check_gaiconf_mtime (const struct stat64
*st
)
1786 return (st
->st_mtim
.tv_sec
== gaiconf_mtime
.tv_sec
1787 && st
->st_mtim
.tv_nsec
== gaiconf_mtime
.tv_nsec
);
1792 static time_t gaiconf_mtime
;
1795 save_gaiconf_mtime (const struct stat64
*st
)
1797 gaiconf_mtime
= st
->st_mtime
;
1801 check_gaiconf_mtime (const struct stat64
*st
)
1803 return st
->st_mtime
== gaiconf_mtime
;
1809 libc_freeres_fn(fini
)
1811 if (labels
!= default_labels
)
1813 const struct prefixentry
*old
= labels
;
1814 labels
= default_labels
;
1815 free ((void *) old
);
1818 if (precedence
!= default_precedence
)
1820 const struct prefixentry
*old
= precedence
;
1821 precedence
= default_precedence
;
1822 free ((void *) old
);
1825 if (scopes
!= default_scopes
)
1827 const struct scopeentry
*old
= scopes
;
1828 scopes
= default_scopes
;
1829 free ((void *) old
);
1836 struct prefixentry entry
;
1837 struct prefixlist
*next
;
1843 struct scopeentry entry
;
1844 struct scopelist
*next
;
1849 free_prefixlist (struct prefixlist
*list
)
1851 while (list
!= NULL
)
1853 struct prefixlist
*oldp
= list
;
1861 free_scopelist (struct scopelist
*list
)
1863 while (list
!= NULL
)
1865 struct scopelist
*oldp
= list
;
1873 prefixcmp (const void *p1
, const void *p2
)
1875 const struct prefixentry
*e1
= (const struct prefixentry
*) p1
;
1876 const struct prefixentry
*e2
= (const struct prefixentry
*) p2
;
1878 if (e1
->bits
< e2
->bits
)
1880 if (e1
->bits
== e2
->bits
)
1887 scopecmp (const void *p1
, const void *p2
)
1889 const struct scopeentry
*e1
= (const struct scopeentry
*) p1
;
1890 const struct scopeentry
*e2
= (const struct scopeentry
*) p2
;
1892 if (e1
->netmask
> e2
->netmask
)
1894 if (e1
->netmask
== e2
->netmask
)
1903 struct prefixlist
*labellist
= NULL
;
1904 size_t nlabellist
= 0;
1905 bool labellist_nullbits
= false;
1906 struct prefixlist
*precedencelist
= NULL
;
1907 size_t nprecedencelist
= 0;
1908 bool precedencelist_nullbits
= false;
1909 struct scopelist
*scopelist
= NULL
;
1910 size_t nscopelist
= 0;
1911 bool scopelist_nullbits
= false;
1913 FILE *fp
= fopen (GAICONF_FNAME
, "rce");
1917 if (__fxstat64 (_STAT_VER
, fileno (fp
), &st
) != 0)
1926 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
1928 while (!feof_unlocked (fp
))
1930 ssize_t n
= __getline (&line
, &linelen
, fp
);
1934 /* Handle comments. No escaping possible so this is easy. */
1935 char *cp
= strchr (line
, '#');
1940 while (isspace (*cp
))
1944 while (*cp
!= '\0' && !isspace (*cp
))
1946 size_t cmdlen
= cp
- cmd
;
1950 while (isspace (*cp
))
1954 while (*cp
!= '\0' && !isspace (*cp
))
1956 size_t val1len
= cp
- cmd
;
1958 /* We always need at least two values. */
1964 while (isspace (*cp
))
1968 while (*cp
!= '\0' && !isspace (*cp
))
1971 /* Ignore the rest of the line. */
1974 struct prefixlist
**listp
;
1980 if (strcmp (cmd
, "label") == 0)
1982 struct in6_addr prefix
;
1983 unsigned long int bits
;
1984 unsigned long int val
;
1989 nullbitsp
= &labellist_nullbits
;
1994 cp
= strchr (val1
, '/');
1997 if (inet_pton (AF_INET6
, val1
, &prefix
)
1999 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2003 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2008 struct prefixlist
*newp
= malloc (sizeof (*newp
));
2016 memcpy (&newp
->entry
.prefix
, &prefix
, sizeof (prefix
));
2017 newp
->entry
.bits
= bits
;
2018 newp
->entry
.val
= val
;
2019 newp
->next
= *listp
;
2022 *nullbitsp
|= bits
== 0;
2028 if (strcmp (cmd
, "reload") == 0)
2030 gaiconf_reload_flag
= strcmp (val1
, "yes") == 0;
2031 if (gaiconf_reload_flag
)
2032 gaiconf_reload_flag_ever_set
= 1;
2037 if (strcmp (cmd
, "scopev4") == 0)
2039 struct in6_addr prefix
;
2040 unsigned long int bits
;
2041 unsigned long int val
;
2046 cp
= strchr (val1
, '/');
2049 if (inet_pton (AF_INET6
, val1
, &prefix
))
2052 if (IN6_IS_ADDR_V4MAPPED (&prefix
)
2054 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2059 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2064 struct scopelist
*newp
;
2066 newp
= malloc (sizeof (*newp
));
2074 newp
->entry
.netmask
= htonl (bits
!= 96
2078 newp
->entry
.addr32
= (prefix
.s6_addr32
[3]
2079 & newp
->entry
.netmask
);
2080 newp
->entry
.scope
= val
;
2081 newp
->next
= scopelist
;
2084 scopelist_nullbits
|= bits
== 96;
2087 else if (inet_pton (AF_INET
, val1
, &prefix
.s6_addr32
[3])
2089 || (bits
= strtoul (cp
, &endp
, 10)) != ULONG_MAX
2093 && ((val
= strtoul (val2
, &endp
, 10)) != ULONG_MAX
2105 if (strcmp (cmd
, "precedence") == 0)
2107 listp
= &precedencelist
;
2108 lenp
= &nprecedencelist
;
2109 nullbitsp
= &precedencelist_nullbits
;
2120 /* Create the array for the labels. */
2121 struct prefixentry
*new_labels
;
2124 if (!labellist_nullbits
)
2126 new_labels
= malloc (nlabellist
* sizeof (*new_labels
));
2127 if (new_labels
== NULL
)
2131 if (!labellist_nullbits
)
2134 memset (&new_labels
[i
].prefix
, '\0', sizeof (struct in6_addr
));
2135 new_labels
[i
].bits
= 0;
2136 new_labels
[i
].val
= 1;
2139 struct prefixlist
*l
= labellist
;
2142 new_labels
[i
] = l
->entry
;
2145 free_prefixlist (labellist
);
2147 /* Sort the entries so that the most specific ones are at
2149 qsort (new_labels
, nlabellist
, sizeof (*new_labels
), prefixcmp
);
2152 new_labels
= (struct prefixentry
*) default_labels
;
2154 struct prefixentry
*new_precedence
;
2155 if (nprecedencelist
> 0)
2157 if (!precedencelist_nullbits
)
2159 new_precedence
= malloc (nprecedencelist
* sizeof (*new_precedence
));
2160 if (new_precedence
== NULL
)
2162 if (new_labels
!= default_labels
)
2167 int i
= nprecedencelist
;
2168 if (!precedencelist_nullbits
)
2171 memset (&new_precedence
[i
].prefix
, '\0',
2172 sizeof (struct in6_addr
));
2173 new_precedence
[i
].bits
= 0;
2174 new_precedence
[i
].val
= 40;
2177 struct prefixlist
*l
= precedencelist
;
2180 new_precedence
[i
] = l
->entry
;
2183 free_prefixlist (precedencelist
);
2185 /* Sort the entries so that the most specific ones are at
2187 qsort (new_precedence
, nprecedencelist
, sizeof (*new_precedence
),
2191 new_precedence
= (struct prefixentry
*) default_precedence
;
2193 struct scopeentry
*new_scopes
;
2196 if (!scopelist_nullbits
)
2198 new_scopes
= malloc (nscopelist
* sizeof (*new_scopes
));
2199 if (new_scopes
== NULL
)
2201 if (new_labels
!= default_labels
)
2203 if (new_precedence
!= default_precedence
)
2204 free (new_precedence
);
2209 if (!scopelist_nullbits
)
2212 new_scopes
[i
].addr32
= 0;
2213 new_scopes
[i
].netmask
= 0;
2214 new_scopes
[i
].scope
= 14;
2217 struct scopelist
*l
= scopelist
;
2220 new_scopes
[i
] = l
->entry
;
2223 free_scopelist (scopelist
);
2225 /* Sort the entries so that the most specific ones are at
2227 qsort (new_scopes
, nscopelist
, sizeof (*new_scopes
),
2231 new_scopes
= (struct scopeentry
*) default_scopes
;
2233 /* Now we are ready to replace the values. */
2234 const struct prefixentry
*old
= labels
;
2235 labels
= new_labels
;
2236 if (old
!= default_labels
)
2237 free ((void *) old
);
2240 precedence
= new_precedence
;
2241 if (old
!= default_precedence
)
2242 free ((void *) old
);
2244 const struct scopeentry
*oldscope
= scopes
;
2245 scopes
= new_scopes
;
2246 if (oldscope
!= default_scopes
)
2247 free ((void *) oldscope
);
2249 save_gaiconf_mtime (&st
);
2254 free_prefixlist (labellist
);
2255 free_prefixlist (precedencelist
);
2256 free_scopelist (scopelist
);
2258 /* If we previously read the file but it is gone now, free the
2259 old data and use the builtin one. Leave the reload flag
2267 gaiconf_reload (void)
2270 if (__xstat64 (_STAT_VER
, GAICONF_FNAME
, &st
) != 0
2271 || !check_gaiconf_mtime (&st
))
2277 getaddrinfo (const char *name
, const char *service
,
2278 const struct addrinfo
*hints
, struct addrinfo
**pai
)
2280 int i
= 0, last_i
= 0;
2282 struct addrinfo
*p
= NULL
;
2283 struct gaih_service gaih_service
, *pservice
;
2284 struct addrinfo local_hints
;
2286 if (name
!= NULL
&& name
[0] == '*' && name
[1] == 0)
2289 if (service
!= NULL
&& service
[0] == '*' && service
[1] == 0)
2292 if (name
== NULL
&& service
== NULL
)
2296 hints
= &default_hints
;
2299 & ~(AI_PASSIVE
|AI_CANONNAME
|AI_NUMERICHOST
|AI_ADDRCONFIG
|AI_V4MAPPED
2301 |AI_IDN
|AI_CANONIDN
|AI_IDN_ALLOW_UNASSIGNED
2302 |AI_IDN_USE_STD3_ASCII_RULES
2304 |AI_NUMERICSERV
|AI_ALL
))
2305 return EAI_BADFLAGS
;
2307 if ((hints
->ai_flags
& AI_CANONNAME
) && name
== NULL
)
2308 return EAI_BADFLAGS
;
2310 struct in6addrinfo
*in6ai
= NULL
;
2311 size_t in6ailen
= 0;
2312 bool seen_ipv4
= false;
2313 bool seen_ipv6
= false;
2314 bool check_pf_called
= false;
2316 if (hints
->ai_flags
& AI_ADDRCONFIG
)
2318 /* We might need information about what interfaces are available.
2319 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2320 cannot cache the results since new interfaces could be added at
2322 __check_pf (&seen_ipv4
, &seen_ipv6
, &in6ai
, &in6ailen
);
2323 check_pf_called
= true;
2325 /* Now make a decision on what we return, if anything. */
2326 if (hints
->ai_family
== PF_UNSPEC
&& (seen_ipv4
|| seen_ipv6
))
2328 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2329 narrow down the search. */
2330 if ((! seen_ipv4
|| ! seen_ipv6
) && (seen_ipv4
|| seen_ipv6
))
2332 local_hints
= *hints
;
2333 local_hints
.ai_family
= seen_ipv4
? PF_INET
: PF_INET6
;
2334 hints
= &local_hints
;
2337 else if ((hints
->ai_family
== PF_INET
&& ! seen_ipv4
)
2338 || (hints
->ai_family
== PF_INET6
&& ! seen_ipv6
))
2340 /* We cannot possibly return a valid answer. */
2341 __free_in6ai (in6ai
);
2346 if (service
&& service
[0])
2349 gaih_service
.name
= service
;
2350 gaih_service
.num
= strtoul (gaih_service
.name
, &c
, 10);
2353 if (hints
->ai_flags
& AI_NUMERICSERV
)
2355 __free_in6ai (in6ai
);
2359 gaih_service
.num
= -1;
2362 pservice
= &gaih_service
;
2367 struct addrinfo
**end
= &p
;
2369 unsigned int naddrs
= 0;
2370 if (hints
->ai_family
== AF_UNSPEC
|| hints
->ai_family
== AF_INET
2371 || hints
->ai_family
== AF_INET6
)
2373 struct scratch_buffer tmpbuf
;
2374 scratch_buffer_init (&tmpbuf
);
2375 last_i
= gaih_inet (name
, pservice
, hints
, end
, &naddrs
, &tmpbuf
);
2376 scratch_buffer_free (&tmpbuf
);
2381 __free_in6ai (in6ai
);
2387 end
= &((*end
)->ai_next
);
2393 __free_in6ai (in6ai
);
2399 /* Read the config file. */
2400 __libc_once_define (static, once
);
2401 __typeof (once
) old_once
= once
;
2402 __libc_once (once
, gaiconf_init
);
2403 /* Sort results according to RFC 3484. */
2404 struct sort_result
*results
;
2407 struct addrinfo
*last
= NULL
;
2408 char *canonname
= NULL
;
2409 bool malloc_results
;
2410 size_t alloc_size
= nresults
* (sizeof (*results
) + sizeof (size_t));
2413 = !__libc_use_alloca (alloc_size
);
2416 results
= malloc (alloc_size
);
2417 if (results
== NULL
)
2419 __free_in6ai (in6ai
);
2424 results
= alloca (alloc_size
);
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
))
2473 close_not_cancel_no_status (fd
);
2475 fd
= __socket (af
, SOCK_DGRAM
, IPPROTO_IP
);
2479 /* Reset the connection. */
2480 struct sockaddr sa
= { .sa_family
= AF_UNSPEC
};
2481 __connect (fd
, &sa
, sizeof (sa
));
2484 socklen_t sl
= sizeof (results
[i
].source_addr
);
2486 && __connect (fd
, q
->ai_addr
, q
->ai_addrlen
) == 0
2487 && __getsockname (fd
,
2488 (struct sockaddr
*) &results
[i
].source_addr
,
2491 results
[i
].source_addr_len
= sl
;
2492 results
[i
].got_source_addr
= true;
2496 /* See whether the source address is on the list of
2497 deprecated or temporary addresses. */
2498 struct in6addrinfo tmp
;
2500 if (q
->ai_family
== AF_INET
&& af
== AF_INET
)
2502 struct sockaddr_in
*sinp
2503 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2506 tmp
.addr
[2] = htonl (0xffff);
2507 /* Special case for lo interface, the source address
2508 being possibly different than the interface
2510 if ((ntohl(sinp
->sin_addr
.s_addr
) & 0xff000000)
2512 tmp
.addr
[3] = htonl(0x7f000001);
2514 tmp
.addr
[3] = sinp
->sin_addr
.s_addr
;
2518 struct sockaddr_in6
*sin6p
2519 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2520 memcpy (tmp
.addr
, &sin6p
->sin6_addr
, IN6ADDRSZ
);
2523 struct in6addrinfo
*found
2524 = bsearch (&tmp
, in6ai
, in6ailen
, sizeof (*in6ai
),
2528 results
[i
].source_addr_flags
= found
->flags
;
2529 results
[i
].prefixlen
= found
->prefixlen
;
2530 results
[i
].index
= found
->index
;
2534 if (q
->ai_family
== AF_INET
&& af
== AF_INET6
)
2536 /* We have to convert the address. The socket is
2537 IPv6 and the request is for IPv4. */
2538 struct sockaddr_in6
*sin6
2539 = (struct sockaddr_in6
*) &results
[i
].source_addr
;
2540 struct sockaddr_in
*sin
2541 = (struct sockaddr_in
*) &results
[i
].source_addr
;
2542 assert (IN6_IS_ADDR_V4MAPPED (sin6
->sin6_addr
.s6_addr32
));
2543 sin
->sin_family
= AF_INET
;
2544 /* We do not have to initialize sin_port since this
2545 fields has the same position and size in the IPv6
2547 assert (offsetof (struct sockaddr_in
, sin_port
)
2548 == offsetof (struct sockaddr_in6
, sin6_port
));
2549 assert (sizeof (sin
->sin_port
)
2550 == sizeof (sin6
->sin6_port
));
2551 memcpy (&sin
->sin_addr
,
2552 &sin6
->sin6_addr
.s6_addr32
[3], INADDRSZ
);
2553 results
[i
].source_addr_len
= sizeof (struct sockaddr_in
);
2556 else if (errno
== EAFNOSUPPORT
&& af
== AF_INET6
2557 && q
->ai_family
== AF_INET
)
2558 /* This could mean IPv6 sockets are IPv6-only. */
2561 /* Just make sure that if we have to process the same
2562 address again we do not copy any memory. */
2563 results
[i
].source_addr_len
= 0;
2566 /* Remember the canonical name. */
2567 if (q
->ai_canonname
!= NULL
)
2569 assert (canonname
== NULL
);
2570 canonname
= q
->ai_canonname
;
2571 q
->ai_canonname
= NULL
;
2576 close_not_cancel_no_status (fd
);
2578 /* We got all the source addresses we can get, now sort using
2580 struct sort_result_combo src
2581 = { .results
= results
, .nresults
= nresults
};
2582 if (__glibc_unlikely (gaiconf_reload_flag_ever_set
))
2584 __libc_lock_define_initialized (static, lock
);
2586 __libc_lock_lock (lock
);
2587 if (__libc_once_get (old_once
) && gaiconf_reload_flag
)
2589 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2590 __libc_lock_unlock (lock
);
2593 __qsort_r (order
, nresults
, sizeof (order
[0]), rfc3484_sort
, &src
);
2595 /* Queue the results up as they come out of sorting. */
2596 q
= p
= results
[order
[0]].dest_addr
;
2597 for (i
= 1; i
< nresults
; ++i
)
2598 q
= q
->ai_next
= results
[order
[i
]].dest_addr
;
2601 /* Fill in the canonical name into the new first entry. */
2602 p
->ai_canonname
= canonname
;
2608 __free_in6ai (in6ai
);
2616 return last_i
? -last_i
: EAI_NONAME
;
2618 libc_hidden_def (getaddrinfo
)
2620 nss_interface_function (getaddrinfo
)
2623 freeaddrinfo (struct addrinfo
*ai
)
2631 free (p
->ai_canonname
);
2635 libc_hidden_def (freeaddrinfo
)