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
836 = __nss_lookup_function (nip, "gethostbyname4_r");
844 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
845 tmpbuflen, &rc, &herrno,
847 if (status == NSS_STATUS_SUCCESS)
849 if (status != NSS_STATUS_TRYAGAIN
850 || rc != ERANGE || herrno != NETDB_INTERNAL)
852 if (status == NSS_STATUS_TRYAGAIN
853 && herrno == TRY_AGAIN)
856 no_data = herrno == NO_DATA;
861 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
862 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
867 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
871 _res.options |= old_res_options & RES_USE_INET6;
872 result = -EAI_MEMORY;
873 goto free_and_return;
876 malloc_tmpbuf = true;
877 tmpbuflen = 2 * tmpbuflen;
881 if (status == NSS_STATUS_SUCCESS)
886 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
887 canon = (*pat)->name;
891 if ((*pat)->family == AF_INET
892 && req->ai_family == AF_INET6
893 && (req->ai_flags & AI_V4MAPPED) != 0)
895 uint32_t *pataddr = (*pat)->addr;
896 (*pat)->family = AF_INET6;
897 pataddr[3] = pataddr[0];
898 pataddr[2] = htonl (0xffff);
901 pat = &((*pat)->next);
904 else if (req->ai_family == AF_UNSPEC
905 || (*pat)->family == req->ai_family)
907 pat = &((*pat)->next);
910 if (req->ai_family == AF_INET6)
914 *pat = ((*pat)->next);
918 no_inet6_data = no_data;
922 nss_gethostbyname3_r fct = NULL;
923 if (req->ai_flags & AI_CANONNAME)
924 /* No need to use this function if we do not look for
925 the canonical name. The function does not exist in
926 all NSS modules and therefore the lookup would
928 fct = __nss_lookup_function (nip, "gethostbyname3_r");
930 /* We are cheating here. The gethostbyname2_r
931 function does not have the same interface as
932 gethostbyname3_r but the extra arguments the
933 latter takes are added at the end. So the
934 gethostbyname2_r code will just ignore them. */
935 fct = __nss_lookup_function (nip, "gethostbyname2_r");
939 if (req->ai_family == AF_INET6
940 || req->ai_family == AF_UNSPEC)
942 gethosts (AF_INET6, struct in6_addr);
943 no_inet6_data = no_data;
944 inet6_status = status;
946 if (req->ai_family == AF_INET
947 || req->ai_family == AF_UNSPEC
948 || (req->ai_family == AF_INET6
949 && (req->ai_flags & AI_V4MAPPED)
950 /* Avoid generating the mapped addresses if we
951 know we are not going to need them. */
952 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
954 gethosts (AF_INET, struct in_addr);
956 if (req->ai_family == AF_INET)
958 no_inet6_data = no_data;
959 inet6_status = status;
963 /* If we found one address for AF_INET or AF_INET6,
964 don't continue the search. */
965 if (inet6_status == NSS_STATUS_SUCCESS
966 || status == NSS_STATUS_SUCCESS)
968 if ((req->ai_flags & AI_CANONNAME) != 0
971 /* If we need the canonical name, get it
972 from the same service as the result. */
973 nss_getcanonname_r cfct;
976 cfct = __nss_lookup_function (nip,
980 const size_t max_fqdn_len = 256;
981 if ((req->ai_flags & AI_CANONIDN) != 0
982 && __libc_use_alloca (alloca_used
984 canonbuf = alloca_account (max_fqdn_len,
988 canonbuf = malloc (max_fqdn_len);
989 if (canonbuf == NULL)
992 |= old_res_options & RES_USE_INET6;
993 result = -EAI_MEMORY;
994 goto free_and_return;
996 malloc_canonbuf = true;
1000 if (DL_CALL_FCT (cfct, (at->name ?: name,
1004 == NSS_STATUS_SUCCESS)
1008 /* Set to name now to avoid using
1010 if (malloc_canonbuf)
1013 malloc_canonbuf = false;
1019 status = NSS_STATUS_SUCCESS;
1023 /* We can have different states for AF_INET and
1024 AF_INET6. Try to find a useful one for both. */
1025 if (inet6_status == NSS_STATUS_TRYAGAIN)
1026 status = NSS_STATUS_TRYAGAIN;
1027 else if (status == NSS_STATUS_UNAVAIL
1028 && inet6_status != NSS_STATUS_UNAVAIL)
1029 status = inet6_status;
1033 status = NSS_STATUS_UNAVAIL;
1036 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1039 if (nip->next == NULL)
1045 _res.options |= old_res_options & RES_USE_INET6;
1047 if (no_data != 0 && no_inet6_data != 0)
1049 /* If both requests timed out report this. */
1050 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1051 result = -EAI_AGAIN;
1053 /* We made requests but they turned out no data. The name
1054 is known, though. */
1055 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1057 goto free_and_return;
1062 if (at->family == AF_UNSPEC)
1064 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1065 goto free_and_return;
1070 struct gaih_addrtuple *atr;
1071 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1072 memset (at, '\0', sizeof (struct gaih_addrtuple));
1074 if (req->ai_family == AF_UNSPEC)
1076 at->next = __alloca (sizeof (struct gaih_addrtuple));
1077 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1080 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1082 at->family = AF_INET6;
1083 if ((req->ai_flags & AI_PASSIVE) == 0)
1084 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1088 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1090 atr->family = AF_INET;
1091 if ((req->ai_flags & AI_PASSIVE) == 0)
1092 atr->addr[0] = htonl (INADDR_LOOPBACK);
1097 struct gaih_servtuple *st2;
1098 struct gaih_addrtuple *at2 = at;
1103 buffer is the size of an unformatted IPv6 address in printable format.
1107 /* Only the first entry gets the canonical name. */
1108 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1110 char *tmpbuf2 = NULL;
1111 bool malloc_tmpbuf2 = false;
1115 struct hostent *h = NULL;
1118 /* Add room for struct host_data. */
1119 size_t tmpbuf2len = (512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1)
1120 * sizeof(char*) + 16 * sizeof(char));
1124 if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1125 tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1130 char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1136 result = -EAI_MEMORY;
1137 goto free_and_return;
1141 tmpbuf2len = 2 * tmpbuf2len;
1142 malloc_tmpbuf2 = true;
1145 rc = __gethostbyaddr_r (at2->addr,
1146 ((at2->family == AF_INET6)
1147 ? sizeof (struct in6_addr)
1148 : sizeof (struct in_addr)),
1149 at2->family, &th, tmpbuf2,
1150 tmpbuf2len, &h, &herrno);
1152 while (rc == ERANGE && herrno == NETDB_INTERNAL);
1154 if (rc != 0 && herrno == NETDB_INTERNAL)
1159 __set_h_errno (herrno);
1160 result = -EAI_SYSTEM;
1161 goto free_and_return;
1168 assert (orig_name != NULL);
1169 /* If the canonical name cannot be determined, use
1170 the passed in string. */
1176 if (req->ai_flags & AI_CANONIDN)
1179 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1180 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1181 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1182 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1185 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1186 if (rc != IDNA_SUCCESS)
1191 if (rc == IDNA_MALLOC_ERROR)
1192 result = -EAI_MEMORY;
1193 else if (rc == IDNA_DLOPEN_ERROR)
1194 result = -EAI_SYSTEM;
1196 result = -EAI_IDN_ENCODE;
1197 goto free_and_return;
1199 /* In case the output string is the same as the input
1200 string no new string has been allocated and we
1212 if (malloc_canonbuf)
1213 /* We already allocated the string using malloc. */
1214 malloc_canonbuf = false;
1217 canon = strdup (canon);
1223 result = -EAI_MEMORY;
1224 goto free_and_return;
1233 family = at2->family;
1234 if (family == AF_INET6)
1236 socklen = sizeof (struct sockaddr_in6);
1238 /* If we looked up IPv4 mapped address discard them here if
1239 the caller isn't interested in all address and we have
1240 found at least one IPv6 address. */
1242 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1243 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1247 socklen = sizeof (struct sockaddr_in);
1249 for (st2 = st; st2 != NULL; st2 = st2->next)
1251 struct addrinfo *ai;
1252 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1255 free ((char *) canon);
1256 result = -EAI_MEMORY;
1257 goto free_and_return;
1260 ai->ai_flags = req->ai_flags;
1261 ai->ai_family = family;
1262 ai->ai_socktype = st2->socktype;
1263 ai->ai_protocol = st2->protocol;
1264 ai->ai_addrlen = socklen;
1265 ai->ai_addr = (void *) (ai + 1);
1267 /* We only add the canonical name once. */
1268 ai->ai_canonname = (char *) canon;
1272 ai->ai_addr->sa_len = socklen;
1273 #endif /* _HAVE_SA_LEN */
1274 ai->ai_addr->sa_family = family;
1276 /* In case of an allocation error the list must be NULL
1280 if (family == AF_INET6)
1282 struct sockaddr_in6 *sin6p =
1283 (struct sockaddr_in6 *) ai->ai_addr;
1285 sin6p->sin6_port = st2->port;
1286 sin6p->sin6_flowinfo = 0;
1287 memcpy (&sin6p->sin6_addr,
1288 at2->addr, sizeof (struct in6_addr));
1289 sin6p->sin6_scope_id = at2->scopeid;
1293 struct sockaddr_in *sinp =
1294 (struct sockaddr_in *) ai->ai_addr;
1295 sinp->sin_port = st2->port;
1296 memcpy (&sinp->sin_addr,
1297 at2->addr, sizeof (struct in_addr));
1298 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1301 pai = &(ai->ai_next);
1313 free ((char *) name);
1316 if (malloc_canonbuf)
1327 struct addrinfo *dest_addr;
1328 /* Using sockaddr_storage is for now overkill. We only support IPv4
1329 and IPv6 so far. If this changes at some point we can adjust the
1331 struct sockaddr_in6 source_addr;
1332 uint8_t source_addr_len;
1333 bool got_source_addr;
1334 uint8_t source_addr_flags;
1340 struct sort_result_combo
1342 struct sort_result *results;
1347 #if __BYTE_ORDER == __BIG_ENDIAN
1348 # define htonl_c(n) n
1350 # define htonl_c(n) __bswap_constant_32 (n)
1353 static const struct scopeentry
1362 } default_scopes[] =
1364 /* Link-local addresses: scope 2. */
1365 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1366 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1367 /* Site-local addresses: scope 5. */
1368 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1369 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1370 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1371 /* Default: scope 14. */
1372 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1375 /* The label table. */
1376 static const struct scopeentry *scopes;
1380 get_scope (const struct sockaddr_in6 *in6)
1383 if (in6->sin6_family == PF_INET6)
1385 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1387 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1388 /* RFC 4291 2.5.3 says that the loopback address is to be
1389 treated like a link-local address. */
1390 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1392 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1395 /* XXX Is this the correct default behavior? */
1399 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1401 else if (in6->sin6_family == PF_INET)
1403 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1408 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1409 == scopes[cnt].addr32)
1410 return scopes[cnt].scope;
1417 /* XXX What is a good default? */
1426 struct in6_addr prefix;
1432 /* The label table. */
1433 static const struct prefixentry *labels;
1435 /* Default labels. */
1436 static const struct prefixentry default_labels[] =
1438 /* See RFC 3484 for the details. */
1440 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1444 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1448 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1452 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1455 /* The next two entries differ from RFC 3484. We need to treat
1456 IPv6 site-local addresses special because they are never NATed,
1457 unlike site-locale IPv4 addresses. If this would not happen, on
1458 machines which have only IPv4 and IPv6 site-local addresses, the
1459 sorting would prefer the IPv6 site-local addresses, causing
1460 unnecessary delays when trying to connect to a global IPv6 address
1461 through a site-local IPv6 address. */
1463 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1467 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1470 /* Additional rule for Teredo tunnels. */
1472 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1476 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1482 /* The precedence table. */
1483 static const struct prefixentry *precedence;
1485 /* The default precedences. */
1486 static const struct prefixentry default_precedence[] =
1488 /* See RFC 3484 for the details. */
1490 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1494 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1495 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1498 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1502 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1503 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1506 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1513 match_prefix (const struct sockaddr_in6 *in6,
1514 const struct prefixentry *list, int default_val)
1517 struct sockaddr_in6 in6_mem;
1519 if (in6->sin6_family == PF_INET)
1521 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1523 /* Construct a V4-to-6 mapped address. */
1524 in6_mem.sin6_family = PF_INET6;
1525 in6_mem.sin6_port = in->sin_port;
1526 in6_mem.sin6_flowinfo = 0;
1527 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1528 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1529 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1530 in6_mem.sin6_scope_id = 0;
1534 else if (in6->sin6_family != PF_INET6)
1537 for (idx = 0; ; ++idx)
1539 unsigned int bits = list[idx].bits;
1540 const uint8_t *mask = list[idx].prefix.s6_addr;
1541 const uint8_t *val = in6->sin6_addr.s6_addr;
1555 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1561 return list[idx].val;
1566 get_label (const struct sockaddr_in6 *in6)
1568 /* XXX What is a good default value? */
1569 return match_prefix (in6, labels, INT_MAX);
1574 get_precedence (const struct sockaddr_in6 *in6)
1576 /* XXX What is a good default value? */
1577 return match_prefix (in6, precedence, 0);
1581 /* Find last bit set in a word. */
1587 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1588 if ((a & mask) != 0)
1595 rfc3484_sort (const void *p1, const void *p2, void *arg)
1597 const size_t idx1 = *(const size_t *) p1;
1598 const size_t idx2 = *(const size_t *) p2;
1599 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1600 struct sort_result *a1 = &src->results[idx1];
1601 struct sort_result *a2 = &src->results[idx2];
1603 /* Rule 1: Avoid unusable destinations.
1604 We have the got_source_addr flag set if the destination is reachable. */
1605 if (a1->got_source_addr && ! a2->got_source_addr)
1607 if (! a1->got_source_addr && a2->got_source_addr)
1611 /* Rule 2: Prefer matching scope. Only interesting if both
1612 destination addresses are IPv6. */
1614 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1617 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1619 if (a1->got_source_addr)
1621 int a1_src_scope = get_scope (&a1->source_addr);
1622 int a2_src_scope = get_scope (&a2->source_addr);
1624 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1626 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1631 /* Rule 3: Avoid deprecated addresses. */
1632 if (a1->got_source_addr)
1634 if (!(a1->source_addr_flags & in6ai_deprecated)
1635 && (a2->source_addr_flags & in6ai_deprecated))
1637 if ((a1->source_addr_flags & in6ai_deprecated)
1638 && !(a2->source_addr_flags & in6ai_deprecated))
1642 /* Rule 4: Prefer home addresses. */
1643 if (a1->got_source_addr)
1645 if (!(a1->source_addr_flags & in6ai_homeaddress)
1646 && (a2->source_addr_flags & in6ai_homeaddress))
1648 if ((a1->source_addr_flags & in6ai_homeaddress)
1649 && !(a2->source_addr_flags & in6ai_homeaddress))
1653 /* Rule 5: Prefer matching label. */
1654 if (a1->got_source_addr)
1657 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1658 int a1_src_label = get_label (&a1->source_addr);
1661 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1662 int a2_src_label = get_label (&a2->source_addr);
1664 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1666 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1671 /* Rule 6: Prefer higher precedence. */
1673 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1675 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1677 if (a1_prec > a2_prec)
1679 if (a1_prec < a2_prec)
1683 /* Rule 7: Prefer native transport. */
1684 if (a1->got_source_addr)
1686 /* The same interface index means the same interface which means
1687 there is no difference in transport. This should catch many
1689 if (a1->index != a2->index)
1691 int a1_native = a1->native;
1692 int a2_native = a2->native;
1694 if (a1_native == -1 || a2_native == -1)
1697 if (a1_native == -1)
1699 /* If we do not have the information use 'native' as
1702 a1_index = a1->index;
1705 a1_index = 0xffffffffu;
1708 if (a2_native == -1)
1710 /* If we do not have the information use 'native' as
1713 a2_index = a2->index;
1716 a2_index = 0xffffffffu;
1718 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1720 /* Fill in the results in all the records. */
1721 for (int i = 0; i < src->nresults; ++i)
1722 if (src->results[i].index == a1_index)
1724 assert (src->results[i].native == -1
1725 || src->results[i].native == a1_native);
1726 src->results[i].native = a1_native;
1728 else if (src->results[i].index == a2_index)
1730 assert (src->results[i].native == -1
1731 || src->results[i].native == a2_native);
1732 src->results[i].native = a2_native;
1736 if (a1_native && !a2_native)
1738 if (!a1_native && a2_native)
1744 /* Rule 8: Prefer smaller scope. */
1745 if (a1_dst_scope < a2_dst_scope)
1747 if (a1_dst_scope > a2_dst_scope)
1751 /* Rule 9: Use longest matching prefix. */
1752 if (a1->got_source_addr
1753 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1758 if (a1->dest_addr->ai_family == PF_INET)
1760 assert (a1->source_addr.sin6_family == PF_INET);
1761 assert (a2->source_addr.sin6_family == PF_INET);
1763 /* Outside of subnets, as defined by the network masks,
1764 common address prefixes for IPv4 addresses make no sense.
1765 So, define a non-zero value only if source and
1766 destination address are on the same subnet. */
1767 struct sockaddr_in *in1_dst
1768 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1769 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1770 struct sockaddr_in *in1_src
1771 = (struct sockaddr_in *) &a1->source_addr;
1772 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1773 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1775 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1776 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1778 struct sockaddr_in *in2_dst
1779 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1780 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1781 struct sockaddr_in *in2_src
1782 = (struct sockaddr_in *) &a2->source_addr;
1783 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1784 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1786 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1787 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1789 else if (a1->dest_addr->ai_family == PF_INET6)
1791 assert (a1->source_addr.sin6_family == PF_INET6);
1792 assert (a2->source_addr.sin6_family == PF_INET6);
1794 struct sockaddr_in6 *in1_dst;
1795 struct sockaddr_in6 *in1_src;
1796 struct sockaddr_in6 *in2_dst;
1797 struct sockaddr_in6 *in2_src;
1799 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1800 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1801 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1802 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1805 for (i = 0; i < 4; ++i)
1806 if (in1_dst->sin6_addr.s6_addr32[i]
1807 != in1_src->sin6_addr.s6_addr32[i]
1808 || (in2_dst->sin6_addr.s6_addr32[i]
1809 != in2_src->sin6_addr.s6_addr32[i]))
1814 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1815 ^ in1_src->sin6_addr.s6_addr32[i]));
1816 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1817 ^ in2_src->sin6_addr.s6_addr32[i]));
1828 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1829 compare with the value indicating the order in which the entries
1830 have been received from the services. NB: no two entries can have
1831 the same order so the test will never return zero. */
1832 return idx1 < idx2 ? -1 : 1;
1837 in6aicmp (const void *p1, const void *p2)
1839 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1840 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1842 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1846 /* Name of the config file for RFC 3484 sorting (for now). */
1847 #define GAICONF_FNAME "/etc/gai.conf"
1850 /* Non-zero if we are supposed to reload the config file automatically
1851 whenever it changed. */
1852 static int gaiconf_reload_flag;
1854 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1855 static int gaiconf_reload_flag_ever_set;
1857 /* Last modification time. */
1858 #ifdef _STATBUF_ST_NSEC
1860 static struct timespec gaiconf_mtime;
1863 save_gaiconf_mtime (const struct stat64 *st)
1865 gaiconf_mtime = st->st_mtim;
1869 check_gaiconf_mtime (const struct stat64 *st)
1871 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1872 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1877 static time_t gaiconf_mtime;
1880 save_gaiconf_mtime (const struct stat64 *st)
1882 gaiconf_mtime = st->st_mtime;
1886 check_gaiconf_mtime (const struct stat64 *st)
1888 return st->mtime == gaiconf_mtime;
1894 libc_freeres_fn(fini)
1896 if (labels != default_labels)
1898 const struct prefixentry *old = labels;
1899 labels = default_labels;
1900 free ((void *) old);
1903 if (precedence != default_precedence)
1905 const struct prefixentry *old = precedence;
1906 precedence = default_precedence;
1907 free ((void *) old);
1910 if (scopes != default_scopes)
1912 const struct scopeentry *old = scopes;
1913 scopes = default_scopes;
1914 free ((void *) old);
1921 struct prefixentry entry;
1922 struct prefixlist *next;
1928 struct scopeentry entry;
1929 struct scopelist *next;
1934 free_prefixlist (struct prefixlist *list)
1936 while (list != NULL)
1938 struct prefixlist *oldp = list;
1946 free_scopelist (struct scopelist *list)
1948 while (list != NULL)
1950 struct scopelist *oldp = list;
1958 prefixcmp (const void *p1, const void *p2)
1960 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1961 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1963 if (e1->bits < e2->bits)
1965 if (e1->bits == e2->bits)
1972 scopecmp (const void *p1, const void *p2)
1974 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1975 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1977 if (e1->netmask > e2->netmask)
1979 if (e1->netmask == e2->netmask)
1988 struct prefixlist *labellist = NULL;
1989 size_t nlabellist = 0;
1990 bool labellist_nullbits = false;
1991 struct prefixlist *precedencelist = NULL;
1992 size_t nprecedencelist = 0;
1993 bool precedencelist_nullbits = false;
1994 struct scopelist *scopelist = NULL;
1995 size_t nscopelist = 0;
1996 bool scopelist_nullbits = false;
1998 FILE *fp = fopen (GAICONF_FNAME, "rce");
2002 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
2011 __fsetlocking (fp, FSETLOCKING_BYCALLER);
2013 while (!feof_unlocked (fp))
2015 ssize_t n = __getline (&line, &linelen, fp);
2019 /* Handle comments. No escaping possible so this is easy. */
2020 char *cp = strchr (line, '#');
2025 while (isspace (*cp))
2029 while (*cp != '\0' && !isspace (*cp))
2031 size_t cmdlen = cp - cmd;
2035 while (isspace (*cp))
2039 while (*cp != '\0' && !isspace (*cp))
2041 size_t val1len = cp - cmd;
2043 /* We always need at least two values. */
2049 while (isspace (*cp))
2053 while (*cp != '\0' && !isspace (*cp))
2056 /* Ignore the rest of the line. */
2059 struct prefixlist **listp;
2065 if (strcmp (cmd, "label") == 0)
2067 struct in6_addr prefix;
2068 unsigned long int bits;
2069 unsigned long int val;
2074 nullbitsp = &labellist_nullbits;
2079 cp = strchr (val1, '/');
2082 if (inet_pton (AF_INET6, val1, &prefix)
2084 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2088 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2093 struct prefixlist *newp = malloc (sizeof (*newp));
2101 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2102 newp->entry.bits = bits;
2103 newp->entry.val = val;
2104 newp->next = *listp;
2107 *nullbitsp |= bits == 0;
2113 if (strcmp (cmd, "reload") == 0)
2115 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2116 if (gaiconf_reload_flag)
2117 gaiconf_reload_flag_ever_set = 1;
2122 if (strcmp (cmd, "scopev4") == 0)
2124 struct in6_addr prefix;
2125 unsigned long int bits;
2126 unsigned long int val;
2131 cp = strchr (val1, '/');
2134 if (inet_pton (AF_INET6, val1, &prefix))
2137 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2139 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2144 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2149 struct scopelist *newp;
2151 newp = malloc (sizeof (*newp));
2159 newp->entry.netmask = htonl (bits != 96
2163 newp->entry.addr32 = (prefix.s6_addr32[3]
2164 & newp->entry.netmask);
2165 newp->entry.scope = val;
2166 newp->next = scopelist;
2169 scopelist_nullbits |= bits == 96;
2172 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2174 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2178 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2190 if (strcmp (cmd, "precedence") == 0)
2192 listp = &precedencelist;
2193 lenp = &nprecedencelist;
2194 nullbitsp = &precedencelist_nullbits;
2205 /* Create the array for the labels. */
2206 struct prefixentry *new_labels;
2209 if (!labellist_nullbits)
2211 new_labels = malloc (nlabellist * sizeof (*new_labels));
2212 if (new_labels == NULL)
2216 if (!labellist_nullbits)
2219 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2220 new_labels[i].bits = 0;
2221 new_labels[i].val = 1;
2224 struct prefixlist *l = labellist;
2227 new_labels[i] = l->entry;
2230 free_prefixlist (labellist);
2232 /* Sort the entries so that the most specific ones are at
2234 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2237 new_labels = (struct prefixentry *) default_labels;
2239 struct prefixentry *new_precedence;
2240 if (nprecedencelist > 0)
2242 if (!precedencelist_nullbits)
2244 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2245 if (new_precedence == NULL)
2247 if (new_labels != default_labels)
2252 int i = nprecedencelist;
2253 if (!precedencelist_nullbits)
2256 memset (&new_precedence[i].prefix, '\0',
2257 sizeof (struct in6_addr));
2258 new_precedence[i].bits = 0;
2259 new_precedence[i].val = 40;
2262 struct prefixlist *l = precedencelist;
2265 new_precedence[i] = l->entry;
2268 free_prefixlist (precedencelist);
2270 /* Sort the entries so that the most specific ones are at
2272 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2276 new_precedence = (struct prefixentry *) default_precedence;
2278 struct scopeentry *new_scopes;
2281 if (!scopelist_nullbits)
2283 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2284 if (new_scopes == NULL)
2286 if (new_labels != default_labels)
2288 if (new_precedence != default_precedence)
2289 free (new_precedence);
2294 if (!scopelist_nullbits)
2297 new_scopes[i].addr32 = 0;
2298 new_scopes[i].netmask = 0;
2299 new_scopes[i].scope = 14;
2302 struct scopelist *l = scopelist;
2305 new_scopes[i] = l->entry;
2308 free_scopelist (scopelist);
2310 /* Sort the entries so that the most specific ones are at
2312 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2316 new_scopes = (struct scopeentry *) default_scopes;
2318 /* Now we are ready to replace the values. */
2319 const struct prefixentry *old = labels;
2320 labels = new_labels;
2321 if (old != default_labels)
2322 free ((void *) old);
2325 precedence = new_precedence;
2326 if (old != default_precedence)
2327 free ((void *) old);
2329 const struct scopeentry *oldscope = scopes;
2330 scopes = new_scopes;
2331 if (oldscope != default_scopes)
2332 free ((void *) oldscope);
2334 save_gaiconf_mtime (&st);
2339 free_prefixlist (labellist);
2340 free_prefixlist (precedencelist);
2341 free_scopelist (scopelist);
2343 /* If we previously read the file but it is gone now, free the
2344 old data and use the builtin one. Leave the reload flag
2352 gaiconf_reload (void)
2355 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2356 || !check_gaiconf_mtime (&st))
2362 getaddrinfo (const char *name, const char *service,
2363 const struct addrinfo *hints, struct addrinfo **pai)
2365 int i = 0, last_i = 0;
2367 struct addrinfo *p = NULL;
2368 struct gaih_service gaih_service, *pservice;
2369 struct addrinfo local_hints;
2371 if (name != NULL && name[0] == '*' && name[1] == 0)
2374 if (service != NULL && service[0] == '*' && service[1] == 0)
2377 if (name == NULL && service == NULL)
2381 hints = &default_hints;
2384 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2386 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2387 |AI_IDN_USE_STD3_ASCII_RULES
2389 |AI_NUMERICSERV|AI_ALL))
2390 return EAI_BADFLAGS;
2392 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2393 return EAI_BADFLAGS;
2395 struct in6addrinfo *in6ai = NULL;
2396 size_t in6ailen = 0;
2397 bool seen_ipv4 = false;
2398 bool seen_ipv6 = false;
2399 bool check_pf_called = false;
2401 if (hints->ai_flags & AI_ADDRCONFIG)
2403 /* We might need information about what interfaces are available.
2404 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2405 cannot cache the results since new interfaces could be added at
2407 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2408 check_pf_called = true;
2410 /* Now make a decision on what we return, if anything. */
2411 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2413 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2414 narrow down the search. */
2415 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2417 local_hints = *hints;
2418 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2419 hints = &local_hints;
2422 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2423 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2425 /* We cannot possibly return a valid answer. */
2426 __free_in6ai (in6ai);
2431 if (service && service[0])
2434 gaih_service.name = service;
2435 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2438 if (hints->ai_flags & AI_NUMERICSERV)
2440 __free_in6ai (in6ai);
2444 gaih_service.num = -1;
2447 pservice = &gaih_service;
2452 struct addrinfo **end = &p;
2454 unsigned int naddrs = 0;
2455 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2456 || hints->ai_family == AF_INET6)
2458 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2462 __free_in6ai (in6ai);
2464 return -(last_i & GAIH_EAI);
2468 end = &((*end)->ai_next);
2474 __free_in6ai (in6ai);
2480 /* Read the config file. */
2481 __libc_once_define (static, once);
2482 __typeof (once) old_once = once;
2483 __libc_once (once, gaiconf_init);
2484 /* Sort results according to RFC 3484. */
2485 struct sort_result results[nresults];
2486 size_t order[nresults];
2488 struct addrinfo *last = NULL;
2489 char *canonname = NULL;
2491 /* Now we definitely need the interface information. */
2492 if (! check_pf_called)
2493 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2495 /* If we have information about deprecated and temporary addresses
2496 sort the array now. */
2498 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2503 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2505 results[i].dest_addr = q;
2506 results[i].native = -1;
2509 /* If we just looked up the address for a different
2510 protocol, reuse the result. */
2511 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2512 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2514 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2515 results[i - 1].source_addr_len);
2516 results[i].source_addr_len = results[i - 1].source_addr_len;
2517 results[i].got_source_addr = results[i - 1].got_source_addr;
2518 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2519 results[i].prefixlen = results[i - 1].prefixlen;
2520 results[i].index = results[i - 1].index;
2524 results[i].got_source_addr = false;
2525 results[i].source_addr_flags = 0;
2526 results[i].prefixlen = 0;
2527 results[i].index = 0xffffffffu;
2529 /* We overwrite the type with SOCK_DGRAM since we do not
2530 want connect() to connect to the other side. If we
2531 cannot determine the source address remember this
2533 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2537 close_not_cancel_no_status (fd);
2539 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2543 /* Reset the connection. */
2544 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2545 __connect (fd, &sa, sizeof (sa));
2548 socklen_t sl = sizeof (results[i].source_addr);
2550 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2551 && __getsockname (fd,
2552 (struct sockaddr *) &results[i].source_addr,
2555 results[i].source_addr_len = sl;
2556 results[i].got_source_addr = true;
2560 /* See whether the source address is on the list of
2561 deprecated or temporary addresses. */
2562 struct in6addrinfo tmp;
2564 if (q->ai_family == AF_INET && af == AF_INET)
2566 struct sockaddr_in *sinp
2567 = (struct sockaddr_in *) &results[i].source_addr;
2570 tmp.addr[2] = htonl (0xffff);
2571 tmp.addr[3] = sinp->sin_addr.s_addr;
2575 struct sockaddr_in6 *sin6p
2576 = (struct sockaddr_in6 *) &results[i].source_addr;
2577 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2580 struct in6addrinfo *found
2581 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2585 results[i].source_addr_flags = found->flags;
2586 results[i].prefixlen = found->prefixlen;
2587 results[i].index = found->index;
2591 if (q->ai_family == AF_INET && af == AF_INET6)
2593 /* We have to convert the address. The socket is
2594 IPv6 and the request is for IPv4. */
2595 struct sockaddr_in6 *sin6
2596 = (struct sockaddr_in6 *) &results[i].source_addr;
2597 struct sockaddr_in *sin
2598 = (struct sockaddr_in *) &results[i].source_addr;
2599 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2600 sin->sin_family = AF_INET;
2601 /* We do not have to initialize sin_port since this
2602 fields has the same position and size in the IPv6
2604 assert (offsetof (struct sockaddr_in, sin_port)
2605 == offsetof (struct sockaddr_in6, sin6_port));
2606 assert (sizeof (sin->sin_port)
2607 == sizeof (sin6->sin6_port));
2608 memcpy (&sin->sin_addr,
2609 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2610 results[i].source_addr_len = sizeof (struct sockaddr_in);
2613 else if (errno == EAFNOSUPPORT && af == AF_INET6
2614 && q->ai_family == AF_INET)
2615 /* This could mean IPv6 sockets are IPv6-only. */
2618 /* Just make sure that if we have to process the same
2619 address again we do not copy any memory. */
2620 results[i].source_addr_len = 0;
2623 /* Remember the canonical name. */
2624 if (q->ai_canonname != NULL)
2626 assert (canonname == NULL);
2627 canonname = q->ai_canonname;
2628 q->ai_canonname = NULL;
2633 close_not_cancel_no_status (fd);
2635 /* We got all the source addresses we can get, now sort using
2637 struct sort_result_combo src
2638 = { .results = results, .nresults = nresults };
2639 if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2641 __libc_lock_define_initialized (static, lock);
2643 __libc_lock_lock (lock);
2644 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2646 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2647 __libc_lock_unlock (lock);
2650 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2652 /* Queue the results up as they come out of sorting. */
2653 q = p = results[order[0]].dest_addr;
2654 for (i = 1; i < nresults; ++i)
2655 q = q->ai_next = results[order[i]].dest_addr;
2658 /* Fill in the canonical name into the new first entry. */
2659 p->ai_canonname = canonname;
2662 __free_in6ai (in6ai);
2670 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2672 libc_hidden_def (getaddrinfo)
2674 static_link_warning (getaddrinfo)
2677 freeaddrinfo (struct addrinfo *ai)
2685 free (p->ai_canonname);
2689 libc_hidden_def (freeaddrinfo)