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 socklen_t size = (air->family[i] == AF_INET
714 ? INADDRSZ : IN6ADDRSZ);
716 if (!((air->family[i] == AF_INET
717 && req->ai_family == AF_INET6
718 && (req->ai_flags & AI_V4MAPPED) != 0)
719 || req->ai_family == AF_UNSPEC
720 || air->family[i] == req->ai_family))
722 /* Skip over non-matching result. */
732 uint32_t *pataddr = (*pat)->addr;
734 if (added_canon || air->canon == NULL)
736 else if (canonbuf == NULL)
738 size_t canonlen = strlen (air->canon) + 1;
739 if ((req->ai_flags & AI_CANONIDN) != 0
740 && __libc_use_alloca (alloca_used + canonlen))
741 canonbuf = alloca_account (canonlen, alloca_used);
744 canonbuf = malloc (canonlen);
745 if (canonbuf == NULL)
747 result = -EAI_MEMORY;
748 goto free_and_return;
750 malloc_canonbuf = true;
752 canon = (*pat)->name = memcpy (canonbuf, air->canon,
756 if (air->family[i] == AF_INET
757 && req->ai_family == AF_INET6
758 && (req->ai_flags & AI_V4MAPPED))
760 (*pat)->family = AF_INET6;
761 pataddr[3] = *(uint32_t *) addrs;
762 pataddr[2] = htonl (0xffff);
765 pat = &((*pat)->next);
768 else if (req->ai_family == AF_UNSPEC
769 || air->family[i] == req->ai_family)
771 (*pat)->family = air->family[i];
772 memcpy (pataddr, addrs, size);
773 pat = &((*pat)->next);
775 if (air->family[i] == AF_INET6)
783 if (at->family == AF_UNSPEC)
785 result = -EAI_NONAME;
786 goto free_and_return;
792 /* The database contains a negative entry. */
793 goto free_and_return;
794 else if (__nss_not_use_nscd_hosts == 0)
796 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
797 result = -EAI_MEMORY;
798 else if (herrno == TRY_AGAIN)
801 result = -EAI_SYSTEM;
803 goto free_and_return;
808 if (__nss_hosts_database == NULL)
809 no_more = __nss_database_lookup ("hosts", NULL,
810 "dns [!UNAVAIL=return] files",
811 &__nss_hosts_database);
814 nip = __nss_hosts_database;
816 /* Initialize configurations. */
817 if (__glibc_unlikely (!_res_hconf.initialized))
819 if (__res_maybe_init (&_res, 0) == -1)
822 /* If we are looking for both IPv4 and IPv6 address we don't
823 want the lookup functions to automatically promote IPv4
824 addresses to IPv6 addresses. Currently this is decided
825 by setting the RES_USE_INET6 bit in _res.options. */
826 old_res_options = _res.options;
827 _res.options &= ~RES_USE_INET6;
829 size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
830 malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
831 assert (tmpbuf == NULL);
833 tmpbuf = alloca_account (tmpbuflen, alloca_used);
836 tmpbuf = malloc (tmpbuflen);
839 _res.options |= old_res_options & RES_USE_INET6;
840 result = -EAI_MEMORY;
841 goto free_and_return;
848 nss_gethostbyname4_r fct4 = NULL;
850 /* gethostbyname4_r sends out parallel A and AAAA queries and
851 is thus only suitable for PF_UNSPEC. */
852 if (req->ai_family == PF_UNSPEC)
853 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
862 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
863 tmpbuflen, &rc, &herrno,
865 if (status == NSS_STATUS_SUCCESS)
867 if (status != NSS_STATUS_TRYAGAIN
868 || rc != ERANGE || herrno != NETDB_INTERNAL)
870 if (status == NSS_STATUS_TRYAGAIN
871 && herrno == TRY_AGAIN)
874 no_data = herrno == NO_DATA;
879 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
880 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
885 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
889 _res.options |= old_res_options & RES_USE_INET6;
890 result = -EAI_MEMORY;
891 goto free_and_return;
894 malloc_tmpbuf = true;
895 tmpbuflen = 2 * tmpbuflen;
899 if (status == NSS_STATUS_SUCCESS)
904 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
905 canon = (*pat)->name;
909 if ((*pat)->family == AF_INET
910 && req->ai_family == AF_INET6
911 && (req->ai_flags & AI_V4MAPPED) != 0)
913 uint32_t *pataddr = (*pat)->addr;
914 (*pat)->family = AF_INET6;
915 pataddr[3] = pataddr[0];
916 pataddr[2] = htonl (0xffff);
919 pat = &((*pat)->next);
922 else if (req->ai_family == AF_UNSPEC
923 || (*pat)->family == req->ai_family)
925 pat = &((*pat)->next);
928 if (req->ai_family == AF_INET6)
932 *pat = ((*pat)->next);
936 no_inet6_data = no_data;
940 nss_gethostbyname3_r fct = NULL;
941 if (req->ai_flags & AI_CANONNAME)
942 /* No need to use this function if we do not look for
943 the canonical name. The function does not exist in
944 all NSS modules and therefore the lookup would
946 fct = __nss_lookup_function (nip, "gethostbyname3_r");
948 /* We are cheating here. The gethostbyname2_r
949 function does not have the same interface as
950 gethostbyname3_r but the extra arguments the
951 latter takes are added at the end. So the
952 gethostbyname2_r code will just ignore them. */
953 fct = __nss_lookup_function (nip, "gethostbyname2_r");
957 if (req->ai_family == AF_INET6
958 || req->ai_family == AF_UNSPEC)
960 gethosts (AF_INET6, struct in6_addr);
961 no_inet6_data = no_data;
962 inet6_status = status;
964 if (req->ai_family == AF_INET
965 || req->ai_family == AF_UNSPEC
966 || (req->ai_family == AF_INET6
967 && (req->ai_flags & AI_V4MAPPED)
968 /* Avoid generating the mapped addresses if we
969 know we are not going to need them. */
970 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
972 gethosts (AF_INET, struct in_addr);
974 if (req->ai_family == AF_INET)
976 no_inet6_data = no_data;
977 inet6_status = status;
981 /* If we found one address for AF_INET or AF_INET6,
982 don't continue the search. */
983 if (inet6_status == NSS_STATUS_SUCCESS
984 || status == NSS_STATUS_SUCCESS)
986 if ((req->ai_flags & AI_CANONNAME) != 0
989 /* If we need the canonical name, get it
990 from the same service as the result. */
991 nss_getcanonname_r cfct;
994 cfct = __nss_lookup_function (nip,
998 const size_t max_fqdn_len = 256;
999 if ((req->ai_flags & AI_CANONIDN) != 0
1000 && __libc_use_alloca (alloca_used
1002 canonbuf = alloca_account (max_fqdn_len,
1006 canonbuf = malloc (max_fqdn_len);
1007 if (canonbuf == NULL)
1010 |= old_res_options & RES_USE_INET6;
1011 result = -EAI_MEMORY;
1012 goto free_and_return;
1014 malloc_canonbuf = true;
1018 if (DL_CALL_FCT (cfct, (at->name ?: name,
1022 == NSS_STATUS_SUCCESS)
1026 /* If the canonical name cannot be
1027 determined, use the passed in
1029 if (malloc_canonbuf)
1032 malloc_canonbuf = false;
1038 status = NSS_STATUS_SUCCESS;
1042 /* We can have different states for AF_INET and
1043 AF_INET6. Try to find a useful one for both. */
1044 if (inet6_status == NSS_STATUS_TRYAGAIN)
1045 status = NSS_STATUS_TRYAGAIN;
1046 else if (status == NSS_STATUS_UNAVAIL
1047 && inet6_status != NSS_STATUS_UNAVAIL)
1048 status = inet6_status;
1053 status = NSS_STATUS_UNAVAIL;
1054 /* Could not load any of the lookup functions. Indicate
1055 an internal error if the failure was due to a system
1056 error other than the file not being found. We use the
1057 errno from the last failed callback. */
1058 if (errno != 0 && errno != ENOENT)
1059 __set_h_errno (NETDB_INTERNAL);
1063 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1066 if (nip->next == NULL)
1072 _res.options |= old_res_options & RES_USE_INET6;
1074 if (h_errno == NETDB_INTERNAL)
1076 result = -EAI_SYSTEM;
1077 goto free_and_return;
1080 if (no_data != 0 && no_inet6_data != 0)
1082 /* If both requests timed out report this. */
1083 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1084 result = -EAI_AGAIN;
1086 /* We made requests but they turned out no data. The name
1087 is known, though. */
1088 result = -EAI_NODATA;
1090 goto free_and_return;
1095 if (at->family == AF_UNSPEC)
1097 result = -EAI_NONAME;
1098 goto free_and_return;
1103 struct gaih_addrtuple *atr;
1104 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1105 memset (at, '\0', sizeof (struct gaih_addrtuple));
1107 if (req->ai_family == AF_UNSPEC)
1109 at->next = __alloca (sizeof (struct gaih_addrtuple));
1110 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1113 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1115 at->family = AF_INET6;
1116 if ((req->ai_flags & AI_PASSIVE) == 0)
1117 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1121 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1123 atr->family = AF_INET;
1124 if ((req->ai_flags & AI_PASSIVE) == 0)
1125 atr->addr[0] = htonl (INADDR_LOOPBACK);
1130 struct gaih_servtuple *st2;
1131 struct gaih_addrtuple *at2 = at;
1136 buffer is the size of an unformatted IPv6 address in printable format.
1140 /* Only the first entry gets the canonical name. */
1141 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1144 /* If the canonical name cannot be determined, use
1145 the passed in string. */
1149 if (req->ai_flags & AI_CANONIDN)
1152 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1153 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1154 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1155 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1158 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1159 if (rc != IDNA_SUCCESS)
1161 if (rc == IDNA_MALLOC_ERROR)
1162 result = -EAI_MEMORY;
1163 else if (rc == IDNA_DLOPEN_ERROR)
1164 result = -EAI_SYSTEM;
1166 result = -EAI_IDN_ENCODE;
1167 goto free_and_return;
1169 /* In case the output string is the same as the input
1170 string no new string has been allocated and we
1182 if (malloc_canonbuf)
1183 /* We already allocated the string using malloc. */
1184 malloc_canonbuf = false;
1187 canon = strdup (canon);
1190 result = -EAI_MEMORY;
1191 goto free_and_return;
1197 family = at2->family;
1198 if (family == AF_INET6)
1200 socklen = sizeof (struct sockaddr_in6);
1202 /* If we looked up IPv4 mapped address discard them here if
1203 the caller isn't interested in all address and we have
1204 found at least one IPv6 address. */
1206 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1207 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1211 socklen = sizeof (struct sockaddr_in);
1213 for (st2 = st; st2 != NULL; st2 = st2->next)
1215 struct addrinfo *ai;
1216 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1219 free ((char *) canon);
1220 result = -EAI_MEMORY;
1221 goto free_and_return;
1224 ai->ai_flags = req->ai_flags;
1225 ai->ai_family = family;
1226 ai->ai_socktype = st2->socktype;
1227 ai->ai_protocol = st2->protocol;
1228 ai->ai_addrlen = socklen;
1229 ai->ai_addr = (void *) (ai + 1);
1231 /* We only add the canonical name once. */
1232 ai->ai_canonname = (char *) canon;
1236 ai->ai_addr->sa_len = socklen;
1237 #endif /* _HAVE_SA_LEN */
1238 ai->ai_addr->sa_family = family;
1240 /* In case of an allocation error the list must be NULL
1244 if (family == AF_INET6)
1246 struct sockaddr_in6 *sin6p =
1247 (struct sockaddr_in6 *) ai->ai_addr;
1249 sin6p->sin6_port = st2->port;
1250 sin6p->sin6_flowinfo = 0;
1251 memcpy (&sin6p->sin6_addr,
1252 at2->addr, sizeof (struct in6_addr));
1253 sin6p->sin6_scope_id = at2->scopeid;
1257 struct sockaddr_in *sinp =
1258 (struct sockaddr_in *) ai->ai_addr;
1259 sinp->sin_port = st2->port;
1260 memcpy (&sinp->sin_addr,
1261 at2->addr, sizeof (struct in_addr));
1262 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1265 pai = &(ai->ai_next);
1277 free ((char *) name);
1280 if (malloc_canonbuf)
1291 struct addrinfo *dest_addr;
1292 /* Using sockaddr_storage is for now overkill. We only support IPv4
1293 and IPv6 so far. If this changes at some point we can adjust the
1295 struct sockaddr_in6 source_addr;
1296 uint8_t source_addr_len;
1297 bool got_source_addr;
1298 uint8_t source_addr_flags;
1304 struct sort_result_combo
1306 struct sort_result *results;
1311 #if __BYTE_ORDER == __BIG_ENDIAN
1312 # define htonl_c(n) n
1314 # define htonl_c(n) __bswap_constant_32 (n)
1317 static const struct scopeentry
1326 } default_scopes[] =
1328 /* Link-local addresses: scope 2. */
1329 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1330 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1331 /* Default: scope 14. */
1332 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1335 /* The label table. */
1336 static const struct scopeentry *scopes;
1340 get_scope (const struct sockaddr_in6 *in6)
1343 if (in6->sin6_family == PF_INET6)
1345 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1347 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1348 /* RFC 4291 2.5.3 says that the loopback address is to be
1349 treated like a link-local address. */
1350 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1352 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1355 /* XXX Is this the correct default behavior? */
1359 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1361 else if (in6->sin6_family == PF_INET)
1363 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1368 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1369 == scopes[cnt].addr32)
1370 return scopes[cnt].scope;
1377 /* XXX What is a good default? */
1386 struct in6_addr prefix;
1392 /* The label table. */
1393 static const struct prefixentry *labels;
1395 /* Default labels. */
1396 static const struct prefixentry default_labels[] =
1398 /* See RFC 3484 for the details. */
1400 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1404 = { .__u6_addr8 = { 0x20, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1412 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1413 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1415 /* The next two entries differ from RFC 3484. We need to treat
1416 IPv6 site-local addresses special because they are never NATed,
1417 unlike site-locale IPv4 addresses. If this would not happen, on
1418 machines which have only IPv4 and IPv6 site-local addresses, the
1419 sorting would prefer the IPv6 site-local addresses, causing
1420 unnecessary delays when trying to connect to a global IPv6 address
1421 through a site-local IPv6 address. */
1423 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1427 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1430 /* Additional rule for Teredo tunnels. */
1432 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1436 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1442 /* The precedence table. */
1443 static const struct prefixentry *precedence;
1445 /* The default precedences. */
1446 static const struct prefixentry default_precedence[] =
1448 /* See RFC 3484 for the details. */
1450 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1454 = { .__u6_addr8 = { 0x20, 0x02, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1462 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1466 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1473 match_prefix (const struct sockaddr_in6 *in6,
1474 const struct prefixentry *list, int default_val)
1477 struct sockaddr_in6 in6_mem;
1479 if (in6->sin6_family == PF_INET)
1481 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1483 /* Construct a V4-to-6 mapped address. */
1484 in6_mem.sin6_family = PF_INET6;
1485 in6_mem.sin6_port = in->sin_port;
1486 in6_mem.sin6_flowinfo = 0;
1487 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1488 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1489 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1490 in6_mem.sin6_scope_id = 0;
1494 else if (in6->sin6_family != PF_INET6)
1497 for (idx = 0; ; ++idx)
1499 unsigned int bits = list[idx].bits;
1500 const uint8_t *mask = list[idx].prefix.s6_addr;
1501 const uint8_t *val = in6->sin6_addr.s6_addr;
1515 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1521 return list[idx].val;
1526 get_label (const struct sockaddr_in6 *in6)
1528 /* XXX What is a good default value? */
1529 return match_prefix (in6, labels, INT_MAX);
1534 get_precedence (const struct sockaddr_in6 *in6)
1536 /* XXX What is a good default value? */
1537 return match_prefix (in6, precedence, 0);
1541 /* Find last bit set in a word. */
1547 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1548 if ((a & mask) != 0)
1555 rfc3484_sort (const void *p1, const void *p2, void *arg)
1557 const size_t idx1 = *(const size_t *) p1;
1558 const size_t idx2 = *(const size_t *) p2;
1559 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1560 struct sort_result *a1 = &src->results[idx1];
1561 struct sort_result *a2 = &src->results[idx2];
1563 /* Rule 1: Avoid unusable destinations.
1564 We have the got_source_addr flag set if the destination is reachable. */
1565 if (a1->got_source_addr && ! a2->got_source_addr)
1567 if (! a1->got_source_addr && a2->got_source_addr)
1571 /* Rule 2: Prefer matching scope. Only interesting if both
1572 destination addresses are IPv6. */
1574 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1577 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1579 if (a1->got_source_addr)
1581 int a1_src_scope = get_scope (&a1->source_addr);
1582 int a2_src_scope = get_scope (&a2->source_addr);
1584 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1586 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1591 /* Rule 3: Avoid deprecated addresses. */
1592 if (a1->got_source_addr)
1594 if (!(a1->source_addr_flags & in6ai_deprecated)
1595 && (a2->source_addr_flags & in6ai_deprecated))
1597 if ((a1->source_addr_flags & in6ai_deprecated)
1598 && !(a2->source_addr_flags & in6ai_deprecated))
1602 /* Rule 4: Prefer home addresses. */
1603 if (a1->got_source_addr)
1605 if (!(a1->source_addr_flags & in6ai_homeaddress)
1606 && (a2->source_addr_flags & in6ai_homeaddress))
1608 if ((a1->source_addr_flags & in6ai_homeaddress)
1609 && !(a2->source_addr_flags & in6ai_homeaddress))
1613 /* Rule 5: Prefer matching label. */
1614 if (a1->got_source_addr)
1617 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1618 int a1_src_label = get_label (&a1->source_addr);
1621 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1622 int a2_src_label = get_label (&a2->source_addr);
1624 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1626 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1631 /* Rule 6: Prefer higher precedence. */
1633 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1635 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1637 if (a1_prec > a2_prec)
1639 if (a1_prec < a2_prec)
1643 /* Rule 7: Prefer native transport. */
1644 if (a1->got_source_addr)
1646 /* The same interface index means the same interface which means
1647 there is no difference in transport. This should catch many
1649 if (a1->index != a2->index)
1651 int a1_native = a1->native;
1652 int a2_native = a2->native;
1654 if (a1_native == -1 || a2_native == -1)
1657 if (a1_native == -1)
1659 /* If we do not have the information use 'native' as
1662 a1_index = a1->index;
1665 a1_index = 0xffffffffu;
1668 if (a2_native == -1)
1670 /* If we do not have the information use 'native' as
1673 a2_index = a2->index;
1676 a2_index = 0xffffffffu;
1678 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1680 /* Fill in the results in all the records. */
1681 for (int i = 0; i < src->nresults; ++i)
1682 if (a1_index != -1 && src->results[i].index == a1_index)
1684 assert (src->results[i].native == -1
1685 || src->results[i].native == a1_native);
1686 src->results[i].native = a1_native;
1688 else if (a2_index != -1 && src->results[i].index == a2_index)
1690 assert (src->results[i].native == -1
1691 || src->results[i].native == a2_native);
1692 src->results[i].native = a2_native;
1696 if (a1_native && !a2_native)
1698 if (!a1_native && a2_native)
1704 /* Rule 8: Prefer smaller scope. */
1705 if (a1_dst_scope < a2_dst_scope)
1707 if (a1_dst_scope > a2_dst_scope)
1711 /* Rule 9: Use longest matching prefix. */
1712 if (a1->got_source_addr
1713 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1718 if (a1->dest_addr->ai_family == PF_INET)
1720 assert (a1->source_addr.sin6_family == PF_INET);
1721 assert (a2->source_addr.sin6_family == PF_INET);
1723 /* Outside of subnets, as defined by the network masks,
1724 common address prefixes for IPv4 addresses make no sense.
1725 So, define a non-zero value only if source and
1726 destination address are on the same subnet. */
1727 struct sockaddr_in *in1_dst
1728 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1729 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1730 struct sockaddr_in *in1_src
1731 = (struct sockaddr_in *) &a1->source_addr;
1732 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1733 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1735 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1736 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1738 struct sockaddr_in *in2_dst
1739 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1740 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1741 struct sockaddr_in *in2_src
1742 = (struct sockaddr_in *) &a2->source_addr;
1743 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1744 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1746 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1747 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1749 else if (a1->dest_addr->ai_family == PF_INET6)
1751 assert (a1->source_addr.sin6_family == PF_INET6);
1752 assert (a2->source_addr.sin6_family == PF_INET6);
1754 struct sockaddr_in6 *in1_dst;
1755 struct sockaddr_in6 *in1_src;
1756 struct sockaddr_in6 *in2_dst;
1757 struct sockaddr_in6 *in2_src;
1759 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1760 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1761 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1762 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1765 for (i = 0; i < 4; ++i)
1766 if (in1_dst->sin6_addr.s6_addr32[i]
1767 != in1_src->sin6_addr.s6_addr32[i]
1768 || (in2_dst->sin6_addr.s6_addr32[i]
1769 != in2_src->sin6_addr.s6_addr32[i]))
1774 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1775 ^ in1_src->sin6_addr.s6_addr32[i]));
1776 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1777 ^ in2_src->sin6_addr.s6_addr32[i]));
1788 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1789 compare with the value indicating the order in which the entries
1790 have been received from the services. NB: no two entries can have
1791 the same order so the test will never return zero. */
1792 return idx1 < idx2 ? -1 : 1;
1797 in6aicmp (const void *p1, const void *p2)
1799 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1800 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1802 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1806 /* Name of the config file for RFC 3484 sorting (for now). */
1807 #define GAICONF_FNAME "/etc/gai.conf"
1810 /* Non-zero if we are supposed to reload the config file automatically
1811 whenever it changed. */
1812 static int gaiconf_reload_flag;
1814 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1815 static int gaiconf_reload_flag_ever_set;
1817 /* Last modification time. */
1818 #ifdef _STATBUF_ST_NSEC
1820 static struct timespec gaiconf_mtime;
1823 save_gaiconf_mtime (const struct stat64 *st)
1825 gaiconf_mtime = st->st_mtim;
1829 check_gaiconf_mtime (const struct stat64 *st)
1831 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1832 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1837 static time_t gaiconf_mtime;
1840 save_gaiconf_mtime (const struct stat64 *st)
1842 gaiconf_mtime = st->st_mtime;
1846 check_gaiconf_mtime (const struct stat64 *st)
1848 return st->st_mtime == gaiconf_mtime;
1854 libc_freeres_fn(fini)
1856 if (labels != default_labels)
1858 const struct prefixentry *old = labels;
1859 labels = default_labels;
1860 free ((void *) old);
1863 if (precedence != default_precedence)
1865 const struct prefixentry *old = precedence;
1866 precedence = default_precedence;
1867 free ((void *) old);
1870 if (scopes != default_scopes)
1872 const struct scopeentry *old = scopes;
1873 scopes = default_scopes;
1874 free ((void *) old);
1881 struct prefixentry entry;
1882 struct prefixlist *next;
1888 struct scopeentry entry;
1889 struct scopelist *next;
1894 free_prefixlist (struct prefixlist *list)
1896 while (list != NULL)
1898 struct prefixlist *oldp = list;
1906 free_scopelist (struct scopelist *list)
1908 while (list != NULL)
1910 struct scopelist *oldp = list;
1918 prefixcmp (const void *p1, const void *p2)
1920 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1921 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1923 if (e1->bits < e2->bits)
1925 if (e1->bits == e2->bits)
1932 scopecmp (const void *p1, const void *p2)
1934 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1935 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1937 if (e1->netmask > e2->netmask)
1939 if (e1->netmask == e2->netmask)
1948 struct prefixlist *labellist = NULL;
1949 size_t nlabellist = 0;
1950 bool labellist_nullbits = false;
1951 struct prefixlist *precedencelist = NULL;
1952 size_t nprecedencelist = 0;
1953 bool precedencelist_nullbits = false;
1954 struct scopelist *scopelist = NULL;
1955 size_t nscopelist = 0;
1956 bool scopelist_nullbits = false;
1958 FILE *fp = fopen (GAICONF_FNAME, "rce");
1962 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1971 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1973 while (!feof_unlocked (fp))
1975 ssize_t n = __getline (&line, &linelen, fp);
1979 /* Handle comments. No escaping possible so this is easy. */
1980 char *cp = strchr (line, '#');
1985 while (isspace (*cp))
1989 while (*cp != '\0' && !isspace (*cp))
1991 size_t cmdlen = cp - cmd;
1995 while (isspace (*cp))
1999 while (*cp != '\0' && !isspace (*cp))
2001 size_t val1len = cp - cmd;
2003 /* We always need at least two values. */
2009 while (isspace (*cp))
2013 while (*cp != '\0' && !isspace (*cp))
2016 /* Ignore the rest of the line. */
2019 struct prefixlist **listp;
2025 if (strcmp (cmd, "label") == 0)
2027 struct in6_addr prefix;
2028 unsigned long int bits;
2029 unsigned long int val;
2034 nullbitsp = &labellist_nullbits;
2039 cp = strchr (val1, '/');
2042 if (inet_pton (AF_INET6, val1, &prefix)
2044 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2048 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2053 struct prefixlist *newp = malloc (sizeof (*newp));
2061 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2062 newp->entry.bits = bits;
2063 newp->entry.val = val;
2064 newp->next = *listp;
2067 *nullbitsp |= bits == 0;
2073 if (strcmp (cmd, "reload") == 0)
2075 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2076 if (gaiconf_reload_flag)
2077 gaiconf_reload_flag_ever_set = 1;
2082 if (strcmp (cmd, "scopev4") == 0)
2084 struct in6_addr prefix;
2085 unsigned long int bits;
2086 unsigned long int val;
2091 cp = strchr (val1, '/');
2094 if (inet_pton (AF_INET6, val1, &prefix))
2097 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2099 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2104 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2109 struct scopelist *newp;
2111 newp = malloc (sizeof (*newp));
2119 newp->entry.netmask = htonl (bits != 96
2123 newp->entry.addr32 = (prefix.s6_addr32[3]
2124 & newp->entry.netmask);
2125 newp->entry.scope = val;
2126 newp->next = scopelist;
2129 scopelist_nullbits |= bits == 96;
2132 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2134 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2138 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2150 if (strcmp (cmd, "precedence") == 0)
2152 listp = &precedencelist;
2153 lenp = &nprecedencelist;
2154 nullbitsp = &precedencelist_nullbits;
2165 /* Create the array for the labels. */
2166 struct prefixentry *new_labels;
2169 if (!labellist_nullbits)
2171 new_labels = malloc (nlabellist * sizeof (*new_labels));
2172 if (new_labels == NULL)
2176 if (!labellist_nullbits)
2179 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2180 new_labels[i].bits = 0;
2181 new_labels[i].val = 1;
2184 struct prefixlist *l = labellist;
2187 new_labels[i] = l->entry;
2190 free_prefixlist (labellist);
2192 /* Sort the entries so that the most specific ones are at
2194 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2197 new_labels = (struct prefixentry *) default_labels;
2199 struct prefixentry *new_precedence;
2200 if (nprecedencelist > 0)
2202 if (!precedencelist_nullbits)
2204 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2205 if (new_precedence == NULL)
2207 if (new_labels != default_labels)
2212 int i = nprecedencelist;
2213 if (!precedencelist_nullbits)
2216 memset (&new_precedence[i].prefix, '\0',
2217 sizeof (struct in6_addr));
2218 new_precedence[i].bits = 0;
2219 new_precedence[i].val = 40;
2222 struct prefixlist *l = precedencelist;
2225 new_precedence[i] = l->entry;
2228 free_prefixlist (precedencelist);
2230 /* Sort the entries so that the most specific ones are at
2232 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2236 new_precedence = (struct prefixentry *) default_precedence;
2238 struct scopeentry *new_scopes;
2241 if (!scopelist_nullbits)
2243 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2244 if (new_scopes == NULL)
2246 if (new_labels != default_labels)
2248 if (new_precedence != default_precedence)
2249 free (new_precedence);
2254 if (!scopelist_nullbits)
2257 new_scopes[i].addr32 = 0;
2258 new_scopes[i].netmask = 0;
2259 new_scopes[i].scope = 14;
2262 struct scopelist *l = scopelist;
2265 new_scopes[i] = l->entry;
2268 free_scopelist (scopelist);
2270 /* Sort the entries so that the most specific ones are at
2272 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2276 new_scopes = (struct scopeentry *) default_scopes;
2278 /* Now we are ready to replace the values. */
2279 const struct prefixentry *old = labels;
2280 labels = new_labels;
2281 if (old != default_labels)
2282 free ((void *) old);
2285 precedence = new_precedence;
2286 if (old != default_precedence)
2287 free ((void *) old);
2289 const struct scopeentry *oldscope = scopes;
2290 scopes = new_scopes;
2291 if (oldscope != default_scopes)
2292 free ((void *) oldscope);
2294 save_gaiconf_mtime (&st);
2299 free_prefixlist (labellist);
2300 free_prefixlist (precedencelist);
2301 free_scopelist (scopelist);
2303 /* If we previously read the file but it is gone now, free the
2304 old data and use the builtin one. Leave the reload flag
2312 gaiconf_reload (void)
2315 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2316 || !check_gaiconf_mtime (&st))
2322 getaddrinfo (const char *name, const char *service,
2323 const struct addrinfo *hints, struct addrinfo **pai)
2325 int i = 0, last_i = 0;
2327 struct addrinfo *p = NULL;
2328 struct gaih_service gaih_service, *pservice;
2329 struct addrinfo local_hints;
2331 if (name != NULL && name[0] == '*' && name[1] == 0)
2334 if (service != NULL && service[0] == '*' && service[1] == 0)
2337 if (name == NULL && service == NULL)
2341 hints = &default_hints;
2344 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2346 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2347 |AI_IDN_USE_STD3_ASCII_RULES
2349 |AI_NUMERICSERV|AI_ALL))
2350 return EAI_BADFLAGS;
2352 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2353 return EAI_BADFLAGS;
2355 struct in6addrinfo *in6ai = NULL;
2356 size_t in6ailen = 0;
2357 bool seen_ipv4 = false;
2358 bool seen_ipv6 = false;
2359 bool check_pf_called = false;
2361 if (hints->ai_flags & AI_ADDRCONFIG)
2363 /* We might need information about what interfaces are available.
2364 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2365 cannot cache the results since new interfaces could be added at
2367 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2368 check_pf_called = true;
2370 /* Now make a decision on what we return, if anything. */
2371 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2373 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2374 narrow down the search. */
2375 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2377 local_hints = *hints;
2378 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2379 hints = &local_hints;
2382 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2383 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2385 /* We cannot possibly return a valid answer. */
2386 __free_in6ai (in6ai);
2391 if (service && service[0])
2394 gaih_service.name = service;
2395 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2398 if (hints->ai_flags & AI_NUMERICSERV)
2400 __free_in6ai (in6ai);
2404 gaih_service.num = -1;
2407 pservice = &gaih_service;
2412 struct addrinfo **end = &p;
2414 unsigned int naddrs = 0;
2415 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2416 || hints->ai_family == AF_INET6)
2418 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2422 __free_in6ai (in6ai);
2428 end = &((*end)->ai_next);
2434 __free_in6ai (in6ai);
2440 /* Read the config file. */
2441 __libc_once_define (static, once);
2442 __typeof (once) old_once = once;
2443 __libc_once (once, gaiconf_init);
2444 /* Sort results according to RFC 3484. */
2445 struct sort_result *results;
2448 struct addrinfo *last = NULL;
2449 char *canonname = NULL;
2450 bool malloc_results;
2451 size_t alloc_size = nresults * (sizeof (*results) + sizeof (size_t));
2454 = !__libc_use_alloca (alloc_size);
2457 results = malloc (alloc_size);
2458 if (results == NULL)
2460 __free_in6ai (in6ai);
2465 results = alloca (alloc_size);
2466 order = (size_t *) (results + nresults);
2468 /* Now we definitely need the interface information. */
2469 if (! check_pf_called)
2470 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2472 /* If we have information about deprecated and temporary addresses
2473 sort the array now. */
2475 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2480 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2482 results[i].dest_addr = q;
2483 results[i].native = -1;
2486 /* If we just looked up the address for a different
2487 protocol, reuse the result. */
2488 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2489 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2491 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2492 results[i - 1].source_addr_len);
2493 results[i].source_addr_len = results[i - 1].source_addr_len;
2494 results[i].got_source_addr = results[i - 1].got_source_addr;
2495 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2496 results[i].prefixlen = results[i - 1].prefixlen;
2497 results[i].index = results[i - 1].index;
2501 results[i].got_source_addr = false;
2502 results[i].source_addr_flags = 0;
2503 results[i].prefixlen = 0;
2504 results[i].index = 0xffffffffu;
2506 /* We overwrite the type with SOCK_DGRAM since we do not
2507 want connect() to connect to the other side. If we
2508 cannot determine the source address remember this
2510 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2514 close_not_cancel_no_status (fd);
2516 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2520 /* Reset the connection. */
2521 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2522 __connect (fd, &sa, sizeof (sa));
2525 socklen_t sl = sizeof (results[i].source_addr);
2527 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2528 && __getsockname (fd,
2529 (struct sockaddr *) &results[i].source_addr,
2532 results[i].source_addr_len = sl;
2533 results[i].got_source_addr = true;
2537 /* See whether the source address is on the list of
2538 deprecated or temporary addresses. */
2539 struct in6addrinfo tmp;
2541 if (q->ai_family == AF_INET && af == AF_INET)
2543 struct sockaddr_in *sinp
2544 = (struct sockaddr_in *) &results[i].source_addr;
2547 tmp.addr[2] = htonl (0xffff);
2548 /* Special case for lo interface, the source address
2549 being possibly different than the interface
2551 if ((ntohl(sinp->sin_addr.s_addr) & 0xff000000)
2553 tmp.addr[3] = htonl(0x7f000001);
2555 tmp.addr[3] = sinp->sin_addr.s_addr;
2559 struct sockaddr_in6 *sin6p
2560 = (struct sockaddr_in6 *) &results[i].source_addr;
2561 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2564 struct in6addrinfo *found
2565 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2569 results[i].source_addr_flags = found->flags;
2570 results[i].prefixlen = found->prefixlen;
2571 results[i].index = found->index;
2575 if (q->ai_family == AF_INET && af == AF_INET6)
2577 /* We have to convert the address. The socket is
2578 IPv6 and the request is for IPv4. */
2579 struct sockaddr_in6 *sin6
2580 = (struct sockaddr_in6 *) &results[i].source_addr;
2581 struct sockaddr_in *sin
2582 = (struct sockaddr_in *) &results[i].source_addr;
2583 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2584 sin->sin_family = AF_INET;
2585 /* We do not have to initialize sin_port since this
2586 fields has the same position and size in the IPv6
2588 assert (offsetof (struct sockaddr_in, sin_port)
2589 == offsetof (struct sockaddr_in6, sin6_port));
2590 assert (sizeof (sin->sin_port)
2591 == sizeof (sin6->sin6_port));
2592 memcpy (&sin->sin_addr,
2593 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2594 results[i].source_addr_len = sizeof (struct sockaddr_in);
2597 else if (errno == EAFNOSUPPORT && af == AF_INET6
2598 && q->ai_family == AF_INET)
2599 /* This could mean IPv6 sockets are IPv6-only. */
2602 /* Just make sure that if we have to process the same
2603 address again we do not copy any memory. */
2604 results[i].source_addr_len = 0;
2607 /* Remember the canonical name. */
2608 if (q->ai_canonname != NULL)
2610 assert (canonname == NULL);
2611 canonname = q->ai_canonname;
2612 q->ai_canonname = NULL;
2617 close_not_cancel_no_status (fd);
2619 /* We got all the source addresses we can get, now sort using
2621 struct sort_result_combo src
2622 = { .results = results, .nresults = nresults };
2623 if (__glibc_unlikely (gaiconf_reload_flag_ever_set))
2625 __libc_lock_define_initialized (static, lock);
2627 __libc_lock_lock (lock);
2628 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2630 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2631 __libc_lock_unlock (lock);
2634 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2636 /* Queue the results up as they come out of sorting. */
2637 q = p = results[order[0]].dest_addr;
2638 for (i = 1; i < nresults; ++i)
2639 q = q->ai_next = results[order[i]].dest_addr;
2642 /* Fill in the canonical name into the new first entry. */
2643 p->ai_canonname = canonname;
2649 __free_in6ai (in6ai);
2657 return last_i ? -last_i : EAI_NONAME;
2659 libc_hidden_def (getaddrinfo)
2661 nss_interface_function (getaddrinfo)
2664 freeaddrinfo (struct addrinfo *ai)
2672 free (p->ai_canonname);
2676 libc_hidden_def (freeaddrinfo)