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>
50 #include <arpa/inet.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
55 #include <sys/types.h>
57 #include <sys/utsname.h>
60 #include <bits/libc-lock.h>
61 #include <not-cancel.h>
62 #include <nscd/nscd-client.h>
63 #include <nscd/nscd_proto.h>
64 #include <resolv/res_hconf.h>
67 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
68 extern int __idna_to_unicode_lzlz (const char *input, char **output,
70 # include <libidn/idna.h>
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
77 # define UNIX_PATH_MAX 108
88 struct gaih_servtuple *next;
94 static const struct gaih_servtuple nullserv;
106 /* Values for `protoflag'. */
107 #define GAI_PROTO_NOSERVICE 1
108 #define GAI_PROTO_PROTOANY 2
110 static const struct gaih_typeproto gaih_inet_typeproto[] =
112 { 0, 0, 0, false, "" },
113 { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
114 { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
115 #if defined SOCK_DCCP && defined IPPROTO_DCCP
116 { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
118 #ifdef IPPROTO_UDPLITE
119 { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
122 { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
123 { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
125 { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
126 { 0, 0, 0, false, "" }
132 int (*gaih)(const char *name, const struct gaih_service *service,
133 const struct addrinfo *req, struct addrinfo **pai,
134 unsigned int *naddrs);
137 static const struct addrinfo default_hints =
139 .ai_flags = AI_DEFAULT,
140 .ai_family = PF_UNSPEC,
145 .ai_canonname = NULL,
151 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
152 const struct addrinfo *req, struct gaih_servtuple *st)
155 size_t tmpbuflen = 1024;
162 tmpbuf = __alloca (tmpbuflen);
164 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
166 if (r != 0 || s == NULL)
171 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
177 st->socktype = tp->socktype;
178 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
179 ? req->ai_protocol : tp->protocol);
180 st->port = s->s_port;
185 #define gethosts(_family, _type) \
191 char *localcanon = NULL; \
195 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
196 &rc, &herrno, NULL, &localcanon)); \
197 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
199 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
201 if (status == NSS_STATUS_SUCCESS && rc == 0) \
207 if (herrno == NETDB_INTERNAL) \
209 __set_h_errno (herrno); \
210 _res.options |= old_res_options & RES_USE_INET6; \
211 return -EAI_SYSTEM; \
213 if (herrno == TRY_AGAIN) \
214 no_data = EAI_AGAIN; \
216 no_data = herrno == NO_DATA; \
218 else if (h != NULL) \
220 for (i = 0; h->h_addr_list[i]; i++) \
224 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
225 (*pat)->scopeid = 0; \
227 uint32_t *addr = (*pat)->addr; \
228 (*pat)->next = NULL; \
229 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
230 if (_family == AF_INET && req->ai_family == AF_INET6) \
232 (*pat)->family = AF_INET6; \
233 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
234 addr[2] = htonl (0xffff); \
240 (*pat)->family = _family; \
241 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
243 pat = &((*pat)->next); \
246 if (localcanon != NULL && canon == NULL) \
247 canon = strdupa (localcanon); \
249 if (_family == AF_INET6 && i > 0) \
255 typedef enum nss_status (*nss_gethostbyname4_r)
256 (const char *name, struct gaih_addrtuple **pat,
257 char *buffer, size_t buflen, int *errnop,
258 int *h_errnop, int32_t *ttlp);
259 typedef enum nss_status (*nss_gethostbyname3_r)
260 (const char *name, int af, struct hostent *host,
261 char *buffer, size_t buflen, int *errnop,
262 int *h_errnop, int32_t *ttlp, char **canonp);
263 typedef enum nss_status (*nss_getcanonname_r)
264 (const char *name, char *buffer, size_t buflen, char **result,
265 int *errnop, int *h_errnop);
266 extern service_user *__nss_hosts_database attribute_hidden;
270 gaih_inet (const char *name, const struct gaih_service *service,
271 const struct addrinfo *req, struct addrinfo **pai,
272 unsigned int *naddrs)
274 const struct gaih_typeproto *tp = gaih_inet_typeproto;
275 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
276 struct gaih_addrtuple *at = NULL;
278 bool got_ipv6 = false;
279 const char *canon = NULL;
280 const char *orig_name = name;
281 size_t alloca_used = 0;
283 if (req->ai_protocol || req->ai_socktype)
288 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
289 || (req->ai_protocol != 0
290 && !(tp->protoflag & GAI_PROTO_PROTOANY)
291 && req->ai_protocol != tp->protocol)))
296 if (req->ai_socktype)
297 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
299 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
306 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
307 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
309 if (service->num < 0)
313 st = (struct gaih_servtuple *)
314 alloca_account (sizeof (struct gaih_servtuple), alloca_used);
316 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
321 struct gaih_servtuple **pst = &st;
322 for (tp++; tp->name[0]; tp++)
324 struct gaih_servtuple *newp;
326 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
329 if (req->ai_socktype != 0
330 && req->ai_socktype != tp->socktype)
332 if (req->ai_protocol != 0
333 && !(tp->protoflag & GAI_PROTO_PROTOANY)
334 && req->ai_protocol != tp->protocol)
337 newp = (struct gaih_servtuple *)
338 alloca_account (sizeof (struct gaih_servtuple),
341 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
343 if (rc & GAIH_OKIFUNSPEC)
351 if (st == (struct gaih_servtuple *) &nullserv)
352 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
357 port = htons (service->num);
365 if (req->ai_socktype || req->ai_protocol)
367 st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
369 st->socktype = tp->socktype;
370 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
371 ? req->ai_protocol : tp->protocol);
376 /* Neither socket type nor protocol is set. Return all socket types
378 struct gaih_servtuple **lastp = &st;
379 for (++tp; tp->name[0]; ++tp)
382 struct gaih_servtuple *newp;
384 newp = alloca_account (sizeof (struct gaih_servtuple),
387 newp->socktype = tp->socktype;
388 newp->protocol = tp->protocol;
397 bool malloc_name = false;
398 bool malloc_addrmem = false;
399 struct gaih_addrtuple *addrmem = NULL;
400 bool malloc_canonbuf = false;
401 char *canonbuf = NULL;
402 bool malloc_tmpbuf = false;
407 at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
408 at->family = AF_UNSPEC;
413 if (req->ai_flags & AI_IDN)
416 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
417 idn_flags |= IDNA_ALLOW_UNASSIGNED;
418 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
419 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
422 rc = __idna_to_ascii_lz (name, &p, idn_flags);
423 if (rc != IDNA_SUCCESS)
425 /* No need to jump to free_and_return here. */
426 if (rc == IDNA_MALLOC_ERROR)
428 if (rc == IDNA_DLOPEN_ERROR)
430 return -EAI_IDN_ENCODE;
432 /* In case the output string is the same as the input string
433 no new string has been allocated. */
442 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
444 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
445 at->family = AF_INET;
446 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
448 at->addr[3] = at->addr[0];
449 at->addr[2] = htonl (0xffff);
452 at->family = AF_INET6;
456 result = -EAI_ADDRFAMILY;
457 goto free_and_return;
460 if (req->ai_flags & AI_CANONNAME)
463 else if (at->family == AF_UNSPEC)
465 char *scope_delim = strchr (name, SCOPE_DELIMITER);
469 bool malloc_namebuf = false;
470 char *namebuf = (char *) name;
472 if (__builtin_expect (scope_delim != NULL, 0))
478 if (__libc_use_alloca (alloca_used
479 + scope_delim - name + 1))
481 namebuf = alloca_account (scope_delim - name + 1,
483 *((char *) __mempcpy (namebuf, name,
484 scope_delim - name)) = '\0';
488 namebuf = strndup (name, scope_delim - name);
491 assert (!malloc_name);
494 malloc_namebuf = true;
499 e = inet_pton (AF_INET6, namebuf, at->addr);
503 else if (scope_delim != NULL && malloc_name)
504 /* Undo what we did above. */
505 *scope_delim = SCOPE_DELIMITER;
509 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
510 at->family = AF_INET6;
511 else if (req->ai_family == AF_INET
512 && IN6_IS_ADDR_V4MAPPED (at->addr))
514 at->addr[0] = at->addr[3];
515 at->family = AF_INET;
519 result = -EAI_ADDRFAMILY;
520 goto free_and_return;
523 if (scope_delim != NULL)
525 int try_numericscope = 0;
526 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
527 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
529 at->scopeid = if_nametoindex (scope_delim + 1);
530 if (at->scopeid == 0)
531 try_numericscope = 1;
534 try_numericscope = 1;
536 if (try_numericscope != 0)
539 assert (sizeof (uint32_t) <= sizeof (unsigned long));
540 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
544 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
545 goto free_and_return;
550 if (req->ai_flags & AI_CANONNAME)
555 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
557 struct gaih_addrtuple **pat = &at;
559 int no_inet6_data = 0;
560 service_user *nip = NULL;
561 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
562 enum nss_status status = NSS_STATUS_UNAVAIL;
566 /* If we do not have to look for IPv6 addresses, use
567 the simple, old functions, which do not support
569 if (req->ai_family == AF_INET)
571 /* Allocate additional room for struct host_data. */
572 size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*)
573 + 16 * sizeof(char));
574 assert (tmpbuf == NULL);
575 tmpbuf = alloca_account (tmpbuflen, alloca_used);
583 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
584 tmpbuflen, &h, &herrno);
585 if (rc != ERANGE || herrno != NETDB_INTERNAL)
589 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
590 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
595 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
599 result = -EAI_MEMORY;
600 goto free_and_return;
603 malloc_tmpbuf = true;
604 tmpbuflen = 2 * tmpbuflen;
613 /* We found data, count the number of addresses. */
614 for (i = 0; h->h_addr_list[i]; ++i)
616 if (i > 0 && *pat != NULL)
619 if (__libc_use_alloca (alloca_used
620 + i * sizeof (struct gaih_addrtuple)))
621 addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
626 * sizeof (struct gaih_addrtuple));
629 result = -EAI_MEMORY;
630 goto free_and_return;
632 malloc_addrmem = true;
635 /* Now convert it into the list. */
636 struct gaih_addrtuple *addrfree = addrmem;
637 for (i = 0; h->h_addr_list[i]; ++i)
645 (*pat)->family = AF_INET;
646 memcpy ((*pat)->addr, h->h_addr_list[i],
648 pat = &((*pat)->next);
654 if (herrno == NETDB_INTERNAL)
656 __set_h_errno (herrno);
657 result = -EAI_SYSTEM;
659 else if (herrno == TRY_AGAIN)
662 /* We made requests but they turned out no data.
663 The name is known, though. */
664 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
666 goto free_and_return;
673 if (__nss_not_use_nscd_hosts > 0
674 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
675 __nss_not_use_nscd_hosts = 0;
677 if (!__nss_not_use_nscd_hosts
678 && !__nss_database_custom[NSS_DBSIDX_hosts])
680 /* Try to use nscd. */
681 struct nscd_ai_result *air = NULL;
683 int err = __nscd_getai (name, &air, &herrno);
686 /* Transform into gaih_addrtuple list. */
687 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
688 char *addrs = air->addrs;
690 if (__libc_use_alloca (alloca_used
691 + air->naddrs * sizeof (struct gaih_addrtuple)))
692 addrmem = alloca_account (air->naddrs
693 * sizeof (struct gaih_addrtuple),
697 addrmem = malloc (air->naddrs
698 * sizeof (struct gaih_addrtuple));
701 result = -EAI_MEMORY;
702 goto free_and_return;
704 malloc_addrmem = true;
707 struct gaih_addrtuple *addrfree = addrmem;
708 for (int i = 0; i < air->naddrs; ++i)
710 socklen_t size = (air->family[i] == AF_INET
711 ? INADDRSZ : IN6ADDRSZ);
717 uint32_t *pataddr = (*pat)->addr;
719 if (added_canon || air->canon == NULL)
721 else if (canonbuf == NULL)
723 size_t canonlen = strlen (air->canon) + 1;
724 if ((req->ai_flags & AI_CANONIDN) != 0
725 && __libc_use_alloca (alloca_used + canonlen))
726 canonbuf = alloca_account (canonlen, alloca_used);
729 canonbuf = malloc (canonlen);
730 if (canonbuf == NULL)
732 result = -EAI_MEMORY;
733 goto free_and_return;
735 malloc_canonbuf = true;
737 canon = (*pat)->name = memcpy (canonbuf, air->canon,
741 if (air->family[i] == AF_INET
742 && req->ai_family == AF_INET6
743 && (req->ai_flags & AI_V4MAPPED))
745 (*pat)->family = AF_INET6;
746 pataddr[3] = *(uint32_t *) addrs;
747 pataddr[2] = htonl (0xffff);
750 pat = &((*pat)->next);
753 else if (req->ai_family == AF_UNSPEC
754 || air->family[i] == req->ai_family)
756 (*pat)->family = air->family[i];
757 memcpy (pataddr, addrs, size);
758 pat = &((*pat)->next);
760 if (air->family[i] == AF_INET6)
768 if (at->family == AF_UNSPEC)
770 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
771 goto free_and_return;
777 /* The database contains a negative entry. */
778 goto free_and_return;
779 else if (__nss_not_use_nscd_hosts == 0)
781 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
782 result = -EAI_MEMORY;
783 else if (herrno == TRY_AGAIN)
786 result = -EAI_SYSTEM;
788 goto free_and_return;
793 if (__nss_hosts_database != NULL)
796 nip = __nss_hosts_database;
799 no_more = __nss_database_lookup ("hosts", NULL,
800 "dns [!UNAVAIL=return] files",
803 /* Initialize configurations. */
804 if (__builtin_expect (!_res_hconf.initialized, 0))
806 if (__res_maybe_init (&_res, 0) == -1)
809 /* If we are looking for both IPv4 and IPv6 address we don't
810 want the lookup functions to automatically promote IPv4
811 addresses to IPv6 addresses. Currently this is decided
812 by setting the RES_USE_INET6 bit in _res.options. */
813 old_res_options = _res.options;
814 _res.options &= ~RES_USE_INET6;
816 size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
817 malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
818 assert (tmpbuf == NULL);
820 tmpbuf = alloca_account (tmpbuflen, alloca_used);
823 tmpbuf = malloc (tmpbuflen);
826 _res.options |= old_res_options & RES_USE_INET6;
827 result = -EAI_MEMORY;
828 goto free_and_return;
835 nss_gethostbyname4_r fct4 = NULL;
837 /* gethostbyname4_r sends out parallel A and AAAA queries and
838 is thus only suitable for PF_UNSPEC. */
839 if (req->ai_family == PF_UNSPEC)
840 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
849 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
850 tmpbuflen, &rc, &herrno,
852 if (status == NSS_STATUS_SUCCESS)
854 if (status != NSS_STATUS_TRYAGAIN
855 || rc != ERANGE || herrno != NETDB_INTERNAL)
857 if (status == NSS_STATUS_TRYAGAIN
858 && herrno == TRY_AGAIN)
861 no_data = herrno == NO_DATA;
866 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
867 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
872 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
876 _res.options |= old_res_options & RES_USE_INET6;
877 result = -EAI_MEMORY;
878 goto free_and_return;
881 malloc_tmpbuf = true;
882 tmpbuflen = 2 * tmpbuflen;
886 if (status == NSS_STATUS_SUCCESS)
891 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
892 canon = (*pat)->name;
896 if ((*pat)->family == AF_INET
897 && req->ai_family == AF_INET6
898 && (req->ai_flags & AI_V4MAPPED) != 0)
900 uint32_t *pataddr = (*pat)->addr;
901 (*pat)->family = AF_INET6;
902 pataddr[3] = pataddr[0];
903 pataddr[2] = htonl (0xffff);
906 pat = &((*pat)->next);
909 else if (req->ai_family == AF_UNSPEC
910 || (*pat)->family == req->ai_family)
912 pat = &((*pat)->next);
915 if (req->ai_family == AF_INET6)
919 *pat = ((*pat)->next);
923 no_inet6_data = no_data;
927 nss_gethostbyname3_r fct = NULL;
928 if (req->ai_flags & AI_CANONNAME)
929 /* No need to use this function if we do not look for
930 the canonical name. The function does not exist in
931 all NSS modules and therefore the lookup would
933 fct = __nss_lookup_function (nip, "gethostbyname3_r");
935 /* We are cheating here. The gethostbyname2_r
936 function does not have the same interface as
937 gethostbyname3_r but the extra arguments the
938 latter takes are added at the end. So the
939 gethostbyname2_r code will just ignore them. */
940 fct = __nss_lookup_function (nip, "gethostbyname2_r");
944 if (req->ai_family == AF_INET6
945 || req->ai_family == AF_UNSPEC)
947 gethosts (AF_INET6, struct in6_addr);
948 no_inet6_data = no_data;
949 inet6_status = status;
951 if (req->ai_family == AF_INET
952 || req->ai_family == AF_UNSPEC
953 || (req->ai_family == AF_INET6
954 && (req->ai_flags & AI_V4MAPPED)
955 /* Avoid generating the mapped addresses if we
956 know we are not going to need them. */
957 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
959 gethosts (AF_INET, struct in_addr);
961 if (req->ai_family == AF_INET)
963 no_inet6_data = no_data;
964 inet6_status = status;
968 /* If we found one address for AF_INET or AF_INET6,
969 don't continue the search. */
970 if (inet6_status == NSS_STATUS_SUCCESS
971 || status == NSS_STATUS_SUCCESS)
973 if ((req->ai_flags & AI_CANONNAME) != 0
976 /* If we need the canonical name, get it
977 from the same service as the result. */
978 nss_getcanonname_r cfct;
981 cfct = __nss_lookup_function (nip,
985 const size_t max_fqdn_len = 256;
986 if ((req->ai_flags & AI_CANONIDN) != 0
987 && __libc_use_alloca (alloca_used
989 canonbuf = alloca_account (max_fqdn_len,
993 canonbuf = malloc (max_fqdn_len);
994 if (canonbuf == NULL)
997 |= old_res_options & RES_USE_INET6;
998 result = -EAI_MEMORY;
999 goto free_and_return;
1001 malloc_canonbuf = true;
1005 if (DL_CALL_FCT (cfct, (at->name ?: name,
1009 == NSS_STATUS_SUCCESS)
1013 /* Set to name now to avoid using
1015 if (malloc_canonbuf)
1018 malloc_canonbuf = false;
1024 status = NSS_STATUS_SUCCESS;
1028 /* We can have different states for AF_INET and
1029 AF_INET6. Try to find a useful one for both. */
1030 if (inet6_status == NSS_STATUS_TRYAGAIN)
1031 status = NSS_STATUS_TRYAGAIN;
1032 else if (status == NSS_STATUS_UNAVAIL
1033 && inet6_status != NSS_STATUS_UNAVAIL)
1034 status = inet6_status;
1038 status = NSS_STATUS_UNAVAIL;
1041 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1044 if (nip->next == NULL)
1050 _res.options |= old_res_options & RES_USE_INET6;
1052 if (no_data != 0 && no_inet6_data != 0)
1054 /* If both requests timed out report this. */
1055 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1056 result = -EAI_AGAIN;
1058 /* We made requests but they turned out no data. The name
1059 is known, though. */
1060 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1062 goto free_and_return;
1067 if (at->family == AF_UNSPEC)
1069 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1070 goto free_and_return;
1075 struct gaih_addrtuple *atr;
1076 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1077 memset (at, '\0', sizeof (struct gaih_addrtuple));
1079 if (req->ai_family == AF_UNSPEC)
1081 at->next = __alloca (sizeof (struct gaih_addrtuple));
1082 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1085 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1087 at->family = AF_INET6;
1088 if ((req->ai_flags & AI_PASSIVE) == 0)
1089 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1093 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1095 atr->family = AF_INET;
1096 if ((req->ai_flags & AI_PASSIVE) == 0)
1097 atr->addr[0] = htonl (INADDR_LOOPBACK);
1102 struct gaih_servtuple *st2;
1103 struct gaih_addrtuple *at2 = at;
1108 buffer is the size of an unformatted IPv6 address in printable format.
1112 /* Only the first entry gets the canonical name. */
1113 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1115 char *tmpbuf2 = NULL;
1116 bool malloc_tmpbuf2 = false;
1120 struct hostent *h = NULL;
1123 /* Add room for struct host_data. */
1124 size_t tmpbuf2len = (512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1)
1125 * sizeof(char*) + 16 * sizeof(char));
1129 if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1130 tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1135 char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1141 result = -EAI_MEMORY;
1142 goto free_and_return;
1146 tmpbuf2len = 2 * tmpbuf2len;
1147 malloc_tmpbuf2 = true;
1150 rc = __gethostbyaddr_r (at2->addr,
1151 ((at2->family == AF_INET6)
1152 ? sizeof (struct in6_addr)
1153 : sizeof (struct in_addr)),
1154 at2->family, &th, tmpbuf2,
1155 tmpbuf2len, &h, &herrno);
1157 while (rc == ERANGE && herrno == NETDB_INTERNAL);
1159 if (rc != 0 && herrno == NETDB_INTERNAL)
1164 __set_h_errno (herrno);
1165 result = -EAI_SYSTEM;
1166 goto free_and_return;
1173 assert (orig_name != NULL);
1174 /* If the canonical name cannot be determined, use
1175 the passed in string. */
1181 if (req->ai_flags & AI_CANONIDN)
1184 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1185 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1186 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1187 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1190 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1191 if (rc != IDNA_SUCCESS)
1196 if (rc == IDNA_MALLOC_ERROR)
1197 result = -EAI_MEMORY;
1198 else if (rc == IDNA_DLOPEN_ERROR)
1199 result = -EAI_SYSTEM;
1201 result = -EAI_IDN_ENCODE;
1202 goto free_and_return;
1204 /* In case the output string is the same as the input
1205 string no new string has been allocated and we
1217 if (malloc_canonbuf)
1218 /* We already allocated the string using malloc. */
1219 malloc_canonbuf = false;
1222 canon = strdup (canon);
1228 result = -EAI_MEMORY;
1229 goto free_and_return;
1238 family = at2->family;
1239 if (family == AF_INET6)
1241 socklen = sizeof (struct sockaddr_in6);
1243 /* If we looked up IPv4 mapped address discard them here if
1244 the caller isn't interested in all address and we have
1245 found at least one IPv6 address. */
1247 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1248 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1252 socklen = sizeof (struct sockaddr_in);
1254 for (st2 = st; st2 != NULL; st2 = st2->next)
1256 struct addrinfo *ai;
1257 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1260 free ((char *) canon);
1261 result = -EAI_MEMORY;
1262 goto free_and_return;
1265 ai->ai_flags = req->ai_flags;
1266 ai->ai_family = family;
1267 ai->ai_socktype = st2->socktype;
1268 ai->ai_protocol = st2->protocol;
1269 ai->ai_addrlen = socklen;
1270 ai->ai_addr = (void *) (ai + 1);
1272 /* We only add the canonical name once. */
1273 ai->ai_canonname = (char *) canon;
1277 ai->ai_addr->sa_len = socklen;
1278 #endif /* _HAVE_SA_LEN */
1279 ai->ai_addr->sa_family = family;
1281 /* In case of an allocation error the list must be NULL
1285 if (family == AF_INET6)
1287 struct sockaddr_in6 *sin6p =
1288 (struct sockaddr_in6 *) ai->ai_addr;
1290 sin6p->sin6_port = st2->port;
1291 sin6p->sin6_flowinfo = 0;
1292 memcpy (&sin6p->sin6_addr,
1293 at2->addr, sizeof (struct in6_addr));
1294 sin6p->sin6_scope_id = at2->scopeid;
1298 struct sockaddr_in *sinp =
1299 (struct sockaddr_in *) ai->ai_addr;
1300 sinp->sin_port = st2->port;
1301 memcpy (&sinp->sin_addr,
1302 at2->addr, sizeof (struct in_addr));
1303 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1306 pai = &(ai->ai_next);
1318 free ((char *) name);
1321 if (malloc_canonbuf)
1332 struct addrinfo *dest_addr;
1333 /* Using sockaddr_storage is for now overkill. We only support IPv4
1334 and IPv6 so far. If this changes at some point we can adjust the
1336 struct sockaddr_in6 source_addr;
1337 uint8_t source_addr_len;
1338 bool got_source_addr;
1339 uint8_t source_addr_flags;
1345 struct sort_result_combo
1347 struct sort_result *results;
1352 #if __BYTE_ORDER == __BIG_ENDIAN
1353 # define htonl_c(n) n
1355 # define htonl_c(n) __bswap_constant_32 (n)
1358 static const struct scopeentry
1367 } default_scopes[] =
1369 /* Link-local addresses: scope 2. */
1370 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1371 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1372 /* Default: scope 14. */
1373 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1376 /* The label table. */
1377 static const struct scopeentry *scopes;
1381 get_scope (const struct sockaddr_in6 *in6)
1384 if (in6->sin6_family == PF_INET6)
1386 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1388 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1389 /* RFC 4291 2.5.3 says that the loopback address is to be
1390 treated like a link-local address. */
1391 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1393 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1396 /* XXX Is this the correct default behavior? */
1400 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1402 else if (in6->sin6_family == PF_INET)
1404 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1409 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1410 == scopes[cnt].addr32)
1411 return scopes[cnt].scope;
1418 /* XXX What is a good default? */
1427 struct in6_addr prefix;
1433 /* The label table. */
1434 static const struct prefixentry *labels;
1436 /* Default labels. */
1437 static const struct prefixentry default_labels[] =
1439 /* See RFC 3484 for the details. */
1441 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1445 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1449 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1453 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1454 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1456 /* The next two entries differ from RFC 3484. We need to treat
1457 IPv6 site-local addresses special because they are never NATed,
1458 unlike site-locale IPv4 addresses. If this would not happen, on
1459 machines which have only IPv4 and IPv6 site-local addresses, the
1460 sorting would prefer the IPv6 site-local addresses, causing
1461 unnecessary delays when trying to connect to a global IPv6 address
1462 through a site-local IPv6 address. */
1464 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1468 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1471 /* Additional rule for Teredo tunnels. */
1473 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1477 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1483 /* The precedence table. */
1484 static const struct prefixentry *precedence;
1486 /* The default precedences. */
1487 static const struct prefixentry default_precedence[] =
1489 /* See RFC 3484 for the details. */
1491 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1492 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1495 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1499 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1503 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1504 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1507 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1514 match_prefix (const struct sockaddr_in6 *in6,
1515 const struct prefixentry *list, int default_val)
1518 struct sockaddr_in6 in6_mem;
1520 if (in6->sin6_family == PF_INET)
1522 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1524 /* Construct a V4-to-6 mapped address. */
1525 in6_mem.sin6_family = PF_INET6;
1526 in6_mem.sin6_port = in->sin_port;
1527 in6_mem.sin6_flowinfo = 0;
1528 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1529 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1530 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1531 in6_mem.sin6_scope_id = 0;
1535 else if (in6->sin6_family != PF_INET6)
1538 for (idx = 0; ; ++idx)
1540 unsigned int bits = list[idx].bits;
1541 const uint8_t *mask = list[idx].prefix.s6_addr;
1542 const uint8_t *val = in6->sin6_addr.s6_addr;
1556 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1562 return list[idx].val;
1567 get_label (const struct sockaddr_in6 *in6)
1569 /* XXX What is a good default value? */
1570 return match_prefix (in6, labels, INT_MAX);
1575 get_precedence (const struct sockaddr_in6 *in6)
1577 /* XXX What is a good default value? */
1578 return match_prefix (in6, precedence, 0);
1582 /* Find last bit set in a word. */
1588 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1589 if ((a & mask) != 0)
1596 rfc3484_sort (const void *p1, const void *p2, void *arg)
1598 const size_t idx1 = *(const size_t *) p1;
1599 const size_t idx2 = *(const size_t *) p2;
1600 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1601 struct sort_result *a1 = &src->results[idx1];
1602 struct sort_result *a2 = &src->results[idx2];
1604 /* Rule 1: Avoid unusable destinations.
1605 We have the got_source_addr flag set if the destination is reachable. */
1606 if (a1->got_source_addr && ! a2->got_source_addr)
1608 if (! a1->got_source_addr && a2->got_source_addr)
1612 /* Rule 2: Prefer matching scope. Only interesting if both
1613 destination addresses are IPv6. */
1615 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1618 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1620 if (a1->got_source_addr)
1622 int a1_src_scope = get_scope (&a1->source_addr);
1623 int a2_src_scope = get_scope (&a2->source_addr);
1625 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1627 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1632 /* Rule 3: Avoid deprecated addresses. */
1633 if (a1->got_source_addr)
1635 if (!(a1->source_addr_flags & in6ai_deprecated)
1636 && (a2->source_addr_flags & in6ai_deprecated))
1638 if ((a1->source_addr_flags & in6ai_deprecated)
1639 && !(a2->source_addr_flags & in6ai_deprecated))
1643 /* Rule 4: Prefer home addresses. */
1644 if (a1->got_source_addr)
1646 if (!(a1->source_addr_flags & in6ai_homeaddress)
1647 && (a2->source_addr_flags & in6ai_homeaddress))
1649 if ((a1->source_addr_flags & in6ai_homeaddress)
1650 && !(a2->source_addr_flags & in6ai_homeaddress))
1654 /* Rule 5: Prefer matching label. */
1655 if (a1->got_source_addr)
1658 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1659 int a1_src_label = get_label (&a1->source_addr);
1662 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1663 int a2_src_label = get_label (&a2->source_addr);
1665 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1667 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1672 /* Rule 6: Prefer higher precedence. */
1674 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1676 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1678 if (a1_prec > a2_prec)
1680 if (a1_prec < a2_prec)
1684 /* Rule 7: Prefer native transport. */
1685 if (a1->got_source_addr)
1687 /* The same interface index means the same interface which means
1688 there is no difference in transport. This should catch many
1690 if (a1->index != a2->index)
1692 int a1_native = a1->native;
1693 int a2_native = a2->native;
1695 if (a1_native == -1 || a2_native == -1)
1698 if (a1_native == -1)
1700 /* If we do not have the information use 'native' as
1703 a1_index = a1->index;
1706 a1_index = 0xffffffffu;
1709 if (a2_native == -1)
1711 /* If we do not have the information use 'native' as
1714 a2_index = a2->index;
1717 a2_index = 0xffffffffu;
1719 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1721 /* Fill in the results in all the records. */
1722 for (int i = 0; i < src->nresults; ++i)
1723 if (src->results[i].index == a1_index)
1725 assert (src->results[i].native == -1
1726 || src->results[i].native == a1_native);
1727 src->results[i].native = a1_native;
1729 else if (src->results[i].index == a2_index)
1731 assert (src->results[i].native == -1
1732 || src->results[i].native == a2_native);
1733 src->results[i].native = a2_native;
1737 if (a1_native && !a2_native)
1739 if (!a1_native && a2_native)
1745 /* Rule 8: Prefer smaller scope. */
1746 if (a1_dst_scope < a2_dst_scope)
1748 if (a1_dst_scope > a2_dst_scope)
1752 /* Rule 9: Use longest matching prefix. */
1753 if (a1->got_source_addr
1754 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1759 if (a1->dest_addr->ai_family == PF_INET)
1761 assert (a1->source_addr.sin6_family == PF_INET);
1762 assert (a2->source_addr.sin6_family == PF_INET);
1764 /* Outside of subnets, as defined by the network masks,
1765 common address prefixes for IPv4 addresses make no sense.
1766 So, define a non-zero value only if source and
1767 destination address are on the same subnet. */
1768 struct sockaddr_in *in1_dst
1769 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1770 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1771 struct sockaddr_in *in1_src
1772 = (struct sockaddr_in *) &a1->source_addr;
1773 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1774 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1776 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1777 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1779 struct sockaddr_in *in2_dst
1780 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1781 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1782 struct sockaddr_in *in2_src
1783 = (struct sockaddr_in *) &a2->source_addr;
1784 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1785 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1787 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1788 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1790 else if (a1->dest_addr->ai_family == PF_INET6)
1792 assert (a1->source_addr.sin6_family == PF_INET6);
1793 assert (a2->source_addr.sin6_family == PF_INET6);
1795 struct sockaddr_in6 *in1_dst;
1796 struct sockaddr_in6 *in1_src;
1797 struct sockaddr_in6 *in2_dst;
1798 struct sockaddr_in6 *in2_src;
1800 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1801 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1802 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1803 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1806 for (i = 0; i < 4; ++i)
1807 if (in1_dst->sin6_addr.s6_addr32[i]
1808 != in1_src->sin6_addr.s6_addr32[i]
1809 || (in2_dst->sin6_addr.s6_addr32[i]
1810 != in2_src->sin6_addr.s6_addr32[i]))
1815 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1816 ^ in1_src->sin6_addr.s6_addr32[i]));
1817 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1818 ^ in2_src->sin6_addr.s6_addr32[i]));
1829 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1830 compare with the value indicating the order in which the entries
1831 have been received from the services. NB: no two entries can have
1832 the same order so the test will never return zero. */
1833 return idx1 < idx2 ? -1 : 1;
1838 in6aicmp (const void *p1, const void *p2)
1840 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1841 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1843 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1847 /* Name of the config file for RFC 3484 sorting (for now). */
1848 #define GAICONF_FNAME "/etc/gai.conf"
1851 /* Non-zero if we are supposed to reload the config file automatically
1852 whenever it changed. */
1853 static int gaiconf_reload_flag;
1855 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1856 static int gaiconf_reload_flag_ever_set;
1858 /* Last modification time. */
1859 #ifdef _STATBUF_ST_NSEC
1861 static struct timespec gaiconf_mtime;
1864 save_gaiconf_mtime (const struct stat64 *st)
1866 gaiconf_mtime = st->st_mtim;
1870 check_gaiconf_mtime (const struct stat64 *st)
1872 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1873 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1878 static time_t gaiconf_mtime;
1881 save_gaiconf_mtime (const struct stat64 *st)
1883 gaiconf_mtime = st->st_mtime;
1887 check_gaiconf_mtime (const struct stat64 *st)
1889 return st->st_mtime == gaiconf_mtime;
1895 libc_freeres_fn(fini)
1897 if (labels != default_labels)
1899 const struct prefixentry *old = labels;
1900 labels = default_labels;
1901 free ((void *) old);
1904 if (precedence != default_precedence)
1906 const struct prefixentry *old = precedence;
1907 precedence = default_precedence;
1908 free ((void *) old);
1911 if (scopes != default_scopes)
1913 const struct scopeentry *old = scopes;
1914 scopes = default_scopes;
1915 free ((void *) old);
1922 struct prefixentry entry;
1923 struct prefixlist *next;
1929 struct scopeentry entry;
1930 struct scopelist *next;
1935 free_prefixlist (struct prefixlist *list)
1937 while (list != NULL)
1939 struct prefixlist *oldp = list;
1947 free_scopelist (struct scopelist *list)
1949 while (list != NULL)
1951 struct scopelist *oldp = list;
1959 prefixcmp (const void *p1, const void *p2)
1961 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1962 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1964 if (e1->bits < e2->bits)
1966 if (e1->bits == e2->bits)
1973 scopecmp (const void *p1, const void *p2)
1975 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1976 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1978 if (e1->netmask > e2->netmask)
1980 if (e1->netmask == e2->netmask)
1989 struct prefixlist *labellist = NULL;
1990 size_t nlabellist = 0;
1991 bool labellist_nullbits = false;
1992 struct prefixlist *precedencelist = NULL;
1993 size_t nprecedencelist = 0;
1994 bool precedencelist_nullbits = false;
1995 struct scopelist *scopelist = NULL;
1996 size_t nscopelist = 0;
1997 bool scopelist_nullbits = false;
1999 FILE *fp = fopen (GAICONF_FNAME, "rce");
2003 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
2012 __fsetlocking (fp, FSETLOCKING_BYCALLER);
2014 while (!feof_unlocked (fp))
2016 ssize_t n = __getline (&line, &linelen, fp);
2020 /* Handle comments. No escaping possible so this is easy. */
2021 char *cp = strchr (line, '#');
2026 while (isspace (*cp))
2030 while (*cp != '\0' && !isspace (*cp))
2032 size_t cmdlen = cp - cmd;
2036 while (isspace (*cp))
2040 while (*cp != '\0' && !isspace (*cp))
2042 size_t val1len = cp - cmd;
2044 /* We always need at least two values. */
2050 while (isspace (*cp))
2054 while (*cp != '\0' && !isspace (*cp))
2057 /* Ignore the rest of the line. */
2060 struct prefixlist **listp;
2066 if (strcmp (cmd, "label") == 0)
2068 struct in6_addr prefix;
2069 unsigned long int bits;
2070 unsigned long int val;
2075 nullbitsp = &labellist_nullbits;
2080 cp = strchr (val1, '/');
2083 if (inet_pton (AF_INET6, val1, &prefix)
2085 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2089 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2094 struct prefixlist *newp = malloc (sizeof (*newp));
2102 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2103 newp->entry.bits = bits;
2104 newp->entry.val = val;
2105 newp->next = *listp;
2108 *nullbitsp |= bits == 0;
2114 if (strcmp (cmd, "reload") == 0)
2116 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2117 if (gaiconf_reload_flag)
2118 gaiconf_reload_flag_ever_set = 1;
2123 if (strcmp (cmd, "scopev4") == 0)
2125 struct in6_addr prefix;
2126 unsigned long int bits;
2127 unsigned long int val;
2132 cp = strchr (val1, '/');
2135 if (inet_pton (AF_INET6, val1, &prefix))
2138 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2140 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2145 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2150 struct scopelist *newp;
2152 newp = malloc (sizeof (*newp));
2160 newp->entry.netmask = htonl (bits != 96
2164 newp->entry.addr32 = (prefix.s6_addr32[3]
2165 & newp->entry.netmask);
2166 newp->entry.scope = val;
2167 newp->next = scopelist;
2170 scopelist_nullbits |= bits == 96;
2173 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2175 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2179 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2191 if (strcmp (cmd, "precedence") == 0)
2193 listp = &precedencelist;
2194 lenp = &nprecedencelist;
2195 nullbitsp = &precedencelist_nullbits;
2206 /* Create the array for the labels. */
2207 struct prefixentry *new_labels;
2210 if (!labellist_nullbits)
2212 new_labels = malloc (nlabellist * sizeof (*new_labels));
2213 if (new_labels == NULL)
2217 if (!labellist_nullbits)
2220 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2221 new_labels[i].bits = 0;
2222 new_labels[i].val = 1;
2225 struct prefixlist *l = labellist;
2228 new_labels[i] = l->entry;
2231 free_prefixlist (labellist);
2233 /* Sort the entries so that the most specific ones are at
2235 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2238 new_labels = (struct prefixentry *) default_labels;
2240 struct prefixentry *new_precedence;
2241 if (nprecedencelist > 0)
2243 if (!precedencelist_nullbits)
2245 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2246 if (new_precedence == NULL)
2248 if (new_labels != default_labels)
2253 int i = nprecedencelist;
2254 if (!precedencelist_nullbits)
2257 memset (&new_precedence[i].prefix, '\0',
2258 sizeof (struct in6_addr));
2259 new_precedence[i].bits = 0;
2260 new_precedence[i].val = 40;
2263 struct prefixlist *l = precedencelist;
2266 new_precedence[i] = l->entry;
2269 free_prefixlist (precedencelist);
2271 /* Sort the entries so that the most specific ones are at
2273 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2277 new_precedence = (struct prefixentry *) default_precedence;
2279 struct scopeentry *new_scopes;
2282 if (!scopelist_nullbits)
2284 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2285 if (new_scopes == NULL)
2287 if (new_labels != default_labels)
2289 if (new_precedence != default_precedence)
2290 free (new_precedence);
2295 if (!scopelist_nullbits)
2298 new_scopes[i].addr32 = 0;
2299 new_scopes[i].netmask = 0;
2300 new_scopes[i].scope = 14;
2303 struct scopelist *l = scopelist;
2306 new_scopes[i] = l->entry;
2309 free_scopelist (scopelist);
2311 /* Sort the entries so that the most specific ones are at
2313 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2317 new_scopes = (struct scopeentry *) default_scopes;
2319 /* Now we are ready to replace the values. */
2320 const struct prefixentry *old = labels;
2321 labels = new_labels;
2322 if (old != default_labels)
2323 free ((void *) old);
2326 precedence = new_precedence;
2327 if (old != default_precedence)
2328 free ((void *) old);
2330 const struct scopeentry *oldscope = scopes;
2331 scopes = new_scopes;
2332 if (oldscope != default_scopes)
2333 free ((void *) oldscope);
2335 save_gaiconf_mtime (&st);
2340 free_prefixlist (labellist);
2341 free_prefixlist (precedencelist);
2342 free_scopelist (scopelist);
2344 /* If we previously read the file but it is gone now, free the
2345 old data and use the builtin one. Leave the reload flag
2353 gaiconf_reload (void)
2356 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2357 || !check_gaiconf_mtime (&st))
2363 getaddrinfo (const char *name, const char *service,
2364 const struct addrinfo *hints, struct addrinfo **pai)
2366 int i = 0, last_i = 0;
2368 struct addrinfo *p = NULL;
2369 struct gaih_service gaih_service, *pservice;
2370 struct addrinfo local_hints;
2372 if (name != NULL && name[0] == '*' && name[1] == 0)
2375 if (service != NULL && service[0] == '*' && service[1] == 0)
2378 if (name == NULL && service == NULL)
2382 hints = &default_hints;
2385 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2387 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2388 |AI_IDN_USE_STD3_ASCII_RULES
2390 |AI_NUMERICSERV|AI_ALL))
2391 return EAI_BADFLAGS;
2393 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2394 return EAI_BADFLAGS;
2396 struct in6addrinfo *in6ai = NULL;
2397 size_t in6ailen = 0;
2398 bool seen_ipv4 = false;
2399 bool seen_ipv6 = false;
2400 bool check_pf_called = false;
2402 if (hints->ai_flags & AI_ADDRCONFIG)
2404 /* We might need information about what interfaces are available.
2405 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2406 cannot cache the results since new interfaces could be added at
2408 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2409 check_pf_called = true;
2411 /* Now make a decision on what we return, if anything. */
2412 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2414 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2415 narrow down the search. */
2416 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2418 local_hints = *hints;
2419 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2420 hints = &local_hints;
2423 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2424 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2426 /* We cannot possibly return a valid answer. */
2427 __free_in6ai (in6ai);
2432 if (service && service[0])
2435 gaih_service.name = service;
2436 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2439 if (hints->ai_flags & AI_NUMERICSERV)
2441 __free_in6ai (in6ai);
2445 gaih_service.num = -1;
2448 pservice = &gaih_service;
2453 struct addrinfo **end = &p;
2455 unsigned int naddrs = 0;
2456 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2457 || hints->ai_family == AF_INET6)
2459 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2463 __free_in6ai (in6ai);
2465 return -(last_i & GAIH_EAI);
2469 end = &((*end)->ai_next);
2475 __free_in6ai (in6ai);
2481 /* Read the config file. */
2482 __libc_once_define (static, once);
2483 __typeof (once) old_once = once;
2484 __libc_once (once, gaiconf_init);
2485 /* Sort results according to RFC 3484. */
2486 struct sort_result results[nresults];
2487 size_t order[nresults];
2489 struct addrinfo *last = NULL;
2490 char *canonname = NULL;
2492 /* Now we definitely need the interface information. */
2493 if (! check_pf_called)
2494 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2496 /* If we have information about deprecated and temporary addresses
2497 sort the array now. */
2499 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2504 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2506 results[i].dest_addr = q;
2507 results[i].native = -1;
2510 /* If we just looked up the address for a different
2511 protocol, reuse the result. */
2512 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2513 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2515 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2516 results[i - 1].source_addr_len);
2517 results[i].source_addr_len = results[i - 1].source_addr_len;
2518 results[i].got_source_addr = results[i - 1].got_source_addr;
2519 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2520 results[i].prefixlen = results[i - 1].prefixlen;
2521 results[i].index = results[i - 1].index;
2525 results[i].got_source_addr = false;
2526 results[i].source_addr_flags = 0;
2527 results[i].prefixlen = 0;
2528 results[i].index = 0xffffffffu;
2530 /* We overwrite the type with SOCK_DGRAM since we do not
2531 want connect() to connect to the other side. If we
2532 cannot determine the source address remember this
2534 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2538 close_not_cancel_no_status (fd);
2540 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2544 /* Reset the connection. */
2545 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2546 __connect (fd, &sa, sizeof (sa));
2549 socklen_t sl = sizeof (results[i].source_addr);
2551 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2552 && __getsockname (fd,
2553 (struct sockaddr *) &results[i].source_addr,
2556 results[i].source_addr_len = sl;
2557 results[i].got_source_addr = true;
2561 /* See whether the source address is on the list of
2562 deprecated or temporary addresses. */
2563 struct in6addrinfo tmp;
2565 if (q->ai_family == AF_INET && af == AF_INET)
2567 struct sockaddr_in *sinp
2568 = (struct sockaddr_in *) &results[i].source_addr;
2571 tmp.addr[2] = htonl (0xffff);
2572 tmp.addr[3] = sinp->sin_addr.s_addr;
2576 struct sockaddr_in6 *sin6p
2577 = (struct sockaddr_in6 *) &results[i].source_addr;
2578 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2581 struct in6addrinfo *found
2582 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2586 results[i].source_addr_flags = found->flags;
2587 results[i].prefixlen = found->prefixlen;
2588 results[i].index = found->index;
2592 if (q->ai_family == AF_INET && af == AF_INET6)
2594 /* We have to convert the address. The socket is
2595 IPv6 and the request is for IPv4. */
2596 struct sockaddr_in6 *sin6
2597 = (struct sockaddr_in6 *) &results[i].source_addr;
2598 struct sockaddr_in *sin
2599 = (struct sockaddr_in *) &results[i].source_addr;
2600 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2601 sin->sin_family = AF_INET;
2602 /* We do not have to initialize sin_port since this
2603 fields has the same position and size in the IPv6
2605 assert (offsetof (struct sockaddr_in, sin_port)
2606 == offsetof (struct sockaddr_in6, sin6_port));
2607 assert (sizeof (sin->sin_port)
2608 == sizeof (sin6->sin6_port));
2609 memcpy (&sin->sin_addr,
2610 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2611 results[i].source_addr_len = sizeof (struct sockaddr_in);
2614 else if (errno == EAFNOSUPPORT && af == AF_INET6
2615 && q->ai_family == AF_INET)
2616 /* This could mean IPv6 sockets are IPv6-only. */
2619 /* Just make sure that if we have to process the same
2620 address again we do not copy any memory. */
2621 results[i].source_addr_len = 0;
2624 /* Remember the canonical name. */
2625 if (q->ai_canonname != NULL)
2627 assert (canonname == NULL);
2628 canonname = q->ai_canonname;
2629 q->ai_canonname = NULL;
2634 close_not_cancel_no_status (fd);
2636 /* We got all the source addresses we can get, now sort using
2638 struct sort_result_combo src
2639 = { .results = results, .nresults = nresults };
2640 if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2642 __libc_lock_define_initialized (static, lock);
2644 __libc_lock_lock (lock);
2645 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2647 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2648 __libc_lock_unlock (lock);
2651 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2653 /* Queue the results up as they come out of sorting. */
2654 q = p = results[order[0]].dest_addr;
2655 for (i = 1; i < nresults; ++i)
2656 q = q->ai_next = results[order[i]].dest_addr;
2659 /* Fill in the canonical name into the new first entry. */
2660 p->ai_canonname = canonname;
2663 __free_in6ai (in6ai);
2671 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2673 libc_hidden_def (getaddrinfo)
2675 nss_interface_function (getaddrinfo)
2678 freeaddrinfo (struct addrinfo *ai)
2686 free (p->ai_canonname);
2690 libc_hidden_def (freeaddrinfo)