1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
47 #include <stdio_ext.h>
51 #include <arpa/inet.h>
53 #include <netinet/in.h>
54 #include <sys/socket.h>
56 #include <sys/types.h>
58 #include <sys/utsname.h>
61 #include <bits/libc-lock.h>
62 #include <not-cancel.h>
63 #include <nscd/nscd-client.h>
64 #include <nscd/nscd_proto.h>
65 #include <resolv/res_hconf.h>
68 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
69 extern int __idna_to_unicode_lzlz (const char *input, char **output,
71 # include <libidn/idna.h>
82 struct gaih_servtuple *next;
88 static const struct gaih_servtuple nullserv;
100 /* Values for `protoflag'. */
101 #define GAI_PROTO_NOSERVICE 1
102 #define GAI_PROTO_PROTOANY 2
104 static const struct gaih_typeproto gaih_inet_typeproto[] =
106 { 0, 0, 0, false, "" },
107 { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
108 { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
109 #if defined SOCK_DCCP && defined IPPROTO_DCCP
110 { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
112 #ifdef IPPROTO_UDPLITE
113 { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
116 { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
117 { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
119 { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
120 { 0, 0, 0, false, "" }
123 static const struct addrinfo default_hints =
125 .ai_flags = AI_DEFAULT,
126 .ai_family = PF_UNSPEC,
131 .ai_canonname = NULL,
137 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
138 const struct addrinfo *req, struct gaih_servtuple *st)
141 size_t tmpbuflen = 1024;
148 tmpbuf = __alloca (tmpbuflen);
150 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
152 if (r != 0 || s == NULL)
163 st->socktype = tp->socktype;
164 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
165 ? req->ai_protocol : tp->protocol);
166 st->port = s->s_port;
171 #define gethosts(_family, _type) \
177 char *localcanon = NULL; \
181 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
182 &rc, &herrno, NULL, &localcanon)); \
183 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
185 if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
186 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
190 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
194 result = -EAI_MEMORY; \
195 goto free_and_return; \
198 malloc_tmpbuf = true; \
199 tmpbuflen = 2 * tmpbuflen; \
202 if (status == NSS_STATUS_SUCCESS && rc == 0) \
208 if (herrno == NETDB_INTERNAL) \
210 __set_h_errno (herrno); \
211 _res.options |= old_res_options & RES_USE_INET6; \
212 result = -EAI_SYSTEM; \
213 goto free_and_return; \
215 if (herrno == TRY_AGAIN) \
216 no_data = EAI_AGAIN; \
218 no_data = herrno == NO_DATA; \
220 else if (h != NULL) \
222 for (i = 0; h->h_addr_list[i]; i++) \
226 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
227 (*pat)->scopeid = 0; \
229 uint32_t *addr = (*pat)->addr; \
230 (*pat)->next = NULL; \
231 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
232 if (_family == AF_INET && req->ai_family == AF_INET6) \
234 (*pat)->family = AF_INET6; \
235 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
236 addr[2] = htonl (0xffff); \
242 (*pat)->family = _family; \
243 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
245 pat = &((*pat)->next); \
248 if (localcanon != NULL && canon == NULL) \
249 canon = strdupa (localcanon); \
251 if (_family == AF_INET6 && i > 0) \
257 typedef enum nss_status (*nss_gethostbyname4_r)
258 (const char *name, struct gaih_addrtuple **pat,
259 char *buffer, size_t buflen, int *errnop,
260 int *h_errnop, int32_t *ttlp);
261 typedef enum nss_status (*nss_gethostbyname3_r)
262 (const char *name, int af, struct hostent *host,
263 char *buffer, size_t buflen, int *errnop,
264 int *h_errnop, int32_t *ttlp, char **canonp);
265 typedef enum nss_status (*nss_getcanonname_r)
266 (const char *name, char *buffer, size_t buflen, char **result,
267 int *errnop, int *h_errnop);
268 extern service_user *__nss_hosts_database attribute_hidden;
272 gaih_inet (const char *name, const struct gaih_service *service,
273 const struct addrinfo *req, struct addrinfo **pai,
274 unsigned int *naddrs)
276 const struct gaih_typeproto *tp = gaih_inet_typeproto;
277 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
278 struct gaih_addrtuple *at = NULL;
280 bool got_ipv6 = false;
281 const char *canon = NULL;
282 const char *orig_name = name;
283 size_t alloca_used = 0;
285 if (req->ai_protocol || req->ai_socktype)
290 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
291 || (req->ai_protocol != 0
292 && !(tp->protoflag & GAI_PROTO_PROTOANY)
293 && req->ai_protocol != tp->protocol)))
298 if (req->ai_socktype)
299 return -EAI_SOCKTYPE;
308 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
311 if (service->num < 0)
315 st = (struct gaih_servtuple *)
316 alloca_account (sizeof (struct gaih_servtuple), alloca_used);
318 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
323 struct gaih_servtuple **pst = &st;
324 for (tp++; tp->name[0]; tp++)
326 struct gaih_servtuple *newp;
328 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
331 if (req->ai_socktype != 0
332 && req->ai_socktype != tp->socktype)
334 if (req->ai_protocol != 0
335 && !(tp->protoflag & GAI_PROTO_PROTOANY)
336 && req->ai_protocol != tp->protocol)
339 newp = (struct gaih_servtuple *)
340 alloca_account (sizeof (struct gaih_servtuple),
343 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
353 if (st == (struct gaih_servtuple *) &nullserv)
359 port = htons (service->num);
367 if (req->ai_socktype || req->ai_protocol)
369 st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
371 st->socktype = tp->socktype;
372 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
373 ? req->ai_protocol : tp->protocol);
378 /* Neither socket type nor protocol is set. Return all socket types
380 struct gaih_servtuple **lastp = &st;
381 for (++tp; tp->name[0]; ++tp)
384 struct gaih_servtuple *newp;
386 newp = alloca_account (sizeof (struct gaih_servtuple),
389 newp->socktype = tp->socktype;
390 newp->protocol = tp->protocol;
399 bool malloc_name = false;
400 bool malloc_addrmem = false;
401 struct gaih_addrtuple *addrmem = NULL;
402 bool malloc_canonbuf = false;
403 char *canonbuf = NULL;
404 bool malloc_tmpbuf = false;
409 at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
410 at->family = AF_UNSPEC;
415 if (req->ai_flags & AI_IDN)
418 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
419 idn_flags |= IDNA_ALLOW_UNASSIGNED;
420 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
421 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
424 rc = __idna_to_ascii_lz (name, &p, idn_flags);
425 if (rc != IDNA_SUCCESS)
427 /* No need to jump to free_and_return here. */
428 if (rc == IDNA_MALLOC_ERROR)
430 if (rc == IDNA_DLOPEN_ERROR)
432 return -EAI_IDN_ENCODE;
434 /* In case the output string is the same as the input string
435 no new string has been allocated. */
444 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
446 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
447 at->family = AF_INET;
448 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
450 at->addr[3] = at->addr[0];
451 at->addr[2] = htonl (0xffff);
454 at->family = AF_INET6;
458 result = -EAI_ADDRFAMILY;
459 goto free_and_return;
462 if (req->ai_flags & AI_CANONNAME)
465 else if (at->family == AF_UNSPEC)
467 char *scope_delim = strchr (name, SCOPE_DELIMITER);
471 bool malloc_namebuf = false;
472 char *namebuf = (char *) name;
474 if (__glibc_unlikely (scope_delim != NULL))
480 if (__libc_use_alloca (alloca_used
481 + scope_delim - name + 1))
483 namebuf = alloca_account (scope_delim - name + 1,
485 *((char *) __mempcpy (namebuf, name,
486 scope_delim - name)) = '\0';
490 namebuf = strndup (name, scope_delim - name);
493 assert (!malloc_name);
496 malloc_namebuf = true;
501 e = inet_pton (AF_INET6, namebuf, at->addr);
505 else if (scope_delim != NULL && malloc_name)
506 /* Undo what we did above. */
507 *scope_delim = SCOPE_DELIMITER;
511 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
512 at->family = AF_INET6;
513 else if (req->ai_family == AF_INET
514 && IN6_IS_ADDR_V4MAPPED (at->addr))
516 at->addr[0] = at->addr[3];
517 at->family = AF_INET;
521 result = -EAI_ADDRFAMILY;
522 goto free_and_return;
525 if (scope_delim != NULL)
527 int try_numericscope = 0;
528 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
529 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
531 at->scopeid = if_nametoindex (scope_delim + 1);
532 if (at->scopeid == 0)
533 try_numericscope = 1;
536 try_numericscope = 1;
538 if (try_numericscope != 0)
541 assert (sizeof (uint32_t) <= sizeof (unsigned long));
542 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
546 result = -EAI_NONAME;
547 goto free_and_return;
552 if (req->ai_flags & AI_CANONNAME)
557 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
559 struct gaih_addrtuple **pat = &at;
561 int no_inet6_data = 0;
563 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
564 enum nss_status status = NSS_STATUS_UNAVAIL;
568 /* If we do not have to look for IPv6 addresses or the canonical
569 name, use the simple, old functions, which do not support
570 IPv6 scope ids, nor retrieving the canonical name. */
571 if (req->ai_family == AF_INET
572 && (req->ai_flags & AI_CANONNAME) == 0)
574 /* Allocate additional room for struct host_data. */
575 size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*)
576 + 16 * sizeof(char));
577 assert (tmpbuf == NULL);
578 tmpbuf = alloca_account (tmpbuflen, alloca_used);
586 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
587 tmpbuflen, &h, &herrno);
588 if (rc != ERANGE || herrno != NETDB_INTERNAL)
592 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
593 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
598 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
602 result = -EAI_MEMORY;
603 goto free_and_return;
606 malloc_tmpbuf = true;
607 tmpbuflen = 2 * tmpbuflen;
616 /* We found data, count the number of addresses. */
617 for (i = 0; h->h_addr_list[i]; ++i)
619 if (i > 0 && *pat != NULL)
622 if (__libc_use_alloca (alloca_used
623 + i * sizeof (struct gaih_addrtuple)))
624 addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
629 * sizeof (struct gaih_addrtuple));
632 result = -EAI_MEMORY;
633 goto free_and_return;
635 malloc_addrmem = true;
638 /* Now convert it into the list. */
639 struct gaih_addrtuple *addrfree = addrmem;
640 for (i = 0; h->h_addr_list[i]; ++i)
648 (*pat)->family = AF_INET;
649 memcpy ((*pat)->addr, h->h_addr_list[i],
651 pat = &((*pat)->next);
657 if (herrno == NETDB_INTERNAL)
659 __set_h_errno (herrno);
660 result = -EAI_SYSTEM;
662 else if (herrno == TRY_AGAIN)
665 /* We made requests but they turned out no data.
666 The name is known, though. */
667 result = -EAI_NODATA;
669 goto free_and_return;
676 if (__nss_not_use_nscd_hosts > 0
677 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
678 __nss_not_use_nscd_hosts = 0;
680 if (!__nss_not_use_nscd_hosts
681 && !__nss_database_custom[NSS_DBSIDX_hosts])
683 /* Try to use nscd. */
684 struct nscd_ai_result *air = NULL;
686 int err = __nscd_getai (name, &air, &herrno);
689 /* Transform into gaih_addrtuple list. */
690 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
691 char *addrs = air->addrs;
693 if (__libc_use_alloca (alloca_used
694 + air->naddrs * sizeof (struct gaih_addrtuple)))
695 addrmem = alloca_account (air->naddrs
696 * sizeof (struct gaih_addrtuple),
700 addrmem = malloc (air->naddrs
701 * sizeof (struct gaih_addrtuple));
704 result = -EAI_MEMORY;
705 goto free_and_return;
707 malloc_addrmem = true;
710 struct gaih_addrtuple *addrfree = addrmem;
711 for (int i = 0; i < air->naddrs; ++i)
713 if (!((air->family[i] == AF_INET
714 && req->ai_family == AF_INET6
715 && (req->ai_flags & AI_V4MAPPED) != 0)
716 || req->ai_family == AF_UNSPEC
717 || air->family[i] == req->ai_family))
718 /* Skip over non-matching result. */
721 socklen_t size = (air->family[i] == AF_INET
722 ? INADDRSZ : IN6ADDRSZ);
728 uint32_t *pataddr = (*pat)->addr;
730 if (added_canon || air->canon == NULL)
732 else if (canonbuf == NULL)
734 size_t canonlen = strlen (air->canon) + 1;
735 if ((req->ai_flags & AI_CANONIDN) != 0
736 && __libc_use_alloca (alloca_used + canonlen))
737 canonbuf = alloca_account (canonlen, alloca_used);
740 canonbuf = malloc (canonlen);
741 if (canonbuf == NULL)
743 result = -EAI_MEMORY;
744 goto free_and_return;
746 malloc_canonbuf = true;
748 canon = (*pat)->name = memcpy (canonbuf, air->canon,
752 if (air->family[i] == AF_INET
753 && req->ai_family == AF_INET6
754 && (req->ai_flags & AI_V4MAPPED))
756 (*pat)->family = AF_INET6;
757 pataddr[3] = *(uint32_t *) addrs;
758 pataddr[2] = htonl (0xffff);
761 pat = &((*pat)->next);
764 else if (req->ai_family == AF_UNSPEC
765 || air->family[i] == req->ai_family)
767 (*pat)->family = air->family[i];
768 memcpy (pataddr, addrs, size);
769 pat = &((*pat)->next);
771 if (air->family[i] == AF_INET6)
779 if (at->family == AF_UNSPEC)
781 result = -EAI_NONAME;
782 goto free_and_return;
788 /* The database contains a negative entry. */
789 goto free_and_return;
790 else if (__nss_not_use_nscd_hosts == 0)
792 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
793 result = -EAI_MEMORY;
794 else if (herrno == TRY_AGAIN)
797 result = -EAI_SYSTEM;
799 goto free_and_return;
804 if (__nss_hosts_database == NULL)
805 no_more = __nss_database_lookup ("hosts", NULL,
806 "dns [!UNAVAIL=return] files",
807 &__nss_hosts_database);
810 nip = __nss_hosts_database;
812 /* Initialize configurations. */
813 if (__glibc_unlikely (!_res_hconf.initialized))
815 if (__res_maybe_init (&_res, 0) == -1)
818 /* If we are looking for both IPv4 and IPv6 address we don't
819 want the lookup functions to automatically promote IPv4
820 addresses to IPv6 addresses. Currently this is decided
821 by setting the RES_USE_INET6 bit in _res.options. */
822 old_res_options = _res.options;
823 _res.options &= ~RES_USE_INET6;
825 size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
826 malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
827 assert (tmpbuf == NULL);
829 tmpbuf = alloca_account (tmpbuflen, alloca_used);
832 tmpbuf = malloc (tmpbuflen);
835 _res.options |= old_res_options & RES_USE_INET6;
836 result = -EAI_MEMORY;
837 goto free_and_return;
844 nss_gethostbyname4_r fct4 = NULL;
846 /* gethostbyname4_r sends out parallel A and AAAA queries and
847 is thus only suitable for PF_UNSPEC. */
848 if (req->ai_family == PF_UNSPEC)
849 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
858 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
859 tmpbuflen, &rc, &herrno,
861 if (status == NSS_STATUS_SUCCESS)
863 if (status != NSS_STATUS_TRYAGAIN
864 || rc != ERANGE || herrno != NETDB_INTERNAL)
866 if (status == NSS_STATUS_TRYAGAIN
867 && herrno == TRY_AGAIN)
870 no_data = herrno == NO_DATA;
875 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
876 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
881 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
885 _res.options |= old_res_options & RES_USE_INET6;
886 result = -EAI_MEMORY;
887 goto free_and_return;
890 malloc_tmpbuf = true;
891 tmpbuflen = 2 * tmpbuflen;
895 if (status == NSS_STATUS_SUCCESS)
900 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
901 canon = (*pat)->name;
905 if ((*pat)->family == AF_INET
906 && req->ai_family == AF_INET6
907 && (req->ai_flags & AI_V4MAPPED) != 0)
909 uint32_t *pataddr = (*pat)->addr;
910 (*pat)->family = AF_INET6;
911 pataddr[3] = pataddr[0];
912 pataddr[2] = htonl (0xffff);
915 pat = &((*pat)->next);
918 else if (req->ai_family == AF_UNSPEC
919 || (*pat)->family == req->ai_family)
921 pat = &((*pat)->next);
924 if (req->ai_family == AF_INET6)
928 *pat = ((*pat)->next);
932 no_inet6_data = no_data;
936 nss_gethostbyname3_r fct = NULL;
937 if (req->ai_flags & AI_CANONNAME)
938 /* No need to use this function if we do not look for
939 the canonical name. The function does not exist in
940 all NSS modules and therefore the lookup would
942 fct = __nss_lookup_function (nip, "gethostbyname3_r");
944 /* We are cheating here. The gethostbyname2_r
945 function does not have the same interface as
946 gethostbyname3_r but the extra arguments the
947 latter takes are added at the end. So the
948 gethostbyname2_r code will just ignore them. */
949 fct = __nss_lookup_function (nip, "gethostbyname2_r");
953 if (req->ai_family == AF_INET6
954 || req->ai_family == AF_UNSPEC)
956 gethosts (AF_INET6, struct in6_addr);
957 no_inet6_data = no_data;
958 inet6_status = status;
960 if (req->ai_family == AF_INET
961 || req->ai_family == AF_UNSPEC
962 || (req->ai_family == AF_INET6
963 && (req->ai_flags & AI_V4MAPPED)
964 /* Avoid generating the mapped addresses if we
965 know we are not going to need them. */
966 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
968 gethosts (AF_INET, struct in_addr);
970 if (req->ai_family == AF_INET)
972 no_inet6_data = no_data;
973 inet6_status = status;
977 /* If we found one address for AF_INET or AF_INET6,
978 don't continue the search. */
979 if (inet6_status == NSS_STATUS_SUCCESS
980 || status == NSS_STATUS_SUCCESS)
982 if ((req->ai_flags & AI_CANONNAME) != 0
985 /* If we need the canonical name, get it
986 from the same service as the result. */
987 nss_getcanonname_r cfct;
990 cfct = __nss_lookup_function (nip,
994 const size_t max_fqdn_len = 256;
995 if ((req->ai_flags & AI_CANONIDN) != 0
996 && __libc_use_alloca (alloca_used
998 canonbuf = alloca_account (max_fqdn_len,
1002 canonbuf = malloc (max_fqdn_len);
1003 if (canonbuf == NULL)
1006 |= old_res_options & RES_USE_INET6;
1007 result = -EAI_MEMORY;
1008 goto free_and_return;
1010 malloc_canonbuf = true;
1014 if (DL_CALL_FCT (cfct, (at->name ?: name,
1018 == NSS_STATUS_SUCCESS)
1022 /* If the canonical name cannot be
1023 determined, use the passed in
1025 if (malloc_canonbuf)
1028 malloc_canonbuf = false;
1034 status = NSS_STATUS_SUCCESS;
1038 /* We can have different states for AF_INET and
1039 AF_INET6. Try to find a useful one for both. */
1040 if (inet6_status == NSS_STATUS_TRYAGAIN)
1041 status = NSS_STATUS_TRYAGAIN;
1042 else if (status == NSS_STATUS_UNAVAIL
1043 && inet6_status != NSS_STATUS_UNAVAIL)
1044 status = inet6_status;
1049 status = NSS_STATUS_UNAVAIL;
1050 /* Could not load any of the lookup functions. Indicate
1051 an internal error if the failure was due to a system
1052 error other than the file not being found. We use the
1053 errno from the last failed callback. */
1054 if (errno != 0 && errno != ENOENT)
1055 __set_h_errno (NETDB_INTERNAL);
1059 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1062 if (nip->next == NULL)
1068 _res.options |= old_res_options & RES_USE_INET6;
1070 if (h_errno == NETDB_INTERNAL)
1072 result = -EAI_SYSTEM;
1073 goto free_and_return;
1076 if (no_data != 0 && no_inet6_data != 0)
1078 /* If both requests timed out report this. */
1079 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1080 result = -EAI_AGAIN;
1082 /* We made requests but they turned out no data. The name
1083 is known, though. */
1084 result = -EAI_NODATA;
1086 goto free_and_return;
1091 if (at->family == AF_UNSPEC)
1093 result = -EAI_NONAME;
1094 goto free_and_return;
1099 struct gaih_addrtuple *atr;
1100 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1101 memset (at, '\0', sizeof (struct gaih_addrtuple));
1103 if (req->ai_family == AF_UNSPEC)
1105 at->next = __alloca (sizeof (struct gaih_addrtuple));
1106 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1109 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1111 at->family = AF_INET6;
1112 if ((req->ai_flags & AI_PASSIVE) == 0)
1113 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1117 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1119 atr->family = AF_INET;
1120 if ((req->ai_flags & AI_PASSIVE) == 0)
1121 atr->addr[0] = htonl (INADDR_LOOPBACK);
1126 struct gaih_servtuple *st2;
1127 struct gaih_addrtuple *at2 = at;
1132 buffer is the size of an unformatted IPv6 address in printable format.
1136 /* Only the first entry gets the canonical name. */
1137 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1140 /* If the canonical name cannot be determined, use
1141 the passed in string. */
1145 if (req->ai_flags & AI_CANONIDN)
1148 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1149 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1150 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1151 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1154 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1155 if (rc != IDNA_SUCCESS)
1157 if (rc == IDNA_MALLOC_ERROR)
1158 result = -EAI_MEMORY;
1159 else if (rc == IDNA_DLOPEN_ERROR)
1160 result = -EAI_SYSTEM;
1162 result = -EAI_IDN_ENCODE;
1163 goto free_and_return;
1165 /* In case the output string is the same as the input
1166 string no new string has been allocated and we
1178 if (malloc_canonbuf)
1179 /* We already allocated the string using malloc. */
1180 malloc_canonbuf = false;
1183 canon = strdup (canon);
1186 result = -EAI_MEMORY;
1187 goto free_and_return;
1193 family = at2->family;
1194 if (family == AF_INET6)
1196 socklen = sizeof (struct sockaddr_in6);
1198 /* If we looked up IPv4 mapped address discard them here if
1199 the caller isn't interested in all address and we have
1200 found at least one IPv6 address. */
1202 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1203 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1207 socklen = sizeof (struct sockaddr_in);
1209 for (st2 = st; st2 != NULL; st2 = st2->next)
1211 struct addrinfo *ai;
1212 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1215 free ((char *) canon);
1216 result = -EAI_MEMORY;
1217 goto free_and_return;
1220 ai->ai_flags = req->ai_flags;
1221 ai->ai_family = family;
1222 ai->ai_socktype = st2->socktype;
1223 ai->ai_protocol = st2->protocol;
1224 ai->ai_addrlen = socklen;
1225 ai->ai_addr = (void *) (ai + 1);
1227 /* We only add the canonical name once. */
1228 ai->ai_canonname = (char *) canon;
1232 ai->ai_addr->sa_len = socklen;
1233 #endif /* _HAVE_SA_LEN */
1234 ai->ai_addr->sa_family = family;
1236 /* In case of an allocation error the list must be NULL
1240 if (family == AF_INET6)
1242 struct sockaddr_in6 *sin6p =
1243 (struct sockaddr_in6 *) ai->ai_addr;
1245 sin6p->sin6_port = st2->port;
1246 sin6p->sin6_flowinfo = 0;
1247 memcpy (&sin6p->sin6_addr,
1248 at2->addr, sizeof (struct in6_addr));
1249 sin6p->sin6_scope_id = at2->scopeid;
1253 struct sockaddr_in *sinp =
1254 (struct sockaddr_in *) ai->ai_addr;
1255 sinp->sin_port = st2->port;
1256 memcpy (&sinp->sin_addr,
1257 at2->addr, sizeof (struct in_addr));
1258 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1261 pai = &(ai->ai_next);
1273 free ((char *) name);
1276 if (malloc_canonbuf)
1287 struct addrinfo *dest_addr;
1288 /* Using sockaddr_storage is for now overkill. We only support IPv4
1289 and IPv6 so far. If this changes at some point we can adjust the
1291 struct sockaddr_in6 source_addr;
1292 uint8_t source_addr_len;
1293 bool got_source_addr;
1294 uint8_t source_addr_flags;
1300 struct sort_result_combo
1302 struct sort_result *results;
1307 #if __BYTE_ORDER == __BIG_ENDIAN
1308 # define htonl_c(n) n
1310 # define htonl_c(n) __bswap_constant_32 (n)
1313 static const struct scopeentry
1322 } default_scopes[] =
1324 /* Link-local addresses: scope 2. */
1325 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1326 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1327 /* Default: scope 14. */
1328 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1331 /* The label table. */
1332 static const struct scopeentry *scopes;
1336 get_scope (const struct sockaddr_in6 *in6)
1339 if (in6->sin6_family == PF_INET6)
1341 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1343 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1344 /* RFC 4291 2.5.3 says that the loopback address is to be
1345 treated like a link-local address. */
1346 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1348 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1351 /* XXX Is this the correct default behavior? */
1355 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1357 else if (in6->sin6_family == PF_INET)
1359 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1364 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1365 == scopes[cnt].addr32)
1366 return scopes[cnt].scope;
1373 /* XXX What is a good default? */
1382 struct in6_addr prefix;
1388 /* The label table. */
1389 static const struct prefixentry *labels;
1391 /* Default labels. */
1392 static const struct prefixentry default_labels[] =
1394 /* See RFC 3484 for the details. */
1396 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1400 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1404 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1408 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1409 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1411 /* The next two entries differ from RFC 3484. We need to treat
1412 IPv6 site-local addresses special because they are never NATed,
1413 unlike site-locale IPv4 addresses. If this would not happen, on
1414 machines which have only IPv4 and IPv6 site-local addresses, the
1415 sorting would prefer the IPv6 site-local addresses, causing
1416 unnecessary delays when trying to connect to a global IPv6 address
1417 through a site-local IPv6 address. */
1419 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1423 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1426 /* Additional rule for Teredo tunnels. */
1428 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1432 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1438 /* The precedence table. */
1439 static const struct prefixentry *precedence;
1441 /* The default precedences. */
1442 static const struct prefixentry default_precedence[] =
1444 /* See RFC 3484 for the details. */
1446 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1450 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1454 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1458 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1459 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1462 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1469 match_prefix (const struct sockaddr_in6 *in6,
1470 const struct prefixentry *list, int default_val)
1473 struct sockaddr_in6 in6_mem;
1475 if (in6->sin6_family == PF_INET)
1477 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1479 /* Construct a V4-to-6 mapped address. */
1480 in6_mem.sin6_family = PF_INET6;
1481 in6_mem.sin6_port = in->sin_port;
1482 in6_mem.sin6_flowinfo = 0;
1483 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1484 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1485 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1486 in6_mem.sin6_scope_id = 0;
1490 else if (in6->sin6_family != PF_INET6)
1493 for (idx = 0; ; ++idx)
1495 unsigned int bits = list[idx].bits;
1496 const uint8_t *mask = list[idx].prefix.s6_addr;
1497 const uint8_t *val = in6->sin6_addr.s6_addr;
1511 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1517 return list[idx].val;
1522 get_label (const struct sockaddr_in6 *in6)
1524 /* XXX What is a good default value? */
1525 return match_prefix (in6, labels, INT_MAX);
1530 get_precedence (const struct sockaddr_in6 *in6)
1532 /* XXX What is a good default value? */
1533 return match_prefix (in6, precedence, 0);
1537 /* Find last bit set in a word. */
1543 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1544 if ((a & mask) != 0)
1551 rfc3484_sort (const void *p1, const void *p2, void *arg)
1553 const size_t idx1 = *(const size_t *) p1;
1554 const size_t idx2 = *(const size_t *) p2;
1555 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1556 struct sort_result *a1 = &src->results[idx1];
1557 struct sort_result *a2 = &src->results[idx2];
1559 /* Rule 1: Avoid unusable destinations.
1560 We have the got_source_addr flag set if the destination is reachable. */
1561 if (a1->got_source_addr && ! a2->got_source_addr)
1563 if (! a1->got_source_addr && a2->got_source_addr)
1567 /* Rule 2: Prefer matching scope. Only interesting if both
1568 destination addresses are IPv6. */
1570 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1573 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1575 if (a1->got_source_addr)
1577 int a1_src_scope = get_scope (&a1->source_addr);
1578 int a2_src_scope = get_scope (&a2->source_addr);
1580 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1582 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1587 /* Rule 3: Avoid deprecated addresses. */
1588 if (a1->got_source_addr)
1590 if (!(a1->source_addr_flags & in6ai_deprecated)
1591 && (a2->source_addr_flags & in6ai_deprecated))
1593 if ((a1->source_addr_flags & in6ai_deprecated)
1594 && !(a2->source_addr_flags & in6ai_deprecated))
1598 /* Rule 4: Prefer home addresses. */
1599 if (a1->got_source_addr)
1601 if (!(a1->source_addr_flags & in6ai_homeaddress)
1602 && (a2->source_addr_flags & in6ai_homeaddress))
1604 if ((a1->source_addr_flags & in6ai_homeaddress)
1605 && !(a2->source_addr_flags & in6ai_homeaddress))
1609 /* Rule 5: Prefer matching label. */
1610 if (a1->got_source_addr)
1613 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1614 int a1_src_label = get_label (&a1->source_addr);
1617 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1618 int a2_src_label = get_label (&a2->source_addr);
1620 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1622 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1627 /* Rule 6: Prefer higher precedence. */
1629 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1631 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1633 if (a1_prec > a2_prec)
1635 if (a1_prec < a2_prec)
1639 /* Rule 7: Prefer native transport. */
1640 if (a1->got_source_addr)
1642 /* The same interface index means the same interface which means
1643 there is no difference in transport. This should catch many
1645 if (a1->index != a2->index)
1647 int a1_native = a1->native;
1648 int a2_native = a2->native;
1650 if (a1_native == -1 || a2_native == -1)
1653 if (a1_native == -1)
1655 /* If we do not have the information use 'native' as
1658 a1_index = a1->index;
1661 a1_index = 0xffffffffu;
1664 if (a2_native == -1)
1666 /* If we do not have the information use 'native' as
1669 a2_index = a2->index;
1672 a2_index = 0xffffffffu;
1674 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1676 /* Fill in the results in all the records. */
1677 for (int i = 0; i < src->nresults; ++i)
1678 if (a1_index != -1 && src->results[i].index == a1_index)
1680 assert (src->results[i].native == -1
1681 || src->results[i].native == a1_native);
1682 src->results[i].native = a1_native;
1684 else if (a2_index != -1 && src->results[i].index == a2_index)
1686 assert (src->results[i].native == -1
1687 || src->results[i].native == a2_native);
1688 src->results[i].native = a2_native;
1692 if (a1_native && !a2_native)
1694 if (!a1_native && a2_native)
1700 /* Rule 8: Prefer smaller scope. */
1701 if (a1_dst_scope < a2_dst_scope)
1703 if (a1_dst_scope > a2_dst_scope)
1707 /* Rule 9: Use longest matching prefix. */
1708 if (a1->got_source_addr
1709 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1714 if (a1->dest_addr->ai_family == PF_INET)
1716 assert (a1->source_addr.sin6_family == PF_INET);
1717 assert (a2->source_addr.sin6_family == PF_INET);
1719 /* Outside of subnets, as defined by the network masks,
1720 common address prefixes for IPv4 addresses make no sense.
1721 So, define a non-zero value only if source and
1722 destination address are on the same subnet. */
1723 struct sockaddr_in *in1_dst
1724 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1725 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1726 struct sockaddr_in *in1_src
1727 = (struct sockaddr_in *) &a1->source_addr;
1728 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1729 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1731 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1732 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1734 struct sockaddr_in *in2_dst
1735 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1736 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1737 struct sockaddr_in *in2_src
1738 = (struct sockaddr_in *) &a2->source_addr;
1739 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1740 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1742 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1743 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1745 else if (a1->dest_addr->ai_family == PF_INET6)
1747 assert (a1->source_addr.sin6_family == PF_INET6);
1748 assert (a2->source_addr.sin6_family == PF_INET6);
1750 struct sockaddr_in6 *in1_dst;
1751 struct sockaddr_in6 *in1_src;
1752 struct sockaddr_in6 *in2_dst;
1753 struct sockaddr_in6 *in2_src;
1755 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1756 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1757 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1758 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1761 for (i = 0; i < 4; ++i)
1762 if (in1_dst->sin6_addr.s6_addr32[i]
1763 != in1_src->sin6_addr.s6_addr32[i]
1764 || (in2_dst->sin6_addr.s6_addr32[i]
1765 != in2_src->sin6_addr.s6_addr32[i]))
1770 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1771 ^ in1_src->sin6_addr.s6_addr32[i]));
1772 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1773 ^ in2_src->sin6_addr.s6_addr32[i]));
1784 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1785 compare with the value indicating the order in which the entries
1786 have been received from the services. NB: no two entries can have
1787 the same order so the test will never return zero. */
1788 return idx1 < idx2 ? -1 : 1;
1793 in6aicmp (const void *p1, const void *p2)
1795 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1796 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1798 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1802 /* Name of the config file for RFC 3484 sorting (for now). */
1803 #define GAICONF_FNAME "/etc/gai.conf"
1806 /* Non-zero if we are supposed to reload the config file automatically
1807 whenever it changed. */
1808 static int gaiconf_reload_flag;
1810 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1811 static int gaiconf_reload_flag_ever_set;
1813 /* Last modification time. */
1814 #ifdef _STATBUF_ST_NSEC
1816 static struct timespec gaiconf_mtime;
1819 save_gaiconf_mtime (const struct stat64 *st)
1821 gaiconf_mtime = st->st_mtim;
1825 check_gaiconf_mtime (const struct stat64 *st)
1827 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1828 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1833 static time_t gaiconf_mtime;
1836 save_gaiconf_mtime (const struct stat64 *st)
1838 gaiconf_mtime = st->st_mtime;
1842 check_gaiconf_mtime (const struct stat64 *st)
1844 return st->st_mtime == gaiconf_mtime;
1850 libc_freeres_fn(fini)
1852 if (labels != default_labels)
1854 const struct prefixentry *old = labels;
1855 labels = default_labels;
1856 free ((void *) old);
1859 if (precedence != default_precedence)
1861 const struct prefixentry *old = precedence;
1862 precedence = default_precedence;
1863 free ((void *) old);
1866 if (scopes != default_scopes)
1868 const struct scopeentry *old = scopes;
1869 scopes = default_scopes;
1870 free ((void *) old);
1877 struct prefixentry entry;
1878 struct prefixlist *next;
1884 struct scopeentry entry;
1885 struct scopelist *next;
1890 free_prefixlist (struct prefixlist *list)
1892 while (list != NULL)
1894 struct prefixlist *oldp = list;
1902 free_scopelist (struct scopelist *list)
1904 while (list != NULL)
1906 struct scopelist *oldp = list;
1914 prefixcmp (const void *p1, const void *p2)
1916 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1917 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1919 if (e1->bits < e2->bits)
1921 if (e1->bits == e2->bits)
1928 scopecmp (const void *p1, const void *p2)
1930 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1931 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1933 if (e1->netmask > e2->netmask)
1935 if (e1->netmask == e2->netmask)
1944 struct prefixlist *labellist = NULL;
1945 size_t nlabellist = 0;
1946 bool labellist_nullbits = false;
1947 struct prefixlist *precedencelist = NULL;
1948 size_t nprecedencelist = 0;
1949 bool precedencelist_nullbits = false;
1950 struct scopelist *scopelist = NULL;
1951 size_t nscopelist = 0;
1952 bool scopelist_nullbits = false;
1954 FILE *fp = fopen (GAICONF_FNAME, "rce");
1958 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1967 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1969 while (!feof_unlocked (fp))
1971 ssize_t n = __getline (&line, &linelen, fp);
1975 /* Handle comments. No escaping possible so this is easy. */
1976 char *cp = strchr (line, '#');
1981 while (isspace (*cp))
1985 while (*cp != '\0' && !isspace (*cp))
1987 size_t cmdlen = cp - cmd;
1991 while (isspace (*cp))
1995 while (*cp != '\0' && !isspace (*cp))
1997 size_t val1len = cp - cmd;
1999 /* We always need at least two values. */
2005 while (isspace (*cp))
2009 while (*cp != '\0' && !isspace (*cp))
2012 /* Ignore the rest of the line. */
2015 struct prefixlist **listp;
2021 if (strcmp (cmd, "label") == 0)
2023 struct in6_addr prefix;
2024 unsigned long int bits;
2025 unsigned long int val;
2030 nullbitsp = &labellist_nullbits;
2035 cp = strchr (val1, '/');
2038 if (inet_pton (AF_INET6, val1, &prefix)
2040 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2044 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2049 struct prefixlist *newp = malloc (sizeof (*newp));
2057 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2058 newp->entry.bits = bits;
2059 newp->entry.val = val;
2060 newp->next = *listp;
2063 *nullbitsp |= bits == 0;
2069 if (strcmp (cmd, "reload") == 0)
2071 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2072 if (gaiconf_reload_flag)
2073 gaiconf_reload_flag_ever_set = 1;
2078 if (strcmp (cmd, "scopev4") == 0)
2080 struct in6_addr prefix;
2081 unsigned long int bits;
2082 unsigned long int val;
2087 cp = strchr (val1, '/');
2090 if (inet_pton (AF_INET6, val1, &prefix))
2093 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2095 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2100 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2105 struct scopelist *newp;
2107 newp = malloc (sizeof (*newp));
2115 newp->entry.netmask = htonl (bits != 96
2119 newp->entry.addr32 = (prefix.s6_addr32[3]
2120 & newp->entry.netmask);
2121 newp->entry.scope = val;
2122 newp->next = scopelist;
2125 scopelist_nullbits |= bits == 96;
2128 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2130 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2134 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2146 if (strcmp (cmd, "precedence") == 0)
2148 listp = &precedencelist;
2149 lenp = &nprecedencelist;
2150 nullbitsp = &precedencelist_nullbits;
2161 /* Create the array for the labels. */
2162 struct prefixentry *new_labels;
2165 if (!labellist_nullbits)
2167 new_labels = malloc (nlabellist * sizeof (*new_labels));
2168 if (new_labels == NULL)
2172 if (!labellist_nullbits)
2175 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2176 new_labels[i].bits = 0;
2177 new_labels[i].val = 1;
2180 struct prefixlist *l = labellist;
2183 new_labels[i] = l->entry;
2186 free_prefixlist (labellist);
2188 /* Sort the entries so that the most specific ones are at
2190 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2193 new_labels = (struct prefixentry *) default_labels;
2195 struct prefixentry *new_precedence;
2196 if (nprecedencelist > 0)
2198 if (!precedencelist_nullbits)
2200 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2201 if (new_precedence == NULL)
2203 if (new_labels != default_labels)
2208 int i = nprecedencelist;
2209 if (!precedencelist_nullbits)
2212 memset (&new_precedence[i].prefix, '\0',
2213 sizeof (struct in6_addr));
2214 new_precedence[i].bits = 0;
2215 new_precedence[i].val = 40;
2218 struct prefixlist *l = precedencelist;
2221 new_precedence[i] = l->entry;
2224 free_prefixlist (precedencelist);
2226 /* Sort the entries so that the most specific ones are at
2228 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2232 new_precedence = (struct prefixentry *) default_precedence;
2234 struct scopeentry *new_scopes;
2237 if (!scopelist_nullbits)
2239 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2240 if (new_scopes == NULL)
2242 if (new_labels != default_labels)
2244 if (new_precedence != default_precedence)
2245 free (new_precedence);
2250 if (!scopelist_nullbits)
2253 new_scopes[i].addr32 = 0;
2254 new_scopes[i].netmask = 0;
2255 new_scopes[i].scope = 14;
2258 struct scopelist *l = scopelist;
2261 new_scopes[i] = l->entry;
2264 free_scopelist (scopelist);
2266 /* Sort the entries so that the most specific ones are at
2268 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2272 new_scopes = (struct scopeentry *) default_scopes;
2274 /* Now we are ready to replace the values. */
2275 const struct prefixentry *old = labels;
2276 labels = new_labels;
2277 if (old != default_labels)
2278 free ((void *) old);
2281 precedence = new_precedence;
2282 if (old != default_precedence)
2283 free ((void *) old);
2285 const struct scopeentry *oldscope = scopes;
2286 scopes = new_scopes;
2287 if (oldscope != default_scopes)
2288 free ((void *) oldscope);
2290 save_gaiconf_mtime (&st);
2295 free_prefixlist (labellist);
2296 free_prefixlist (precedencelist);
2297 free_scopelist (scopelist);
2299 /* If we previously read the file but it is gone now, free the
2300 old data and use the builtin one. Leave the reload flag
2308 gaiconf_reload (void)
2311 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2312 || !check_gaiconf_mtime (&st))
2318 getaddrinfo (const char *name, const char *service,
2319 const struct addrinfo *hints, struct addrinfo **pai)
2321 int i = 0, last_i = 0;
2323 struct addrinfo *p = NULL;
2324 struct gaih_service gaih_service, *pservice;
2325 struct addrinfo local_hints;
2327 if (name != NULL && name[0] == '*' && name[1] == 0)
2330 if (service != NULL && service[0] == '*' && service[1] == 0)
2333 if (name == NULL && service == NULL)
2337 hints = &default_hints;
2340 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2342 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2343 |AI_IDN_USE_STD3_ASCII_RULES
2345 |AI_NUMERICSERV|AI_ALL))
2346 return EAI_BADFLAGS;
2348 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2349 return EAI_BADFLAGS;
2351 struct in6addrinfo *in6ai = NULL;
2352 size_t in6ailen = 0;
2353 bool seen_ipv4 = false;
2354 bool seen_ipv6 = false;
2355 bool check_pf_called = false;
2357 if (hints->ai_flags & AI_ADDRCONFIG)
2359 /* We might need information about what interfaces are available.
2360 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2361 cannot cache the results since new interfaces could be added at
2363 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2364 check_pf_called = true;
2366 /* Now make a decision on what we return, if anything. */
2367 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2369 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2370 narrow down the search. */
2371 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2373 local_hints = *hints;
2374 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2375 hints = &local_hints;
2378 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2379 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2381 /* We cannot possibly return a valid answer. */
2382 __free_in6ai (in6ai);
2387 if (service && service[0])
2390 gaih_service.name = service;
2391 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2394 if (hints->ai_flags & AI_NUMERICSERV)
2396 __free_in6ai (in6ai);
2400 gaih_service.num = -1;
2403 pservice = &gaih_service;
2408 struct addrinfo **end = &p;
2410 unsigned int naddrs = 0;
2411 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2412 || hints->ai_family == AF_INET6)
2414 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2418 __free_in6ai (in6ai);
2424 end = &((*end)->ai_next);
2430 __free_in6ai (in6ai);
2436 /* Read the config file. */
2437 __libc_once_define (static, once);
2438 __typeof (once) old_once = once;
2439 __libc_once (once, gaiconf_init);
2440 /* Sort results according to RFC 3484. */
2441 struct sort_result *results;
2444 struct addrinfo *last = NULL;
2445 char *canonname = NULL;
2446 bool malloc_results;
2447 size_t alloc_size = nresults * (sizeof (*results) + sizeof (size_t));
2450 = !__libc_use_alloca (alloc_size);
2453 results = malloc (alloc_size);
2454 if (results == NULL)
2456 __free_in6ai (in6ai);
2461 results = alloca (alloc_size);
2462 order = (size_t *) (results + nresults);
2464 /* Now we definitely need the interface information. */
2465 if (! check_pf_called)
2466 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2468 /* If we have information about deprecated and temporary addresses
2469 sort the array now. */
2471 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2476 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2478 results[i].dest_addr = q;
2479 results[i].native = -1;
2482 /* If we just looked up the address for a different
2483 protocol, reuse the result. */
2484 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2485 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2487 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2488 results[i - 1].source_addr_len);
2489 results[i].source_addr_len = results[i - 1].source_addr_len;
2490 results[i].got_source_addr = results[i - 1].got_source_addr;
2491 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2492 results[i].prefixlen = results[i - 1].prefixlen;
2493 results[i].index = results[i - 1].index;
2497 results[i].got_source_addr = false;
2498 results[i].source_addr_flags = 0;
2499 results[i].prefixlen = 0;
2500 results[i].index = 0xffffffffu;
2502 /* We overwrite the type with SOCK_DGRAM since we do not
2503 want connect() to connect to the other side. If we
2504 cannot determine the source address remember this
2506 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2510 close_not_cancel_no_status (fd);
2512 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2516 /* Reset the connection. */
2517 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2518 __connect (fd, &sa, sizeof (sa));
2521 socklen_t sl = sizeof (results[i].source_addr);
2523 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2524 && __getsockname (fd,
2525 (struct sockaddr *) &results[i].source_addr,
2528 results[i].source_addr_len = sl;
2529 results[i].got_source_addr = true;
2533 /* See whether the source address is on the list of
2534 deprecated or temporary addresses. */
2535 struct in6addrinfo tmp;
2537 if (q->ai_family == AF_INET && af == AF_INET)
2539 struct sockaddr_in *sinp
2540 = (struct sockaddr_in *) &results[i].source_addr;
2543 tmp.addr[2] = htonl (0xffff);
2544 /* Special case for lo interface, the source address
2545 being possibly different than the interface
2547 if ((ntohl(sinp->sin_addr.s_addr) & 0xff000000)
2549 tmp.addr[3] = htonl(0x7f000001);
2551 tmp.addr[3] = sinp->sin_addr.s_addr;
2555 struct sockaddr_in6 *sin6p
2556 = (struct sockaddr_in6 *) &results[i].source_addr;
2557 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2560 struct in6addrinfo *found
2561 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2565 results[i].source_addr_flags = found->flags;
2566 results[i].prefixlen = found->prefixlen;
2567 results[i].index = found->index;
2571 if (q->ai_family == AF_INET && af == AF_INET6)
2573 /* We have to convert the address. The socket is
2574 IPv6 and the request is for IPv4. */
2575 struct sockaddr_in6 *sin6
2576 = (struct sockaddr_in6 *) &results[i].source_addr;
2577 struct sockaddr_in *sin
2578 = (struct sockaddr_in *) &results[i].source_addr;
2579 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2580 sin->sin_family = AF_INET;
2581 /* We do not have to initialize sin_port since this
2582 fields has the same position and size in the IPv6
2584 assert (offsetof (struct sockaddr_in, sin_port)
2585 == offsetof (struct sockaddr_in6, sin6_port));
2586 assert (sizeof (sin->sin_port)
2587 == sizeof (sin6->sin6_port));
2588 memcpy (&sin->sin_addr,
2589 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2590 results[i].source_addr_len = sizeof (struct sockaddr_in);
2593 else if (errno == EAFNOSUPPORT && af == AF_INET6
2594 && q->ai_family == AF_INET)
2595 /* This could mean IPv6 sockets are IPv6-only. */
2598 /* Just make sure that if we have to process the same
2599 address again we do not copy any memory. */
2600 results[i].source_addr_len = 0;
2603 /* Remember the canonical name. */
2604 if (q->ai_canonname != NULL)
2606 assert (canonname == NULL);
2607 canonname = q->ai_canonname;
2608 q->ai_canonname = NULL;
2613 close_not_cancel_no_status (fd);
2615 /* We got all the source addresses we can get, now sort using
2617 struct sort_result_combo src
2618 = { .results = results, .nresults = nresults };
2619 if (__glibc_unlikely (gaiconf_reload_flag_ever_set))
2621 __libc_lock_define_initialized (static, lock);
2623 __libc_lock_lock (lock);
2624 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2626 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2627 __libc_lock_unlock (lock);
2630 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2632 /* Queue the results up as they come out of sorting. */
2633 q = p = results[order[0]].dest_addr;
2634 for (i = 1; i < nresults; ++i)
2635 q = q->ai_next = results[order[i]].dest_addr;
2638 /* Fill in the canonical name into the new first entry. */
2639 p->ai_canonname = canonname;
2645 __free_in6ai (in6ai);
2653 return last_i ? -last_i : EAI_NONAME;
2655 libc_hidden_def (getaddrinfo)
2657 nss_interface_function (getaddrinfo)
2660 freeaddrinfo (struct addrinfo *ai)
2668 free (p->ai_canonname);
2672 libc_hidden_def (freeaddrinfo)