1 /* The Inner Net License, Version 2.00
3 The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
7 0. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
11 1. All terms of the all other applicable copyrights and licenses must be
13 2. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20 may be used to endorse or promote products derived from this software
21 without specific prior written permission.
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 If these license terms cause you a real problem, contact the author. */
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
47 #include <stdio_ext.h>
51 #include <arpa/inet.h>
53 #include <netinet/in.h>
54 #include <sys/socket.h>
56 #include <sys/types.h>
58 #include <sys/utsname.h>
61 #include <bits/libc-lock.h>
62 #include <not-cancel.h>
63 #include <nscd/nscd-client.h>
64 #include <nscd/nscd_proto.h>
65 #include <resolv/res_hconf.h>
68 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
69 extern int __idna_to_unicode_lzlz (const char *input, char **output,
71 # include <libidn/idna.h>
74 #define GAIH_OKIFUNSPEC 0x0100
75 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
78 # define UNIX_PATH_MAX 108
89 struct gaih_servtuple *next;
95 static const struct gaih_servtuple nullserv;
107 /* Values for `protoflag'. */
108 #define GAI_PROTO_NOSERVICE 1
109 #define GAI_PROTO_PROTOANY 2
111 static const struct gaih_typeproto gaih_inet_typeproto[] =
113 { 0, 0, 0, false, "" },
114 { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
115 { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
116 #if defined SOCK_DCCP && defined IPPROTO_DCCP
117 { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
119 #ifdef IPPROTO_UDPLITE
120 { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
123 { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
124 { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
126 { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
127 { 0, 0, 0, false, "" }
133 int (*gaih)(const char *name, const struct gaih_service *service,
134 const struct addrinfo *req, struct addrinfo **pai,
135 unsigned int *naddrs);
138 static const struct addrinfo default_hints =
140 .ai_flags = AI_DEFAULT,
141 .ai_family = PF_UNSPEC,
146 .ai_canonname = NULL,
152 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
153 const struct addrinfo *req, struct gaih_servtuple *st)
156 size_t tmpbuflen = 1024;
163 tmpbuf = __alloca (tmpbuflen);
165 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
167 if (r != 0 || s == NULL)
172 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
178 st->socktype = tp->socktype;
179 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
180 ? req->ai_protocol : tp->protocol);
181 st->port = s->s_port;
186 #define gethosts(_family, _type) \
192 char *localcanon = NULL; \
196 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
197 &rc, &herrno, NULL, &localcanon)); \
198 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
200 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
202 if (status == NSS_STATUS_SUCCESS && rc == 0) \
208 if (herrno == NETDB_INTERNAL) \
210 __set_h_errno (herrno); \
211 _res.options |= old_res_options & RES_USE_INET6; \
212 return -EAI_SYSTEM; \
214 if (herrno == TRY_AGAIN) \
215 no_data = EAI_AGAIN; \
217 no_data = herrno == NO_DATA; \
219 else if (h != NULL) \
221 for (i = 0; h->h_addr_list[i]; i++) \
225 *pat = __alloca (sizeof (struct gaih_addrtuple)); \
226 (*pat)->scopeid = 0; \
228 uint32_t *addr = (*pat)->addr; \
229 (*pat)->next = NULL; \
230 (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
231 if (_family == AF_INET && req->ai_family == AF_INET6) \
233 (*pat)->family = AF_INET6; \
234 addr[3] = *(uint32_t *) h->h_addr_list[i]; \
235 addr[2] = htonl (0xffff); \
241 (*pat)->family = _family; \
242 memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
244 pat = &((*pat)->next); \
247 if (localcanon != NULL && canon == NULL) \
248 canon = strdupa (localcanon); \
250 if (_family == AF_INET6 && i > 0) \
256 typedef enum nss_status (*nss_gethostbyname4_r)
257 (const char *name, struct gaih_addrtuple **pat,
258 char *buffer, size_t buflen, int *errnop,
259 int *h_errnop, int32_t *ttlp);
260 typedef enum nss_status (*nss_gethostbyname3_r)
261 (const char *name, int af, struct hostent *host,
262 char *buffer, size_t buflen, int *errnop,
263 int *h_errnop, int32_t *ttlp, char **canonp);
264 typedef enum nss_status (*nss_getcanonname_r)
265 (const char *name, char *buffer, size_t buflen, char **result,
266 int *errnop, int *h_errnop);
267 extern service_user *__nss_hosts_database attribute_hidden;
271 gaih_inet (const char *name, const struct gaih_service *service,
272 const struct addrinfo *req, struct addrinfo **pai,
273 unsigned int *naddrs)
275 const struct gaih_typeproto *tp = gaih_inet_typeproto;
276 struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
277 struct gaih_addrtuple *at = NULL;
279 bool got_ipv6 = false;
280 const char *canon = NULL;
281 const char *orig_name = name;
282 size_t alloca_used = 0;
284 if (req->ai_protocol || req->ai_socktype)
289 && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
290 || (req->ai_protocol != 0
291 && !(tp->protoflag & GAI_PROTO_PROTOANY)
292 && req->ai_protocol != tp->protocol)))
297 if (req->ai_socktype)
298 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
300 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
307 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
308 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
310 if (service->num < 0)
314 st = (struct gaih_servtuple *)
315 alloca_account (sizeof (struct gaih_servtuple), alloca_used);
317 if ((rc = gaih_inet_serv (service->name, tp, req, st)))
322 struct gaih_servtuple **pst = &st;
323 for (tp++; tp->name[0]; tp++)
325 struct gaih_servtuple *newp;
327 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
330 if (req->ai_socktype != 0
331 && req->ai_socktype != tp->socktype)
333 if (req->ai_protocol != 0
334 && !(tp->protoflag & GAI_PROTO_PROTOANY)
335 && req->ai_protocol != tp->protocol)
338 newp = (struct gaih_servtuple *)
339 alloca_account (sizeof (struct gaih_servtuple),
342 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
344 if (rc & GAIH_OKIFUNSPEC)
352 if (st == (struct gaih_servtuple *) &nullserv)
353 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
358 port = htons (service->num);
366 if (req->ai_socktype || req->ai_protocol)
368 st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
370 st->socktype = tp->socktype;
371 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
372 ? req->ai_protocol : tp->protocol);
377 /* Neither socket type nor protocol is set. Return all socket types
379 struct gaih_servtuple **lastp = &st;
380 for (++tp; tp->name[0]; ++tp)
383 struct gaih_servtuple *newp;
385 newp = alloca_account (sizeof (struct gaih_servtuple),
388 newp->socktype = tp->socktype;
389 newp->protocol = tp->protocol;
398 bool malloc_name = false;
399 bool malloc_addrmem = false;
400 struct gaih_addrtuple *addrmem = NULL;
401 bool malloc_canonbuf = false;
402 char *canonbuf = NULL;
403 bool malloc_tmpbuf = false;
408 at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
409 at->family = AF_UNSPEC;
414 if (req->ai_flags & AI_IDN)
417 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
418 idn_flags |= IDNA_ALLOW_UNASSIGNED;
419 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
420 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
423 rc = __idna_to_ascii_lz (name, &p, idn_flags);
424 if (rc != IDNA_SUCCESS)
426 /* No need to jump to free_and_return here. */
427 if (rc == IDNA_MALLOC_ERROR)
429 if (rc == IDNA_DLOPEN_ERROR)
431 return -EAI_IDN_ENCODE;
433 /* In case the output string is the same as the input string
434 no new string has been allocated. */
443 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
445 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
446 at->family = AF_INET;
447 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
449 at->addr[3] = at->addr[0];
450 at->addr[2] = htonl (0xffff);
453 at->family = AF_INET6;
457 result = -EAI_ADDRFAMILY;
458 goto free_and_return;
461 if (req->ai_flags & AI_CANONNAME)
464 else if (at->family == AF_UNSPEC)
466 char *scope_delim = strchr (name, SCOPE_DELIMITER);
470 bool malloc_namebuf = false;
471 char *namebuf = (char *) name;
473 if (__builtin_expect (scope_delim != NULL, 0))
479 if (__libc_use_alloca (alloca_used
480 + scope_delim - name + 1))
482 namebuf = alloca_account (scope_delim - name + 1,
484 *((char *) __mempcpy (namebuf, name,
485 scope_delim - name)) = '\0';
489 namebuf = strndup (name, scope_delim - name);
492 assert (!malloc_name);
495 malloc_namebuf = true;
500 e = inet_pton (AF_INET6, namebuf, at->addr);
504 else if (scope_delim != NULL && malloc_name)
505 /* Undo what we did above. */
506 *scope_delim = SCOPE_DELIMITER;
510 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
511 at->family = AF_INET6;
512 else if (req->ai_family == AF_INET
513 && IN6_IS_ADDR_V4MAPPED (at->addr))
515 at->addr[0] = at->addr[3];
516 at->family = AF_INET;
520 result = -EAI_ADDRFAMILY;
521 goto free_and_return;
524 if (scope_delim != NULL)
526 int try_numericscope = 0;
527 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
528 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
530 at->scopeid = if_nametoindex (scope_delim + 1);
531 if (at->scopeid == 0)
532 try_numericscope = 1;
535 try_numericscope = 1;
537 if (try_numericscope != 0)
540 assert (sizeof (uint32_t) <= sizeof (unsigned long));
541 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
545 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
546 goto free_and_return;
551 if (req->ai_flags & AI_CANONNAME)
556 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
558 struct gaih_addrtuple **pat = &at;
560 int no_inet6_data = 0;
562 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
563 enum nss_status status = NSS_STATUS_UNAVAIL;
567 /* If we do not have to look for IPv6 addresses, use
568 the simple, old functions, which do not support
570 if (req->ai_family == AF_INET)
572 /* Allocate additional room for struct host_data. */
573 size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*)
574 + 16 * sizeof(char));
575 assert (tmpbuf == NULL);
576 tmpbuf = alloca_account (tmpbuflen, alloca_used);
584 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
585 tmpbuflen, &h, &herrno);
586 if (rc != ERANGE || herrno != NETDB_INTERNAL)
590 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
591 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
596 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
600 result = -EAI_MEMORY;
601 goto free_and_return;
604 malloc_tmpbuf = true;
605 tmpbuflen = 2 * tmpbuflen;
614 /* We found data, count the number of addresses. */
615 for (i = 0; h->h_addr_list[i]; ++i)
617 if (i > 0 && *pat != NULL)
620 if (__libc_use_alloca (alloca_used
621 + i * sizeof (struct gaih_addrtuple)))
622 addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
627 * sizeof (struct gaih_addrtuple));
630 result = -EAI_MEMORY;
631 goto free_and_return;
633 malloc_addrmem = true;
636 /* Now convert it into the list. */
637 struct gaih_addrtuple *addrfree = addrmem;
638 for (i = 0; h->h_addr_list[i]; ++i)
646 (*pat)->family = AF_INET;
647 memcpy ((*pat)->addr, h->h_addr_list[i],
649 pat = &((*pat)->next);
655 if (herrno == NETDB_INTERNAL)
657 __set_h_errno (herrno);
658 result = -EAI_SYSTEM;
660 else if (herrno == TRY_AGAIN)
663 /* We made requests but they turned out no data.
664 The name is known, though. */
665 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
667 goto free_and_return;
674 if (__nss_not_use_nscd_hosts > 0
675 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
676 __nss_not_use_nscd_hosts = 0;
678 if (!__nss_not_use_nscd_hosts
679 && !__nss_database_custom[NSS_DBSIDX_hosts])
681 /* Try to use nscd. */
682 struct nscd_ai_result *air = NULL;
684 int err = __nscd_getai (name, &air, &herrno);
687 /* Transform into gaih_addrtuple list. */
688 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
689 char *addrs = air->addrs;
691 if (__libc_use_alloca (alloca_used
692 + air->naddrs * sizeof (struct gaih_addrtuple)))
693 addrmem = alloca_account (air->naddrs
694 * sizeof (struct gaih_addrtuple),
698 addrmem = malloc (air->naddrs
699 * sizeof (struct gaih_addrtuple));
702 result = -EAI_MEMORY;
703 goto free_and_return;
705 malloc_addrmem = true;
708 struct gaih_addrtuple *addrfree = addrmem;
709 for (int i = 0; i < air->naddrs; ++i)
711 socklen_t size = (air->family[i] == AF_INET
712 ? INADDRSZ : IN6ADDRSZ);
718 uint32_t *pataddr = (*pat)->addr;
720 if (added_canon || air->canon == NULL)
722 else if (canonbuf == NULL)
724 size_t canonlen = strlen (air->canon) + 1;
725 if ((req->ai_flags & AI_CANONIDN) != 0
726 && __libc_use_alloca (alloca_used + canonlen))
727 canonbuf = alloca_account (canonlen, alloca_used);
730 canonbuf = malloc (canonlen);
731 if (canonbuf == NULL)
733 result = -EAI_MEMORY;
734 goto free_and_return;
736 malloc_canonbuf = true;
738 canon = (*pat)->name = memcpy (canonbuf, air->canon,
742 if (air->family[i] == AF_INET
743 && req->ai_family == AF_INET6
744 && (req->ai_flags & AI_V4MAPPED))
746 (*pat)->family = AF_INET6;
747 pataddr[3] = *(uint32_t *) addrs;
748 pataddr[2] = htonl (0xffff);
751 pat = &((*pat)->next);
754 else if (req->ai_family == AF_UNSPEC
755 || air->family[i] == req->ai_family)
757 (*pat)->family = air->family[i];
758 memcpy (pataddr, addrs, size);
759 pat = &((*pat)->next);
761 if (air->family[i] == AF_INET6)
769 if (at->family == AF_UNSPEC)
771 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
772 goto free_and_return;
778 /* The database contains a negative entry. */
779 goto free_and_return;
780 else if (__nss_not_use_nscd_hosts == 0)
782 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
783 result = -EAI_MEMORY;
784 else if (herrno == TRY_AGAIN)
787 result = -EAI_SYSTEM;
789 goto free_and_return;
794 if (__nss_hosts_database == NULL)
795 no_more = __nss_database_lookup ("hosts", NULL,
796 "dns [!UNAVAIL=return] files",
797 &__nss_hosts_database);
800 nip = __nss_hosts_database;
802 /* Initialize configurations. */
803 if (__glibc_unlikely (!_res_hconf.initialized))
805 if (__res_maybe_init (&_res, 0) == -1)
808 /* If we are looking for both IPv4 and IPv6 address we don't
809 want the lookup functions to automatically promote IPv4
810 addresses to IPv6 addresses. Currently this is decided
811 by setting the RES_USE_INET6 bit in _res.options. */
812 old_res_options = _res.options;
813 _res.options &= ~RES_USE_INET6;
815 size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
816 malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
817 assert (tmpbuf == NULL);
819 tmpbuf = alloca_account (tmpbuflen, alloca_used);
822 tmpbuf = malloc (tmpbuflen);
825 _res.options |= old_res_options & RES_USE_INET6;
826 result = -EAI_MEMORY;
827 goto free_and_return;
834 nss_gethostbyname4_r fct4 = NULL;
836 /* gethostbyname4_r sends out parallel A and AAAA queries and
837 is thus only suitable for PF_UNSPEC. */
838 if (req->ai_family == PF_UNSPEC)
839 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
848 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
849 tmpbuflen, &rc, &herrno,
851 if (status == NSS_STATUS_SUCCESS)
853 if (status != NSS_STATUS_TRYAGAIN
854 || rc != ERANGE || herrno != NETDB_INTERNAL)
856 if (status == NSS_STATUS_TRYAGAIN
857 && herrno == TRY_AGAIN)
860 no_data = herrno == NO_DATA;
865 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
866 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
871 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
875 _res.options |= old_res_options & RES_USE_INET6;
876 result = -EAI_MEMORY;
877 goto free_and_return;
880 malloc_tmpbuf = true;
881 tmpbuflen = 2 * tmpbuflen;
885 if (status == NSS_STATUS_SUCCESS)
890 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
891 canon = (*pat)->name;
895 if ((*pat)->family == AF_INET
896 && req->ai_family == AF_INET6
897 && (req->ai_flags & AI_V4MAPPED) != 0)
899 uint32_t *pataddr = (*pat)->addr;
900 (*pat)->family = AF_INET6;
901 pataddr[3] = pataddr[0];
902 pataddr[2] = htonl (0xffff);
905 pat = &((*pat)->next);
908 else if (req->ai_family == AF_UNSPEC
909 || (*pat)->family == req->ai_family)
911 pat = &((*pat)->next);
914 if (req->ai_family == AF_INET6)
918 *pat = ((*pat)->next);
922 no_inet6_data = no_data;
926 nss_gethostbyname3_r fct = NULL;
927 if (req->ai_flags & AI_CANONNAME)
928 /* No need to use this function if we do not look for
929 the canonical name. The function does not exist in
930 all NSS modules and therefore the lookup would
932 fct = __nss_lookup_function (nip, "gethostbyname3_r");
934 /* We are cheating here. The gethostbyname2_r
935 function does not have the same interface as
936 gethostbyname3_r but the extra arguments the
937 latter takes are added at the end. So the
938 gethostbyname2_r code will just ignore them. */
939 fct = __nss_lookup_function (nip, "gethostbyname2_r");
943 if (req->ai_family == AF_INET6
944 || req->ai_family == AF_UNSPEC)
946 gethosts (AF_INET6, struct in6_addr);
947 no_inet6_data = no_data;
948 inet6_status = status;
950 if (req->ai_family == AF_INET
951 || req->ai_family == AF_UNSPEC
952 || (req->ai_family == AF_INET6
953 && (req->ai_flags & AI_V4MAPPED)
954 /* Avoid generating the mapped addresses if we
955 know we are not going to need them. */
956 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
958 gethosts (AF_INET, struct in_addr);
960 if (req->ai_family == AF_INET)
962 no_inet6_data = no_data;
963 inet6_status = status;
967 /* If we found one address for AF_INET or AF_INET6,
968 don't continue the search. */
969 if (inet6_status == NSS_STATUS_SUCCESS
970 || status == NSS_STATUS_SUCCESS)
972 if ((req->ai_flags & AI_CANONNAME) != 0
975 /* If we need the canonical name, get it
976 from the same service as the result. */
977 nss_getcanonname_r cfct;
980 cfct = __nss_lookup_function (nip,
984 const size_t max_fqdn_len = 256;
985 if ((req->ai_flags & AI_CANONIDN) != 0
986 && __libc_use_alloca (alloca_used
988 canonbuf = alloca_account (max_fqdn_len,
992 canonbuf = malloc (max_fqdn_len);
993 if (canonbuf == NULL)
996 |= old_res_options & RES_USE_INET6;
997 result = -EAI_MEMORY;
998 goto free_and_return;
1000 malloc_canonbuf = true;
1004 if (DL_CALL_FCT (cfct, (at->name ?: name,
1008 == NSS_STATUS_SUCCESS)
1012 /* Set to name now to avoid using
1014 if (malloc_canonbuf)
1017 malloc_canonbuf = false;
1023 status = NSS_STATUS_SUCCESS;
1027 /* We can have different states for AF_INET and
1028 AF_INET6. Try to find a useful one for both. */
1029 if (inet6_status == NSS_STATUS_TRYAGAIN)
1030 status = NSS_STATUS_TRYAGAIN;
1031 else if (status == NSS_STATUS_UNAVAIL
1032 && inet6_status != NSS_STATUS_UNAVAIL)
1033 status = inet6_status;
1038 status = NSS_STATUS_UNAVAIL;
1039 /* Could not load any of the lookup functions. Indicate
1040 an internal error if the failure was due to a system
1041 error other than the file not being found. We use the
1042 errno from the last failed callback. */
1043 if (errno != 0 && errno != ENOENT)
1044 __set_h_errno (NETDB_INTERNAL);
1048 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1051 if (nip->next == NULL)
1057 _res.options |= old_res_options & RES_USE_INET6;
1059 if (h_errno == NETDB_INTERNAL)
1061 result = GAIH_OKIFUNSPEC | -EAI_SYSTEM;
1062 goto free_and_return;
1065 if (no_data != 0 && no_inet6_data != 0)
1067 /* If both requests timed out report this. */
1068 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1069 result = -EAI_AGAIN;
1071 /* We made requests but they turned out no data. The name
1072 is known, though. */
1073 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1075 goto free_and_return;
1080 if (at->family == AF_UNSPEC)
1082 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1083 goto free_and_return;
1088 struct gaih_addrtuple *atr;
1089 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1090 memset (at, '\0', sizeof (struct gaih_addrtuple));
1092 if (req->ai_family == AF_UNSPEC)
1094 at->next = __alloca (sizeof (struct gaih_addrtuple));
1095 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1098 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1100 at->family = AF_INET6;
1101 if ((req->ai_flags & AI_PASSIVE) == 0)
1102 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1106 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1108 atr->family = AF_INET;
1109 if ((req->ai_flags & AI_PASSIVE) == 0)
1110 atr->addr[0] = htonl (INADDR_LOOPBACK);
1115 struct gaih_servtuple *st2;
1116 struct gaih_addrtuple *at2 = at;
1121 buffer is the size of an unformatted IPv6 address in printable format.
1125 /* Only the first entry gets the canonical name. */
1126 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1128 char *tmpbuf2 = NULL;
1129 bool malloc_tmpbuf2 = false;
1133 struct hostent *h = NULL;
1136 /* Add room for struct host_data. */
1137 size_t tmpbuf2len = (512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1)
1138 * sizeof(char*) + 16 * sizeof(char));
1142 if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1143 tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1148 char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1154 result = -EAI_MEMORY;
1155 goto free_and_return;
1159 tmpbuf2len = 2 * tmpbuf2len;
1160 malloc_tmpbuf2 = true;
1163 rc = __gethostbyaddr_r (at2->addr,
1164 ((at2->family == AF_INET6)
1165 ? sizeof (struct in6_addr)
1166 : sizeof (struct in_addr)),
1167 at2->family, &th, tmpbuf2,
1168 tmpbuf2len, &h, &herrno);
1170 while (rc == ERANGE && herrno == NETDB_INTERNAL);
1172 if (rc != 0 && herrno == NETDB_INTERNAL)
1177 __set_h_errno (herrno);
1178 result = -EAI_SYSTEM;
1179 goto free_and_return;
1186 assert (orig_name != NULL);
1187 /* If the canonical name cannot be determined, use
1188 the passed in string. */
1194 if (req->ai_flags & AI_CANONIDN)
1197 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1198 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1199 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1200 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1203 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1204 if (rc != IDNA_SUCCESS)
1209 if (rc == IDNA_MALLOC_ERROR)
1210 result = -EAI_MEMORY;
1211 else if (rc == IDNA_DLOPEN_ERROR)
1212 result = -EAI_SYSTEM;
1214 result = -EAI_IDN_ENCODE;
1215 goto free_and_return;
1217 /* In case the output string is the same as the input
1218 string no new string has been allocated and we
1230 if (malloc_canonbuf)
1231 /* We already allocated the string using malloc. */
1232 malloc_canonbuf = false;
1235 canon = strdup (canon);
1241 result = -EAI_MEMORY;
1242 goto free_and_return;
1251 family = at2->family;
1252 if (family == AF_INET6)
1254 socklen = sizeof (struct sockaddr_in6);
1256 /* If we looked up IPv4 mapped address discard them here if
1257 the caller isn't interested in all address and we have
1258 found at least one IPv6 address. */
1260 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1261 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1265 socklen = sizeof (struct sockaddr_in);
1267 for (st2 = st; st2 != NULL; st2 = st2->next)
1269 struct addrinfo *ai;
1270 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1273 free ((char *) canon);
1274 result = -EAI_MEMORY;
1275 goto free_and_return;
1278 ai->ai_flags = req->ai_flags;
1279 ai->ai_family = family;
1280 ai->ai_socktype = st2->socktype;
1281 ai->ai_protocol = st2->protocol;
1282 ai->ai_addrlen = socklen;
1283 ai->ai_addr = (void *) (ai + 1);
1285 /* We only add the canonical name once. */
1286 ai->ai_canonname = (char *) canon;
1290 ai->ai_addr->sa_len = socklen;
1291 #endif /* _HAVE_SA_LEN */
1292 ai->ai_addr->sa_family = family;
1294 /* In case of an allocation error the list must be NULL
1298 if (family == AF_INET6)
1300 struct sockaddr_in6 *sin6p =
1301 (struct sockaddr_in6 *) ai->ai_addr;
1303 sin6p->sin6_port = st2->port;
1304 sin6p->sin6_flowinfo = 0;
1305 memcpy (&sin6p->sin6_addr,
1306 at2->addr, sizeof (struct in6_addr));
1307 sin6p->sin6_scope_id = at2->scopeid;
1311 struct sockaddr_in *sinp =
1312 (struct sockaddr_in *) ai->ai_addr;
1313 sinp->sin_port = st2->port;
1314 memcpy (&sinp->sin_addr,
1315 at2->addr, sizeof (struct in_addr));
1316 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1319 pai = &(ai->ai_next);
1331 free ((char *) name);
1334 if (malloc_canonbuf)
1345 struct addrinfo *dest_addr;
1346 /* Using sockaddr_storage is for now overkill. We only support IPv4
1347 and IPv6 so far. If this changes at some point we can adjust the
1349 struct sockaddr_in6 source_addr;
1350 uint8_t source_addr_len;
1351 bool got_source_addr;
1352 uint8_t source_addr_flags;
1358 struct sort_result_combo
1360 struct sort_result *results;
1365 #if __BYTE_ORDER == __BIG_ENDIAN
1366 # define htonl_c(n) n
1368 # define htonl_c(n) __bswap_constant_32 (n)
1371 static const struct scopeentry
1380 } default_scopes[] =
1382 /* Link-local addresses: scope 2. */
1383 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1384 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1385 /* Default: scope 14. */
1386 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1389 /* The label table. */
1390 static const struct scopeentry *scopes;
1394 get_scope (const struct sockaddr_in6 *in6)
1397 if (in6->sin6_family == PF_INET6)
1399 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1401 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1402 /* RFC 4291 2.5.3 says that the loopback address is to be
1403 treated like a link-local address. */
1404 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1406 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1409 /* XXX Is this the correct default behavior? */
1413 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1415 else if (in6->sin6_family == PF_INET)
1417 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1422 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1423 == scopes[cnt].addr32)
1424 return scopes[cnt].scope;
1431 /* XXX What is a good default? */
1440 struct in6_addr prefix;
1446 /* The label table. */
1447 static const struct prefixentry *labels;
1449 /* Default labels. */
1450 static const struct prefixentry default_labels[] =
1452 /* See RFC 3484 for the details. */
1454 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1458 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1462 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1463 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1466 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1467 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1469 /* The next two entries differ from RFC 3484. We need to treat
1470 IPv6 site-local addresses special because they are never NATed,
1471 unlike site-locale IPv4 addresses. If this would not happen, on
1472 machines which have only IPv4 and IPv6 site-local addresses, the
1473 sorting would prefer the IPv6 site-local addresses, causing
1474 unnecessary delays when trying to connect to a global IPv6 address
1475 through a site-local IPv6 address. */
1477 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1481 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1484 /* Additional rule for Teredo tunnels. */
1486 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1490 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1496 /* The precedence table. */
1497 static const struct prefixentry *precedence;
1499 /* The default precedences. */
1500 static const struct prefixentry default_precedence[] =
1502 /* See RFC 3484 for the details. */
1504 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1508 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1512 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1516 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1517 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1520 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1527 match_prefix (const struct sockaddr_in6 *in6,
1528 const struct prefixentry *list, int default_val)
1531 struct sockaddr_in6 in6_mem;
1533 if (in6->sin6_family == PF_INET)
1535 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1537 /* Construct a V4-to-6 mapped address. */
1538 in6_mem.sin6_family = PF_INET6;
1539 in6_mem.sin6_port = in->sin_port;
1540 in6_mem.sin6_flowinfo = 0;
1541 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1542 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1543 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1544 in6_mem.sin6_scope_id = 0;
1548 else if (in6->sin6_family != PF_INET6)
1551 for (idx = 0; ; ++idx)
1553 unsigned int bits = list[idx].bits;
1554 const uint8_t *mask = list[idx].prefix.s6_addr;
1555 const uint8_t *val = in6->sin6_addr.s6_addr;
1569 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1575 return list[idx].val;
1580 get_label (const struct sockaddr_in6 *in6)
1582 /* XXX What is a good default value? */
1583 return match_prefix (in6, labels, INT_MAX);
1588 get_precedence (const struct sockaddr_in6 *in6)
1590 /* XXX What is a good default value? */
1591 return match_prefix (in6, precedence, 0);
1595 /* Find last bit set in a word. */
1601 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1602 if ((a & mask) != 0)
1609 rfc3484_sort (const void *p1, const void *p2, void *arg)
1611 const size_t idx1 = *(const size_t *) p1;
1612 const size_t idx2 = *(const size_t *) p2;
1613 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1614 struct sort_result *a1 = &src->results[idx1];
1615 struct sort_result *a2 = &src->results[idx2];
1617 /* Rule 1: Avoid unusable destinations.
1618 We have the got_source_addr flag set if the destination is reachable. */
1619 if (a1->got_source_addr && ! a2->got_source_addr)
1621 if (! a1->got_source_addr && a2->got_source_addr)
1625 /* Rule 2: Prefer matching scope. Only interesting if both
1626 destination addresses are IPv6. */
1628 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1631 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1633 if (a1->got_source_addr)
1635 int a1_src_scope = get_scope (&a1->source_addr);
1636 int a2_src_scope = get_scope (&a2->source_addr);
1638 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1640 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1645 /* Rule 3: Avoid deprecated addresses. */
1646 if (a1->got_source_addr)
1648 if (!(a1->source_addr_flags & in6ai_deprecated)
1649 && (a2->source_addr_flags & in6ai_deprecated))
1651 if ((a1->source_addr_flags & in6ai_deprecated)
1652 && !(a2->source_addr_flags & in6ai_deprecated))
1656 /* Rule 4: Prefer home addresses. */
1657 if (a1->got_source_addr)
1659 if (!(a1->source_addr_flags & in6ai_homeaddress)
1660 && (a2->source_addr_flags & in6ai_homeaddress))
1662 if ((a1->source_addr_flags & in6ai_homeaddress)
1663 && !(a2->source_addr_flags & in6ai_homeaddress))
1667 /* Rule 5: Prefer matching label. */
1668 if (a1->got_source_addr)
1671 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1672 int a1_src_label = get_label (&a1->source_addr);
1675 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1676 int a2_src_label = get_label (&a2->source_addr);
1678 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1680 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1685 /* Rule 6: Prefer higher precedence. */
1687 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1689 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1691 if (a1_prec > a2_prec)
1693 if (a1_prec < a2_prec)
1697 /* Rule 7: Prefer native transport. */
1698 if (a1->got_source_addr)
1700 /* The same interface index means the same interface which means
1701 there is no difference in transport. This should catch many
1703 if (a1->index != a2->index)
1705 int a1_native = a1->native;
1706 int a2_native = a2->native;
1708 if (a1_native == -1 || a2_native == -1)
1711 if (a1_native == -1)
1713 /* If we do not have the information use 'native' as
1716 a1_index = a1->index;
1719 a1_index = 0xffffffffu;
1722 if (a2_native == -1)
1724 /* If we do not have the information use 'native' as
1727 a2_index = a2->index;
1730 a2_index = 0xffffffffu;
1732 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1734 /* Fill in the results in all the records. */
1735 for (int i = 0; i < src->nresults; ++i)
1736 if (src->results[i].index == a1_index)
1738 assert (src->results[i].native == -1
1739 || src->results[i].native == a1_native);
1740 src->results[i].native = a1_native;
1742 else if (src->results[i].index == a2_index)
1744 assert (src->results[i].native == -1
1745 || src->results[i].native == a2_native);
1746 src->results[i].native = a2_native;
1750 if (a1_native && !a2_native)
1752 if (!a1_native && a2_native)
1758 /* Rule 8: Prefer smaller scope. */
1759 if (a1_dst_scope < a2_dst_scope)
1761 if (a1_dst_scope > a2_dst_scope)
1765 /* Rule 9: Use longest matching prefix. */
1766 if (a1->got_source_addr
1767 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1772 if (a1->dest_addr->ai_family == PF_INET)
1774 assert (a1->source_addr.sin6_family == PF_INET);
1775 assert (a2->source_addr.sin6_family == PF_INET);
1777 /* Outside of subnets, as defined by the network masks,
1778 common address prefixes for IPv4 addresses make no sense.
1779 So, define a non-zero value only if source and
1780 destination address are on the same subnet. */
1781 struct sockaddr_in *in1_dst
1782 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1783 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1784 struct sockaddr_in *in1_src
1785 = (struct sockaddr_in *) &a1->source_addr;
1786 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1787 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1789 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1790 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1792 struct sockaddr_in *in2_dst
1793 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1794 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1795 struct sockaddr_in *in2_src
1796 = (struct sockaddr_in *) &a2->source_addr;
1797 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1798 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1800 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1801 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1803 else if (a1->dest_addr->ai_family == PF_INET6)
1805 assert (a1->source_addr.sin6_family == PF_INET6);
1806 assert (a2->source_addr.sin6_family == PF_INET6);
1808 struct sockaddr_in6 *in1_dst;
1809 struct sockaddr_in6 *in1_src;
1810 struct sockaddr_in6 *in2_dst;
1811 struct sockaddr_in6 *in2_src;
1813 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1814 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1815 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1816 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1819 for (i = 0; i < 4; ++i)
1820 if (in1_dst->sin6_addr.s6_addr32[i]
1821 != in1_src->sin6_addr.s6_addr32[i]
1822 || (in2_dst->sin6_addr.s6_addr32[i]
1823 != in2_src->sin6_addr.s6_addr32[i]))
1828 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1829 ^ in1_src->sin6_addr.s6_addr32[i]));
1830 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1831 ^ in2_src->sin6_addr.s6_addr32[i]));
1842 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1843 compare with the value indicating the order in which the entries
1844 have been received from the services. NB: no two entries can have
1845 the same order so the test will never return zero. */
1846 return idx1 < idx2 ? -1 : 1;
1851 in6aicmp (const void *p1, const void *p2)
1853 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1854 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1856 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1860 /* Name of the config file for RFC 3484 sorting (for now). */
1861 #define GAICONF_FNAME "/etc/gai.conf"
1864 /* Non-zero if we are supposed to reload the config file automatically
1865 whenever it changed. */
1866 static int gaiconf_reload_flag;
1868 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1869 static int gaiconf_reload_flag_ever_set;
1871 /* Last modification time. */
1872 #ifdef _STATBUF_ST_NSEC
1874 static struct timespec gaiconf_mtime;
1877 save_gaiconf_mtime (const struct stat64 *st)
1879 gaiconf_mtime = st->st_mtim;
1883 check_gaiconf_mtime (const struct stat64 *st)
1885 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1886 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1891 static time_t gaiconf_mtime;
1894 save_gaiconf_mtime (const struct stat64 *st)
1896 gaiconf_mtime = st->st_mtime;
1900 check_gaiconf_mtime (const struct stat64 *st)
1902 return st->st_mtime == gaiconf_mtime;
1908 libc_freeres_fn(fini)
1910 if (labels != default_labels)
1912 const struct prefixentry *old = labels;
1913 labels = default_labels;
1914 free ((void *) old);
1917 if (precedence != default_precedence)
1919 const struct prefixentry *old = precedence;
1920 precedence = default_precedence;
1921 free ((void *) old);
1924 if (scopes != default_scopes)
1926 const struct scopeentry *old = scopes;
1927 scopes = default_scopes;
1928 free ((void *) old);
1935 struct prefixentry entry;
1936 struct prefixlist *next;
1942 struct scopeentry entry;
1943 struct scopelist *next;
1948 free_prefixlist (struct prefixlist *list)
1950 while (list != NULL)
1952 struct prefixlist *oldp = list;
1960 free_scopelist (struct scopelist *list)
1962 while (list != NULL)
1964 struct scopelist *oldp = list;
1972 prefixcmp (const void *p1, const void *p2)
1974 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1975 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1977 if (e1->bits < e2->bits)
1979 if (e1->bits == e2->bits)
1986 scopecmp (const void *p1, const void *p2)
1988 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1989 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1991 if (e1->netmask > e2->netmask)
1993 if (e1->netmask == e2->netmask)
2002 struct prefixlist *labellist = NULL;
2003 size_t nlabellist = 0;
2004 bool labellist_nullbits = false;
2005 struct prefixlist *precedencelist = NULL;
2006 size_t nprecedencelist = 0;
2007 bool precedencelist_nullbits = false;
2008 struct scopelist *scopelist = NULL;
2009 size_t nscopelist = 0;
2010 bool scopelist_nullbits = false;
2012 FILE *fp = fopen (GAICONF_FNAME, "rce");
2016 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
2025 __fsetlocking (fp, FSETLOCKING_BYCALLER);
2027 while (!feof_unlocked (fp))
2029 ssize_t n = __getline (&line, &linelen, fp);
2033 /* Handle comments. No escaping possible so this is easy. */
2034 char *cp = strchr (line, '#');
2039 while (isspace (*cp))
2043 while (*cp != '\0' && !isspace (*cp))
2045 size_t cmdlen = cp - cmd;
2049 while (isspace (*cp))
2053 while (*cp != '\0' && !isspace (*cp))
2055 size_t val1len = cp - cmd;
2057 /* We always need at least two values. */
2063 while (isspace (*cp))
2067 while (*cp != '\0' && !isspace (*cp))
2070 /* Ignore the rest of the line. */
2073 struct prefixlist **listp;
2079 if (strcmp (cmd, "label") == 0)
2081 struct in6_addr prefix;
2082 unsigned long int bits;
2083 unsigned long int val;
2088 nullbitsp = &labellist_nullbits;
2093 cp = strchr (val1, '/');
2096 if (inet_pton (AF_INET6, val1, &prefix)
2098 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2102 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2107 struct prefixlist *newp = malloc (sizeof (*newp));
2115 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2116 newp->entry.bits = bits;
2117 newp->entry.val = val;
2118 newp->next = *listp;
2121 *nullbitsp |= bits == 0;
2127 if (strcmp (cmd, "reload") == 0)
2129 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2130 if (gaiconf_reload_flag)
2131 gaiconf_reload_flag_ever_set = 1;
2136 if (strcmp (cmd, "scopev4") == 0)
2138 struct in6_addr prefix;
2139 unsigned long int bits;
2140 unsigned long int val;
2145 cp = strchr (val1, '/');
2148 if (inet_pton (AF_INET6, val1, &prefix))
2151 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2153 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2158 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2163 struct scopelist *newp;
2165 newp = malloc (sizeof (*newp));
2173 newp->entry.netmask = htonl (bits != 96
2177 newp->entry.addr32 = (prefix.s6_addr32[3]
2178 & newp->entry.netmask);
2179 newp->entry.scope = val;
2180 newp->next = scopelist;
2183 scopelist_nullbits |= bits == 96;
2186 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2188 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2192 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2204 if (strcmp (cmd, "precedence") == 0)
2206 listp = &precedencelist;
2207 lenp = &nprecedencelist;
2208 nullbitsp = &precedencelist_nullbits;
2219 /* Create the array for the labels. */
2220 struct prefixentry *new_labels;
2223 if (!labellist_nullbits)
2225 new_labels = malloc (nlabellist * sizeof (*new_labels));
2226 if (new_labels == NULL)
2230 if (!labellist_nullbits)
2233 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2234 new_labels[i].bits = 0;
2235 new_labels[i].val = 1;
2238 struct prefixlist *l = labellist;
2241 new_labels[i] = l->entry;
2244 free_prefixlist (labellist);
2246 /* Sort the entries so that the most specific ones are at
2248 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2251 new_labels = (struct prefixentry *) default_labels;
2253 struct prefixentry *new_precedence;
2254 if (nprecedencelist > 0)
2256 if (!precedencelist_nullbits)
2258 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2259 if (new_precedence == NULL)
2261 if (new_labels != default_labels)
2266 int i = nprecedencelist;
2267 if (!precedencelist_nullbits)
2270 memset (&new_precedence[i].prefix, '\0',
2271 sizeof (struct in6_addr));
2272 new_precedence[i].bits = 0;
2273 new_precedence[i].val = 40;
2276 struct prefixlist *l = precedencelist;
2279 new_precedence[i] = l->entry;
2282 free_prefixlist (precedencelist);
2284 /* Sort the entries so that the most specific ones are at
2286 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2290 new_precedence = (struct prefixentry *) default_precedence;
2292 struct scopeentry *new_scopes;
2295 if (!scopelist_nullbits)
2297 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2298 if (new_scopes == NULL)
2300 if (new_labels != default_labels)
2302 if (new_precedence != default_precedence)
2303 free (new_precedence);
2308 if (!scopelist_nullbits)
2311 new_scopes[i].addr32 = 0;
2312 new_scopes[i].netmask = 0;
2313 new_scopes[i].scope = 14;
2316 struct scopelist *l = scopelist;
2319 new_scopes[i] = l->entry;
2322 free_scopelist (scopelist);
2324 /* Sort the entries so that the most specific ones are at
2326 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2330 new_scopes = (struct scopeentry *) default_scopes;
2332 /* Now we are ready to replace the values. */
2333 const struct prefixentry *old = labels;
2334 labels = new_labels;
2335 if (old != default_labels)
2336 free ((void *) old);
2339 precedence = new_precedence;
2340 if (old != default_precedence)
2341 free ((void *) old);
2343 const struct scopeentry *oldscope = scopes;
2344 scopes = new_scopes;
2345 if (oldscope != default_scopes)
2346 free ((void *) oldscope);
2348 save_gaiconf_mtime (&st);
2353 free_prefixlist (labellist);
2354 free_prefixlist (precedencelist);
2355 free_scopelist (scopelist);
2357 /* If we previously read the file but it is gone now, free the
2358 old data and use the builtin one. Leave the reload flag
2366 gaiconf_reload (void)
2369 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2370 || !check_gaiconf_mtime (&st))
2376 getaddrinfo (const char *name, const char *service,
2377 const struct addrinfo *hints, struct addrinfo **pai)
2379 int i = 0, last_i = 0;
2381 struct addrinfo *p = NULL;
2382 struct gaih_service gaih_service, *pservice;
2383 struct addrinfo local_hints;
2385 if (name != NULL && name[0] == '*' && name[1] == 0)
2388 if (service != NULL && service[0] == '*' && service[1] == 0)
2391 if (name == NULL && service == NULL)
2395 hints = &default_hints;
2398 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2400 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2401 |AI_IDN_USE_STD3_ASCII_RULES
2403 |AI_NUMERICSERV|AI_ALL))
2404 return EAI_BADFLAGS;
2406 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2407 return EAI_BADFLAGS;
2409 struct in6addrinfo *in6ai = NULL;
2410 size_t in6ailen = 0;
2411 bool seen_ipv4 = false;
2412 bool seen_ipv6 = false;
2413 bool check_pf_called = false;
2415 if (hints->ai_flags & AI_ADDRCONFIG)
2417 /* We might need information about what interfaces are available.
2418 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2419 cannot cache the results since new interfaces could be added at
2421 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2422 check_pf_called = true;
2424 /* Now make a decision on what we return, if anything. */
2425 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2427 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2428 narrow down the search. */
2429 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2431 local_hints = *hints;
2432 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2433 hints = &local_hints;
2436 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2437 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2439 /* We cannot possibly return a valid answer. */
2440 __free_in6ai (in6ai);
2445 if (service && service[0])
2448 gaih_service.name = service;
2449 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2452 if (hints->ai_flags & AI_NUMERICSERV)
2454 __free_in6ai (in6ai);
2458 gaih_service.num = -1;
2461 pservice = &gaih_service;
2466 struct addrinfo **end = &p;
2468 unsigned int naddrs = 0;
2469 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2470 || hints->ai_family == AF_INET6)
2472 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2476 __free_in6ai (in6ai);
2478 return -(last_i & GAIH_EAI);
2482 end = &((*end)->ai_next);
2488 __free_in6ai (in6ai);
2494 /* Read the config file. */
2495 __libc_once_define (static, once);
2496 __typeof (once) old_once = once;
2497 __libc_once (once, gaiconf_init);
2498 /* Sort results according to RFC 3484. */
2499 struct sort_result *results;
2502 struct addrinfo *last = NULL;
2503 char *canonname = NULL;
2504 bool malloc_results;
2505 size_t alloc_size = nresults * (sizeof (*results) + sizeof (size_t));
2508 = !__libc_use_alloca (alloc_size);
2511 results = malloc (alloc_size);
2512 if (results == NULL)
2514 __free_in6ai (in6ai);
2519 results = alloca (alloc_size);
2520 order = (size_t *) (results + nresults);
2522 /* Now we definitely need the interface information. */
2523 if (! check_pf_called)
2524 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2526 /* If we have information about deprecated and temporary addresses
2527 sort the array now. */
2529 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2534 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2536 results[i].dest_addr = q;
2537 results[i].native = -1;
2540 /* If we just looked up the address for a different
2541 protocol, reuse the result. */
2542 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2543 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2545 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2546 results[i - 1].source_addr_len);
2547 results[i].source_addr_len = results[i - 1].source_addr_len;
2548 results[i].got_source_addr = results[i - 1].got_source_addr;
2549 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2550 results[i].prefixlen = results[i - 1].prefixlen;
2551 results[i].index = results[i - 1].index;
2555 results[i].got_source_addr = false;
2556 results[i].source_addr_flags = 0;
2557 results[i].prefixlen = 0;
2558 results[i].index = 0xffffffffu;
2560 /* We overwrite the type with SOCK_DGRAM since we do not
2561 want connect() to connect to the other side. If we
2562 cannot determine the source address remember this
2564 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2568 close_not_cancel_no_status (fd);
2570 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2574 /* Reset the connection. */
2575 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2576 __connect (fd, &sa, sizeof (sa));
2579 socklen_t sl = sizeof (results[i].source_addr);
2581 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2582 && __getsockname (fd,
2583 (struct sockaddr *) &results[i].source_addr,
2586 results[i].source_addr_len = sl;
2587 results[i].got_source_addr = true;
2591 /* See whether the source address is on the list of
2592 deprecated or temporary addresses. */
2593 struct in6addrinfo tmp;
2595 if (q->ai_family == AF_INET && af == AF_INET)
2597 struct sockaddr_in *sinp
2598 = (struct sockaddr_in *) &results[i].source_addr;
2601 tmp.addr[2] = htonl (0xffff);
2602 tmp.addr[3] = sinp->sin_addr.s_addr;
2606 struct sockaddr_in6 *sin6p
2607 = (struct sockaddr_in6 *) &results[i].source_addr;
2608 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2611 struct in6addrinfo *found
2612 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2616 results[i].source_addr_flags = found->flags;
2617 results[i].prefixlen = found->prefixlen;
2618 results[i].index = found->index;
2622 if (q->ai_family == AF_INET && af == AF_INET6)
2624 /* We have to convert the address. The socket is
2625 IPv6 and the request is for IPv4. */
2626 struct sockaddr_in6 *sin6
2627 = (struct sockaddr_in6 *) &results[i].source_addr;
2628 struct sockaddr_in *sin
2629 = (struct sockaddr_in *) &results[i].source_addr;
2630 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2631 sin->sin_family = AF_INET;
2632 /* We do not have to initialize sin_port since this
2633 fields has the same position and size in the IPv6
2635 assert (offsetof (struct sockaddr_in, sin_port)
2636 == offsetof (struct sockaddr_in6, sin6_port));
2637 assert (sizeof (sin->sin_port)
2638 == sizeof (sin6->sin6_port));
2639 memcpy (&sin->sin_addr,
2640 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2641 results[i].source_addr_len = sizeof (struct sockaddr_in);
2644 else if (errno == EAFNOSUPPORT && af == AF_INET6
2645 && q->ai_family == AF_INET)
2646 /* This could mean IPv6 sockets are IPv6-only. */
2649 /* Just make sure that if we have to process the same
2650 address again we do not copy any memory. */
2651 results[i].source_addr_len = 0;
2654 /* Remember the canonical name. */
2655 if (q->ai_canonname != NULL)
2657 assert (canonname == NULL);
2658 canonname = q->ai_canonname;
2659 q->ai_canonname = NULL;
2664 close_not_cancel_no_status (fd);
2666 /* We got all the source addresses we can get, now sort using
2668 struct sort_result_combo src
2669 = { .results = results, .nresults = nresults };
2670 if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2672 __libc_lock_define_initialized (static, lock);
2674 __libc_lock_lock (lock);
2675 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2677 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2678 __libc_lock_unlock (lock);
2681 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2683 /* Queue the results up as they come out of sorting. */
2684 q = p = results[order[0]].dest_addr;
2685 for (i = 1; i < nresults; ++i)
2686 q = q->ai_next = results[order[i]].dest_addr;
2689 /* Fill in the canonical name into the new first entry. */
2690 p->ai_canonname = canonname;
2696 __free_in6ai (in6ai);
2704 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2706 libc_hidden_def (getaddrinfo)
2708 nss_interface_function (getaddrinfo)
2711 freeaddrinfo (struct addrinfo *ai)
2719 free (p->ai_canonname);
2723 libc_hidden_def (freeaddrinfo)