Return EAI_SYSTEM if we're out of file descriptors
[glibc.git] / sysdeps / posix / getaddrinfo.c
blobd95c2d1156baf66190df7fa7538bd4d824a4c880
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
10 way or form.
11 1. All terms of the all other applicable copyrights and licenses must be
12 followed.
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. */
38 #include <assert.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <ifaddrs.h>
42 #include <netdb.h>
43 #include <nss.h>
44 #include <resolv.h>
45 #include <stdbool.h>
46 #include <stdio.h>
47 #include <stdio_ext.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <arpa/inet.h>
51 #include <net/if.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
54 #include <sys/stat.h>
55 #include <sys/types.h>
56 #include <sys/un.h>
57 #include <sys/utsname.h>
58 #include <unistd.h>
59 #include <nsswitch.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>
66 #ifdef HAVE_LIBIDN
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,
69 int flags);
70 # include <libidn/idna.h>
71 #endif
73 #define GAIH_OKIFUNSPEC 0x0100
74 #define GAIH_EAI ~(GAIH_OKIFUNSPEC)
76 #ifndef UNIX_PATH_MAX
77 # define UNIX_PATH_MAX 108
78 #endif
80 struct gaih_service
82 const char *name;
83 int num;
86 struct gaih_servtuple
88 struct gaih_servtuple *next;
89 int socktype;
90 int protocol;
91 int port;
94 static const struct gaih_servtuple nullserv;
97 struct gaih_typeproto
99 int socktype;
100 int protocol;
101 uint8_t protoflag;
102 bool defaultflag;
103 char name[8];
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" },
117 #endif
118 #ifdef IPPROTO_UDPLITE
119 { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
120 #endif
121 #ifdef IPPROTO_SCTP
122 { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
123 { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
124 #endif
125 { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
126 { 0, 0, 0, false, "" }
129 struct gaih
131 int family;
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,
141 .ai_socktype = 0,
142 .ai_protocol = 0,
143 .ai_addrlen = 0,
144 .ai_addr = NULL,
145 .ai_canonname = NULL,
146 .ai_next = NULL
150 static int
151 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
152 const struct addrinfo *req, struct gaih_servtuple *st)
154 struct servent *s;
155 size_t tmpbuflen = 1024;
156 struct servent ts;
157 char *tmpbuf;
158 int r;
162 tmpbuf = __alloca (tmpbuflen);
164 r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
165 &s);
166 if (r != 0 || s == NULL)
168 if (r == ERANGE)
169 tmpbuflen *= 2;
170 else
171 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
174 while (r);
176 st->next = NULL;
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;
182 return 0;
185 #define gethosts(_family, _type) \
187 int i; \
188 int herrno; \
189 struct hostent th; \
190 struct hostent *h; \
191 char *localcanon = NULL; \
192 no_data = 0; \
193 while (1) { \
194 rc = 0; \
195 status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
196 &rc, &herrno, NULL, &localcanon)); \
197 if (rc != ERANGE || herrno != NETDB_INTERNAL) \
198 break; \
199 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen); \
201 if (status == NSS_STATUS_SUCCESS && rc == 0) \
202 h = &th; \
203 else \
204 h = NULL; \
205 if (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; \
215 else \
216 no_data = herrno == NO_DATA; \
218 else if (h != NULL) \
220 for (i = 0; h->h_addr_list[i]; i++) \
222 if (*pat == NULL) \
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); \
235 addr[1] = 0; \
236 addr[0] = 0; \
238 else \
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) \
250 got_ipv6 = true; \
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;
269 static int
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;
277 int rc;
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)
285 ++tp;
287 while (tp->name[0]
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)))
292 ++tp;
294 if (! tp->name[0])
296 if (req->ai_socktype)
297 return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
298 else
299 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
303 int port = 0;
304 if (service != NULL)
306 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
307 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
309 if (service->num < 0)
311 if (tp->name[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)))
317 return rc;
319 else
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)
327 continue;
329 if (req->ai_socktype != 0
330 && req->ai_socktype != tp->socktype)
331 continue;
332 if (req->ai_protocol != 0
333 && !(tp->protoflag & GAI_PROTO_PROTOANY)
334 && req->ai_protocol != tp->protocol)
335 continue;
337 newp = (struct gaih_servtuple *)
338 alloca_account (sizeof (struct gaih_servtuple),
339 alloca_used);
341 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
343 if (rc & GAIH_OKIFUNSPEC)
344 continue;
345 return rc;
348 *pst = newp;
349 pst = &(newp->next);
351 if (st == (struct gaih_servtuple *) &nullserv)
352 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
355 else
357 port = htons (service->num);
358 goto got_port;
361 else
363 got_port:
365 if (req->ai_socktype || req->ai_protocol)
367 st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
368 st->next = NULL;
369 st->socktype = tp->socktype;
370 st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
371 ? req->ai_protocol : tp->protocol);
372 st->port = port;
374 else
376 /* Neither socket type nor protocol is set. Return all socket types
377 we know about. */
378 struct gaih_servtuple **lastp = &st;
379 for (++tp; tp->name[0]; ++tp)
380 if (tp->defaultflag)
382 struct gaih_servtuple *newp;
384 newp = alloca_account (sizeof (struct gaih_servtuple),
385 alloca_used);
386 newp->next = NULL;
387 newp->socktype = tp->socktype;
388 newp->protocol = tp->protocol;
389 newp->port = port;
391 *lastp = newp;
392 lastp = &newp->next;
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;
403 char *tmpbuf = NULL;
404 int result = 0;
405 if (name != NULL)
407 at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
408 at->family = AF_UNSPEC;
409 at->scopeid = 0;
410 at->next = NULL;
412 #ifdef HAVE_LIBIDN
413 if (req->ai_flags & AI_IDN)
415 int idn_flags = 0;
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;
421 char *p = NULL;
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)
427 return -EAI_MEMORY;
428 if (rc == IDNA_DLOPEN_ERROR)
429 return -EAI_SYSTEM;
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. */
434 if (p != name)
436 name = p;
437 malloc_name = true;
440 #endif
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);
450 at->addr[1] = 0;
451 at->addr[0] = 0;
452 at->family = AF_INET6;
454 else
456 result = -EAI_ADDRFAMILY;
457 goto free_and_return;
460 if (req->ai_flags & AI_CANONNAME)
461 canon = name;
463 else if (at->family == AF_UNSPEC)
465 char *scope_delim = strchr (name, SCOPE_DELIMITER);
466 int e;
469 bool malloc_namebuf = false;
470 char *namebuf = (char *) name;
472 if (__builtin_expect (scope_delim != NULL, 0))
474 if (malloc_name)
475 *scope_delim = '\0';
476 else
478 if (__libc_use_alloca (alloca_used
479 + scope_delim - name + 1))
481 namebuf = alloca_account (scope_delim - name + 1,
482 alloca_used);
483 *((char *) __mempcpy (namebuf, name,
484 scope_delim - name)) = '\0';
486 else
488 namebuf = strndup (name, scope_delim - name);
489 if (namebuf == NULL)
491 assert (!malloc_name);
492 return -EAI_MEMORY;
494 malloc_namebuf = true;
499 e = inet_pton (AF_INET6, namebuf, at->addr);
501 if (malloc_namebuf)
502 free (namebuf);
503 else if (scope_delim != NULL && malloc_name)
504 /* Undo what we did above. */
505 *scope_delim = SCOPE_DELIMITER;
507 if (e > 0)
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;
517 else
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;
533 else
534 try_numericscope = 1;
536 if (try_numericscope != 0)
538 char *end;
539 assert (sizeof (uint32_t) <= sizeof (unsigned long));
540 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
541 10);
542 if (*end != '\0')
544 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
545 goto free_and_return;
550 if (req->ai_flags & AI_CANONNAME)
551 canon = name;
555 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
557 struct gaih_addrtuple **pat = &at;
558 int no_data = 0;
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;
563 int no_more;
564 int old_res_options;
566 /* If we do not have to look for IPv6 addresses, use
567 the simple, old functions, which do not support
568 IPv6 scope ids. */
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);
576 int rc;
577 struct hostent th;
578 struct hostent *h;
579 int herrno;
581 while (1)
583 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
584 tmpbuflen, &h, &herrno);
585 if (rc != ERANGE || herrno != NETDB_INTERNAL)
586 break;
588 if (!malloc_tmpbuf
589 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
590 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
591 2 * tmpbuflen,
592 alloca_used);
593 else
595 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
596 2 * tmpbuflen);
597 if (newp == NULL)
599 result = -EAI_MEMORY;
600 goto free_and_return;
602 tmpbuf = newp;
603 malloc_tmpbuf = true;
604 tmpbuflen = 2 * tmpbuflen;
608 if (rc == 0)
610 if (h != NULL)
612 int i;
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)
617 --i;
619 if (__libc_use_alloca (alloca_used
620 + i * sizeof (struct gaih_addrtuple)))
621 addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
622 alloca_used);
623 else
625 addrmem = malloc (i
626 * sizeof (struct gaih_addrtuple));
627 if (addrmem == NULL)
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)
639 if (*pat == NULL)
641 *pat = addrfree++;
642 (*pat)->scopeid = 0;
644 (*pat)->next = NULL;
645 (*pat)->family = AF_INET;
646 memcpy ((*pat)->addr, h->h_addr_list[i],
647 h->h_length);
648 pat = &((*pat)->next);
652 else
654 if (herrno == NETDB_INTERNAL)
656 __set_h_errno (herrno);
657 result = -EAI_SYSTEM;
659 else if (herrno == TRY_AGAIN)
660 result = -EAI_AGAIN;
661 else
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;
669 goto process_list;
672 #ifdef USE_NSCD
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;
682 int herrno;
683 int err = __nscd_getai (name, &air, &herrno);
684 if (air != NULL)
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),
694 alloca_used);
695 else
697 addrmem = malloc (air->naddrs
698 * sizeof (struct gaih_addrtuple));
699 if (addrmem == NULL)
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);
712 if (*pat == NULL)
714 *pat = addrfree++;
715 (*pat)->scopeid = 0;
717 uint32_t *pataddr = (*pat)->addr;
718 (*pat)->next = NULL;
719 if (added_canon || air->canon == NULL)
720 (*pat)->name = 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);
727 else
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,
738 canonlen);
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);
748 pataddr[1] = 0;
749 pataddr[0] = 0;
750 pat = &((*pat)->next);
751 added_canon = true;
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);
759 added_canon = true;
760 if (air->family[i] == AF_INET6)
761 got_ipv6 = true;
763 addrs += size;
766 free (air);
768 if (at->family == AF_UNSPEC)
770 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
771 goto free_and_return;
774 goto process_list;
776 else if (err == 0)
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)
784 result = -EAI_AGAIN;
785 else
786 result = -EAI_SYSTEM;
788 goto free_and_return;
791 #endif
793 if (__nss_hosts_database != NULL)
795 no_more = 0;
796 nip = __nss_hosts_database;
798 else
799 no_more = __nss_database_lookup ("hosts", NULL,
800 "dns [!UNAVAIL=return] files",
801 &nip);
803 /* Initialize configurations. */
804 if (__builtin_expect (!_res_hconf.initialized, 0))
805 _res_hconf_init ();
806 if (__res_maybe_init (&_res, 0) == -1)
807 no_more = 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);
819 if (!malloc_tmpbuf)
820 tmpbuf = alloca_account (tmpbuflen, alloca_used);
821 else
823 tmpbuf = malloc (tmpbuflen);
824 if (tmpbuf == NULL)
826 _res.options |= old_res_options & RES_USE_INET6;
827 result = -EAI_MEMORY;
828 goto free_and_return;
832 while (!no_more)
834 no_data = 0;
835 nss_gethostbyname4_r fct4 = NULL;
837 /* gethostbyname4_r sends out parallel A and AAAA queries and
838 is thus only suitable for PF_UNSPEC. */
839 if (req->ai_family == PF_UNSPEC)
840 fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
842 if (fct4 != NULL)
844 int herrno;
846 while (1)
848 rc = 0;
849 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
850 tmpbuflen, &rc, &herrno,
851 NULL));
852 if (status == NSS_STATUS_SUCCESS)
853 break;
854 if (status != NSS_STATUS_TRYAGAIN
855 || rc != ERANGE || herrno != NETDB_INTERNAL)
857 if (status == NSS_STATUS_TRYAGAIN
858 && herrno == TRY_AGAIN)
859 no_data = EAI_AGAIN;
860 else
861 no_data = herrno == NO_DATA;
862 break;
865 if (!malloc_tmpbuf
866 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
867 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
868 2 * tmpbuflen,
869 alloca_used);
870 else
872 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
873 2 * tmpbuflen);
874 if (newp == NULL)
876 _res.options |= old_res_options & RES_USE_INET6;
877 result = -EAI_MEMORY;
878 goto free_and_return;
880 tmpbuf = newp;
881 malloc_tmpbuf = true;
882 tmpbuflen = 2 * tmpbuflen;
886 if (status == NSS_STATUS_SUCCESS)
888 assert (!no_data);
889 no_data = 1;
891 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
892 canon = (*pat)->name;
894 while (*pat != NULL)
896 if ((*pat)->family == AF_INET
897 && req->ai_family == AF_INET6
898 && (req->ai_flags & AI_V4MAPPED) != 0)
900 uint32_t *pataddr = (*pat)->addr;
901 (*pat)->family = AF_INET6;
902 pataddr[3] = pataddr[0];
903 pataddr[2] = htonl (0xffff);
904 pataddr[1] = 0;
905 pataddr[0] = 0;
906 pat = &((*pat)->next);
907 no_data = 0;
909 else if (req->ai_family == AF_UNSPEC
910 || (*pat)->family == req->ai_family)
912 pat = &((*pat)->next);
914 no_data = 0;
915 if (req->ai_family == AF_INET6)
916 got_ipv6 = true;
918 else
919 *pat = ((*pat)->next);
923 no_inet6_data = no_data;
925 else
927 nss_gethostbyname3_r fct = NULL;
928 if (req->ai_flags & AI_CANONNAME)
929 /* No need to use this function if we do not look for
930 the canonical name. The function does not exist in
931 all NSS modules and therefore the lookup would
932 often fail. */
933 fct = __nss_lookup_function (nip, "gethostbyname3_r");
934 if (fct == NULL)
935 /* We are cheating here. The gethostbyname2_r
936 function does not have the same interface as
937 gethostbyname3_r but the extra arguments the
938 latter takes are added at the end. So the
939 gethostbyname2_r code will just ignore them. */
940 fct = __nss_lookup_function (nip, "gethostbyname2_r");
942 if (fct != NULL)
944 if (req->ai_family == AF_INET6
945 || req->ai_family == AF_UNSPEC)
947 gethosts (AF_INET6, struct in6_addr);
948 no_inet6_data = no_data;
949 inet6_status = status;
951 if (req->ai_family == AF_INET
952 || req->ai_family == AF_UNSPEC
953 || (req->ai_family == AF_INET6
954 && (req->ai_flags & AI_V4MAPPED)
955 /* Avoid generating the mapped addresses if we
956 know we are not going to need them. */
957 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
959 gethosts (AF_INET, struct in_addr);
961 if (req->ai_family == AF_INET)
963 no_inet6_data = no_data;
964 inet6_status = status;
968 /* If we found one address for AF_INET or AF_INET6,
969 don't continue the search. */
970 if (inet6_status == NSS_STATUS_SUCCESS
971 || status == NSS_STATUS_SUCCESS)
973 if ((req->ai_flags & AI_CANONNAME) != 0
974 && canon == NULL)
976 /* If we need the canonical name, get it
977 from the same service as the result. */
978 nss_getcanonname_r cfct;
979 int herrno;
981 cfct = __nss_lookup_function (nip,
982 "getcanonname_r");
983 if (cfct != NULL)
985 const size_t max_fqdn_len = 256;
986 if ((req->ai_flags & AI_CANONIDN) != 0
987 && __libc_use_alloca (alloca_used
988 + max_fqdn_len))
989 canonbuf = alloca_account (max_fqdn_len,
990 alloca_used);
991 else
993 canonbuf = malloc (max_fqdn_len);
994 if (canonbuf == NULL)
996 _res.options
997 |= old_res_options & RES_USE_INET6;
998 result = -EAI_MEMORY;
999 goto free_and_return;
1001 malloc_canonbuf = true;
1003 char *s;
1005 if (DL_CALL_FCT (cfct, (at->name ?: name,
1006 canonbuf,
1007 max_fqdn_len,
1008 &s, &rc, &herrno))
1009 == NSS_STATUS_SUCCESS)
1010 canon = s;
1011 else
1013 /* Set to name now to avoid using
1014 gethostbyaddr. */
1015 if (malloc_canonbuf)
1017 free (canonbuf);
1018 malloc_canonbuf = false;
1020 canon = name;
1024 status = NSS_STATUS_SUCCESS;
1026 else
1028 /* We can have different states for AF_INET and
1029 AF_INET6. Try to find a useful one for both. */
1030 if (inet6_status == NSS_STATUS_TRYAGAIN)
1031 status = NSS_STATUS_TRYAGAIN;
1032 else if (status == NSS_STATUS_UNAVAIL
1033 && inet6_status != NSS_STATUS_UNAVAIL)
1034 status = inet6_status;
1037 else
1038 status = NSS_STATUS_UNAVAIL;
1041 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1042 break;
1044 if (nip->next == NULL)
1045 no_more = -1;
1046 else
1047 nip = nip->next;
1050 _res.options |= old_res_options & RES_USE_INET6;
1052 if (status == NSS_STATUS_UNAVAIL)
1054 result = GAIH_OKIFUNSPEC | -EAI_SYSTEM;
1055 goto free_and_return;
1058 if (no_data != 0 && no_inet6_data != 0)
1060 /* If both requests timed out report this. */
1061 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1062 result = -EAI_AGAIN;
1063 else
1064 /* We made requests but they turned out no data. The name
1065 is known, though. */
1066 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1068 goto free_and_return;
1072 process_list:
1073 if (at->family == AF_UNSPEC)
1075 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1076 goto free_and_return;
1079 else
1081 struct gaih_addrtuple *atr;
1082 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1083 memset (at, '\0', sizeof (struct gaih_addrtuple));
1085 if (req->ai_family == AF_UNSPEC)
1087 at->next = __alloca (sizeof (struct gaih_addrtuple));
1088 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1091 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1093 at->family = AF_INET6;
1094 if ((req->ai_flags & AI_PASSIVE) == 0)
1095 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1096 atr = at->next;
1099 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1101 atr->family = AF_INET;
1102 if ((req->ai_flags & AI_PASSIVE) == 0)
1103 atr->addr[0] = htonl (INADDR_LOOPBACK);
1108 struct gaih_servtuple *st2;
1109 struct gaih_addrtuple *at2 = at;
1110 size_t socklen;
1111 sa_family_t family;
1114 buffer is the size of an unformatted IPv6 address in printable format.
1116 while (at2 != NULL)
1118 /* Only the first entry gets the canonical name. */
1119 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1121 char *tmpbuf2 = NULL;
1122 bool malloc_tmpbuf2 = false;
1124 if (canon == NULL)
1126 struct hostent *h = NULL;
1127 int herrno;
1128 struct hostent th;
1129 /* Add room for struct host_data. */
1130 size_t tmpbuf2len = (512 + (MAX_NR_ALIASES+MAX_NR_ADDRS+1)
1131 * sizeof(char*) + 16 * sizeof(char));
1135 if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1136 tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1137 tmpbuf2len * 2,
1138 alloca_used);
1139 else
1141 char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1142 2 * tmpbuf2len);
1143 if (newp == NULL)
1145 if (malloc_tmpbuf2)
1146 free (tmpbuf2);
1147 result = -EAI_MEMORY;
1148 goto free_and_return;
1151 tmpbuf2 = newp;
1152 tmpbuf2len = 2 * tmpbuf2len;
1153 malloc_tmpbuf2 = true;
1156 rc = __gethostbyaddr_r (at2->addr,
1157 ((at2->family == AF_INET6)
1158 ? sizeof (struct in6_addr)
1159 : sizeof (struct in_addr)),
1160 at2->family, &th, tmpbuf2,
1161 tmpbuf2len, &h, &herrno);
1163 while (rc == ERANGE && herrno == NETDB_INTERNAL);
1165 if (rc != 0 && herrno == NETDB_INTERNAL)
1167 if (malloc_tmpbuf2)
1168 free (tmpbuf2);
1170 __set_h_errno (herrno);
1171 result = -EAI_SYSTEM;
1172 goto free_and_return;
1175 if (h != NULL)
1176 canon = h->h_name;
1177 else
1179 assert (orig_name != NULL);
1180 /* If the canonical name cannot be determined, use
1181 the passed in string. */
1182 canon = orig_name;
1186 #ifdef HAVE_LIBIDN
1187 if (req->ai_flags & AI_CANONIDN)
1189 int idn_flags = 0;
1190 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1191 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1192 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1193 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1195 char *out;
1196 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1197 if (rc != IDNA_SUCCESS)
1199 if (malloc_tmpbuf2)
1200 free (tmpbuf2);
1202 if (rc == IDNA_MALLOC_ERROR)
1203 result = -EAI_MEMORY;
1204 else if (rc == IDNA_DLOPEN_ERROR)
1205 result = -EAI_SYSTEM;
1206 else
1207 result = -EAI_IDN_ENCODE;
1208 goto free_and_return;
1210 /* In case the output string is the same as the input
1211 string no new string has been allocated and we
1212 make a copy. */
1213 if (out == canon)
1214 goto make_copy;
1215 canon = out;
1217 else
1218 #endif
1220 #ifdef HAVE_LIBIDN
1221 make_copy:
1222 #endif
1223 if (malloc_canonbuf)
1224 /* We already allocated the string using malloc. */
1225 malloc_canonbuf = false;
1226 else
1228 canon = strdup (canon);
1229 if (canon == NULL)
1231 if (malloc_tmpbuf2)
1232 free (tmpbuf2);
1234 result = -EAI_MEMORY;
1235 goto free_and_return;
1240 if (malloc_tmpbuf2)
1241 free (tmpbuf2);
1244 family = at2->family;
1245 if (family == AF_INET6)
1247 socklen = sizeof (struct sockaddr_in6);
1249 /* If we looked up IPv4 mapped address discard them here if
1250 the caller isn't interested in all address and we have
1251 found at least one IPv6 address. */
1252 if (got_ipv6
1253 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1254 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1255 goto ignore;
1257 else
1258 socklen = sizeof (struct sockaddr_in);
1260 for (st2 = st; st2 != NULL; st2 = st2->next)
1262 struct addrinfo *ai;
1263 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1264 if (ai == NULL)
1266 free ((char *) canon);
1267 result = -EAI_MEMORY;
1268 goto free_and_return;
1271 ai->ai_flags = req->ai_flags;
1272 ai->ai_family = family;
1273 ai->ai_socktype = st2->socktype;
1274 ai->ai_protocol = st2->protocol;
1275 ai->ai_addrlen = socklen;
1276 ai->ai_addr = (void *) (ai + 1);
1278 /* We only add the canonical name once. */
1279 ai->ai_canonname = (char *) canon;
1280 canon = NULL;
1282 #ifdef _HAVE_SA_LEN
1283 ai->ai_addr->sa_len = socklen;
1284 #endif /* _HAVE_SA_LEN */
1285 ai->ai_addr->sa_family = family;
1287 /* In case of an allocation error the list must be NULL
1288 terminated. */
1289 ai->ai_next = NULL;
1291 if (family == AF_INET6)
1293 struct sockaddr_in6 *sin6p =
1294 (struct sockaddr_in6 *) ai->ai_addr;
1296 sin6p->sin6_port = st2->port;
1297 sin6p->sin6_flowinfo = 0;
1298 memcpy (&sin6p->sin6_addr,
1299 at2->addr, sizeof (struct in6_addr));
1300 sin6p->sin6_scope_id = at2->scopeid;
1302 else
1304 struct sockaddr_in *sinp =
1305 (struct sockaddr_in *) ai->ai_addr;
1306 sinp->sin_port = st2->port;
1307 memcpy (&sinp->sin_addr,
1308 at2->addr, sizeof (struct in_addr));
1309 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1312 pai = &(ai->ai_next);
1315 ++*naddrs;
1317 ignore:
1318 at2 = at2->next;
1322 free_and_return:
1323 if (malloc_name)
1324 free ((char *) name);
1325 if (malloc_addrmem)
1326 free (addrmem);
1327 if (malloc_canonbuf)
1328 free (canonbuf);
1329 if (malloc_tmpbuf)
1330 free (tmpbuf);
1332 return result;
1336 struct sort_result
1338 struct addrinfo *dest_addr;
1339 /* Using sockaddr_storage is for now overkill. We only support IPv4
1340 and IPv6 so far. If this changes at some point we can adjust the
1341 type here. */
1342 struct sockaddr_in6 source_addr;
1343 uint8_t source_addr_len;
1344 bool got_source_addr;
1345 uint8_t source_addr_flags;
1346 uint8_t prefixlen;
1347 uint32_t index;
1348 int32_t native;
1351 struct sort_result_combo
1353 struct sort_result *results;
1354 int nresults;
1358 #if __BYTE_ORDER == __BIG_ENDIAN
1359 # define htonl_c(n) n
1360 #else
1361 # define htonl_c(n) __bswap_constant_32 (n)
1362 #endif
1364 static const struct scopeentry
1366 union
1368 char addr[4];
1369 uint32_t addr32;
1371 uint32_t netmask;
1372 int32_t scope;
1373 } default_scopes[] =
1375 /* Link-local addresses: scope 2. */
1376 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1377 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1378 /* Default: scope 14. */
1379 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1382 /* The label table. */
1383 static const struct scopeentry *scopes;
1386 static int
1387 get_scope (const struct sockaddr_in6 *in6)
1389 int scope;
1390 if (in6->sin6_family == PF_INET6)
1392 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1394 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1395 /* RFC 4291 2.5.3 says that the loopback address is to be
1396 treated like a link-local address. */
1397 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1398 scope = 2;
1399 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1400 scope = 5;
1401 else
1402 /* XXX Is this the correct default behavior? */
1403 scope = 14;
1405 else
1406 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1408 else if (in6->sin6_family == PF_INET)
1410 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1412 size_t cnt = 0;
1413 while (1)
1415 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1416 == scopes[cnt].addr32)
1417 return scopes[cnt].scope;
1419 ++cnt;
1421 /* NOTREACHED */
1423 else
1424 /* XXX What is a good default? */
1425 scope = 15;
1427 return scope;
1431 struct prefixentry
1433 struct in6_addr prefix;
1434 unsigned int bits;
1435 int val;
1439 /* The label table. */
1440 static const struct prefixentry *labels;
1442 /* Default labels. */
1443 static const struct prefixentry default_labels[] =
1445 /* See RFC 3484 for the details. */
1446 { { .__in6_u
1447 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1448 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1449 }, 128, 0 },
1450 { { .__in6_u
1451 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1453 }, 16, 2 },
1454 { { .__in6_u
1455 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1457 }, 96, 3 },
1458 { { .__in6_u
1459 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1460 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1461 }, 96, 4 },
1462 /* The next two entries differ from RFC 3484. We need to treat
1463 IPv6 site-local addresses special because they are never NATed,
1464 unlike site-locale IPv4 addresses. If this would not happen, on
1465 machines which have only IPv4 and IPv6 site-local addresses, the
1466 sorting would prefer the IPv6 site-local addresses, causing
1467 unnecessary delays when trying to connect to a global IPv6 address
1468 through a site-local IPv6 address. */
1469 { { .__in6_u
1470 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1472 }, 10, 5 },
1473 { { .__in6_u
1474 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1476 }, 7, 6 },
1477 /* Additional rule for Teredo tunnels. */
1478 { { .__in6_u
1479 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1481 }, 32, 7 },
1482 { { .__in6_u
1483 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1485 }, 0, 1 }
1489 /* The precedence table. */
1490 static const struct prefixentry *precedence;
1492 /* The default precedences. */
1493 static const struct prefixentry default_precedence[] =
1495 /* See RFC 3484 for the details. */
1496 { { .__in6_u
1497 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1499 }, 128, 50 },
1500 { { .__in6_u
1501 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1503 }, 16, 30 },
1504 { { .__in6_u
1505 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1506 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1507 }, 96, 20 },
1508 { { .__in6_u
1509 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1511 }, 96, 10 },
1512 { { .__in6_u
1513 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1515 }, 0, 40 }
1519 static int
1520 match_prefix (const struct sockaddr_in6 *in6,
1521 const struct prefixentry *list, int default_val)
1523 int idx;
1524 struct sockaddr_in6 in6_mem;
1526 if (in6->sin6_family == PF_INET)
1528 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1530 /* Construct a V4-to-6 mapped address. */
1531 in6_mem.sin6_family = PF_INET6;
1532 in6_mem.sin6_port = in->sin_port;
1533 in6_mem.sin6_flowinfo = 0;
1534 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1535 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1536 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1537 in6_mem.sin6_scope_id = 0;
1539 in6 = &in6_mem;
1541 else if (in6->sin6_family != PF_INET6)
1542 return default_val;
1544 for (idx = 0; ; ++idx)
1546 unsigned int bits = list[idx].bits;
1547 const uint8_t *mask = list[idx].prefix.s6_addr;
1548 const uint8_t *val = in6->sin6_addr.s6_addr;
1550 while (bits >= 8)
1552 if (*mask != *val)
1553 break;
1555 ++mask;
1556 ++val;
1557 bits -= 8;
1560 if (bits < 8)
1562 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1563 /* Match! */
1564 break;
1568 return list[idx].val;
1572 static int
1573 get_label (const struct sockaddr_in6 *in6)
1575 /* XXX What is a good default value? */
1576 return match_prefix (in6, labels, INT_MAX);
1580 static int
1581 get_precedence (const struct sockaddr_in6 *in6)
1583 /* XXX What is a good default value? */
1584 return match_prefix (in6, precedence, 0);
1588 /* Find last bit set in a word. */
1589 static int
1590 fls (uint32_t a)
1592 uint32_t mask;
1593 int n;
1594 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1595 if ((a & mask) != 0)
1596 break;
1597 return n;
1601 static int
1602 rfc3484_sort (const void *p1, const void *p2, void *arg)
1604 const size_t idx1 = *(const size_t *) p1;
1605 const size_t idx2 = *(const size_t *) p2;
1606 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1607 struct sort_result *a1 = &src->results[idx1];
1608 struct sort_result *a2 = &src->results[idx2];
1610 /* Rule 1: Avoid unusable destinations.
1611 We have the got_source_addr flag set if the destination is reachable. */
1612 if (a1->got_source_addr && ! a2->got_source_addr)
1613 return -1;
1614 if (! a1->got_source_addr && a2->got_source_addr)
1615 return 1;
1618 /* Rule 2: Prefer matching scope. Only interesting if both
1619 destination addresses are IPv6. */
1620 int a1_dst_scope
1621 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1623 int a2_dst_scope
1624 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1626 if (a1->got_source_addr)
1628 int a1_src_scope = get_scope (&a1->source_addr);
1629 int a2_src_scope = get_scope (&a2->source_addr);
1631 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1632 return -1;
1633 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1634 return 1;
1638 /* Rule 3: Avoid deprecated addresses. */
1639 if (a1->got_source_addr)
1641 if (!(a1->source_addr_flags & in6ai_deprecated)
1642 && (a2->source_addr_flags & in6ai_deprecated))
1643 return -1;
1644 if ((a1->source_addr_flags & in6ai_deprecated)
1645 && !(a2->source_addr_flags & in6ai_deprecated))
1646 return 1;
1649 /* Rule 4: Prefer home addresses. */
1650 if (a1->got_source_addr)
1652 if (!(a1->source_addr_flags & in6ai_homeaddress)
1653 && (a2->source_addr_flags & in6ai_homeaddress))
1654 return 1;
1655 if ((a1->source_addr_flags & in6ai_homeaddress)
1656 && !(a2->source_addr_flags & in6ai_homeaddress))
1657 return -1;
1660 /* Rule 5: Prefer matching label. */
1661 if (a1->got_source_addr)
1663 int a1_dst_label
1664 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1665 int a1_src_label = get_label (&a1->source_addr);
1667 int a2_dst_label
1668 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1669 int a2_src_label = get_label (&a2->source_addr);
1671 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1672 return -1;
1673 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1674 return 1;
1678 /* Rule 6: Prefer higher precedence. */
1679 int a1_prec
1680 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1681 int a2_prec
1682 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1684 if (a1_prec > a2_prec)
1685 return -1;
1686 if (a1_prec < a2_prec)
1687 return 1;
1690 /* Rule 7: Prefer native transport. */
1691 if (a1->got_source_addr)
1693 /* The same interface index means the same interface which means
1694 there is no difference in transport. This should catch many
1695 (most?) cases. */
1696 if (a1->index != a2->index)
1698 int a1_native = a1->native;
1699 int a2_native = a2->native;
1701 if (a1_native == -1 || a2_native == -1)
1703 uint32_t a1_index;
1704 if (a1_native == -1)
1706 /* If we do not have the information use 'native' as
1707 the default. */
1708 a1_native = 0;
1709 a1_index = a1->index;
1711 else
1712 a1_index = 0xffffffffu;
1714 uint32_t a2_index;
1715 if (a2_native == -1)
1717 /* If we do not have the information use 'native' as
1718 the default. */
1719 a2_native = 0;
1720 a2_index = a2->index;
1722 else
1723 a2_index = 0xffffffffu;
1725 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1727 /* Fill in the results in all the records. */
1728 for (int i = 0; i < src->nresults; ++i)
1729 if (src->results[i].index == a1_index)
1731 assert (src->results[i].native == -1
1732 || src->results[i].native == a1_native);
1733 src->results[i].native = a1_native;
1735 else if (src->results[i].index == a2_index)
1737 assert (src->results[i].native == -1
1738 || src->results[i].native == a2_native);
1739 src->results[i].native = a2_native;
1743 if (a1_native && !a2_native)
1744 return -1;
1745 if (!a1_native && a2_native)
1746 return 1;
1751 /* Rule 8: Prefer smaller scope. */
1752 if (a1_dst_scope < a2_dst_scope)
1753 return -1;
1754 if (a1_dst_scope > a2_dst_scope)
1755 return 1;
1758 /* Rule 9: Use longest matching prefix. */
1759 if (a1->got_source_addr
1760 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1762 int bit1 = 0;
1763 int bit2 = 0;
1765 if (a1->dest_addr->ai_family == PF_INET)
1767 assert (a1->source_addr.sin6_family == PF_INET);
1768 assert (a2->source_addr.sin6_family == PF_INET);
1770 /* Outside of subnets, as defined by the network masks,
1771 common address prefixes for IPv4 addresses make no sense.
1772 So, define a non-zero value only if source and
1773 destination address are on the same subnet. */
1774 struct sockaddr_in *in1_dst
1775 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1776 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1777 struct sockaddr_in *in1_src
1778 = (struct sockaddr_in *) &a1->source_addr;
1779 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1780 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1782 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1783 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1785 struct sockaddr_in *in2_dst
1786 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1787 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1788 struct sockaddr_in *in2_src
1789 = (struct sockaddr_in *) &a2->source_addr;
1790 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1791 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1793 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1794 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1796 else if (a1->dest_addr->ai_family == PF_INET6)
1798 assert (a1->source_addr.sin6_family == PF_INET6);
1799 assert (a2->source_addr.sin6_family == PF_INET6);
1801 struct sockaddr_in6 *in1_dst;
1802 struct sockaddr_in6 *in1_src;
1803 struct sockaddr_in6 *in2_dst;
1804 struct sockaddr_in6 *in2_src;
1806 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1807 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1808 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1809 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1811 int i;
1812 for (i = 0; i < 4; ++i)
1813 if (in1_dst->sin6_addr.s6_addr32[i]
1814 != in1_src->sin6_addr.s6_addr32[i]
1815 || (in2_dst->sin6_addr.s6_addr32[i]
1816 != in2_src->sin6_addr.s6_addr32[i]))
1817 break;
1819 if (i < 4)
1821 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1822 ^ in1_src->sin6_addr.s6_addr32[i]));
1823 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1824 ^ in2_src->sin6_addr.s6_addr32[i]));
1828 if (bit1 > bit2)
1829 return -1;
1830 if (bit1 < bit2)
1831 return 1;
1835 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1836 compare with the value indicating the order in which the entries
1837 have been received from the services. NB: no two entries can have
1838 the same order so the test will never return zero. */
1839 return idx1 < idx2 ? -1 : 1;
1843 static int
1844 in6aicmp (const void *p1, const void *p2)
1846 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1847 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1849 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1853 /* Name of the config file for RFC 3484 sorting (for now). */
1854 #define GAICONF_FNAME "/etc/gai.conf"
1857 /* Non-zero if we are supposed to reload the config file automatically
1858 whenever it changed. */
1859 static int gaiconf_reload_flag;
1861 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1862 static int gaiconf_reload_flag_ever_set;
1864 /* Last modification time. */
1865 #ifdef _STATBUF_ST_NSEC
1867 static struct timespec gaiconf_mtime;
1869 static inline void
1870 save_gaiconf_mtime (const struct stat64 *st)
1872 gaiconf_mtime = st->st_mtim;
1875 static inline bool
1876 check_gaiconf_mtime (const struct stat64 *st)
1878 return (st->st_mtim.tv_sec == gaiconf_mtime.tv_sec
1879 && st->st_mtim.tv_nsec == gaiconf_mtime.tv_nsec);
1882 #else
1884 static time_t gaiconf_mtime;
1886 static inline void
1887 save_gaiconf_mtime (const struct stat64 *st)
1889 gaiconf_mtime = st->st_mtime;
1892 static inline bool
1893 check_gaiconf_mtime (const struct stat64 *st)
1895 return st->st_mtime == gaiconf_mtime;
1898 #endif
1901 libc_freeres_fn(fini)
1903 if (labels != default_labels)
1905 const struct prefixentry *old = labels;
1906 labels = default_labels;
1907 free ((void *) old);
1910 if (precedence != default_precedence)
1912 const struct prefixentry *old = precedence;
1913 precedence = default_precedence;
1914 free ((void *) old);
1917 if (scopes != default_scopes)
1919 const struct scopeentry *old = scopes;
1920 scopes = default_scopes;
1921 free ((void *) old);
1926 struct prefixlist
1928 struct prefixentry entry;
1929 struct prefixlist *next;
1933 struct scopelist
1935 struct scopeentry entry;
1936 struct scopelist *next;
1940 static void
1941 free_prefixlist (struct prefixlist *list)
1943 while (list != NULL)
1945 struct prefixlist *oldp = list;
1946 list = list->next;
1947 free (oldp);
1952 static void
1953 free_scopelist (struct scopelist *list)
1955 while (list != NULL)
1957 struct scopelist *oldp = list;
1958 list = list->next;
1959 free (oldp);
1964 static int
1965 prefixcmp (const void *p1, const void *p2)
1967 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1968 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1970 if (e1->bits < e2->bits)
1971 return 1;
1972 if (e1->bits == e2->bits)
1973 return 0;
1974 return -1;
1978 static int
1979 scopecmp (const void *p1, const void *p2)
1981 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1982 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1984 if (e1->netmask > e2->netmask)
1985 return -1;
1986 if (e1->netmask == e2->netmask)
1987 return 0;
1988 return 1;
1992 static void
1993 gaiconf_init (void)
1995 struct prefixlist *labellist = NULL;
1996 size_t nlabellist = 0;
1997 bool labellist_nullbits = false;
1998 struct prefixlist *precedencelist = NULL;
1999 size_t nprecedencelist = 0;
2000 bool precedencelist_nullbits = false;
2001 struct scopelist *scopelist = NULL;
2002 size_t nscopelist = 0;
2003 bool scopelist_nullbits = false;
2005 FILE *fp = fopen (GAICONF_FNAME, "rce");
2006 if (fp != NULL)
2008 struct stat64 st;
2009 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
2011 fclose (fp);
2012 goto no_file;
2015 char *line = NULL;
2016 size_t linelen = 0;
2018 __fsetlocking (fp, FSETLOCKING_BYCALLER);
2020 while (!feof_unlocked (fp))
2022 ssize_t n = __getline (&line, &linelen, fp);
2023 if (n <= 0)
2024 break;
2026 /* Handle comments. No escaping possible so this is easy. */
2027 char *cp = strchr (line, '#');
2028 if (cp != NULL)
2029 *cp = '\0';
2031 cp = line;
2032 while (isspace (*cp))
2033 ++cp;
2035 char *cmd = cp;
2036 while (*cp != '\0' && !isspace (*cp))
2037 ++cp;
2038 size_t cmdlen = cp - cmd;
2040 if (*cp != '\0')
2041 *cp++ = '\0';
2042 while (isspace (*cp))
2043 ++cp;
2045 char *val1 = cp;
2046 while (*cp != '\0' && !isspace (*cp))
2047 ++cp;
2048 size_t val1len = cp - cmd;
2050 /* We always need at least two values. */
2051 if (val1len == 0)
2052 continue;
2054 if (*cp != '\0')
2055 *cp++ = '\0';
2056 while (isspace (*cp))
2057 ++cp;
2059 char *val2 = cp;
2060 while (*cp != '\0' && !isspace (*cp))
2061 ++cp;
2063 /* Ignore the rest of the line. */
2064 *cp = '\0';
2066 struct prefixlist **listp;
2067 size_t *lenp;
2068 bool *nullbitsp;
2069 switch (cmdlen)
2071 case 5:
2072 if (strcmp (cmd, "label") == 0)
2074 struct in6_addr prefix;
2075 unsigned long int bits;
2076 unsigned long int val;
2077 char *endp;
2079 listp = &labellist;
2080 lenp = &nlabellist;
2081 nullbitsp = &labellist_nullbits;
2083 new_elem:
2084 bits = 128;
2085 __set_errno (0);
2086 cp = strchr (val1, '/');
2087 if (cp != NULL)
2088 *cp++ = '\0';
2089 if (inet_pton (AF_INET6, val1, &prefix)
2090 && (cp == NULL
2091 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2092 || errno != ERANGE)
2093 && *endp == '\0'
2094 && bits <= 128
2095 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2096 || errno != ERANGE)
2097 && *endp == '\0'
2098 && val <= INT_MAX)
2100 struct prefixlist *newp = malloc (sizeof (*newp));
2101 if (newp == NULL)
2103 free (line);
2104 fclose (fp);
2105 goto no_file;
2108 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2109 newp->entry.bits = bits;
2110 newp->entry.val = val;
2111 newp->next = *listp;
2112 *listp = newp;
2113 ++*lenp;
2114 *nullbitsp |= bits == 0;
2117 break;
2119 case 6:
2120 if (strcmp (cmd, "reload") == 0)
2122 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2123 if (gaiconf_reload_flag)
2124 gaiconf_reload_flag_ever_set = 1;
2126 break;
2128 case 7:
2129 if (strcmp (cmd, "scopev4") == 0)
2131 struct in6_addr prefix;
2132 unsigned long int bits;
2133 unsigned long int val;
2134 char *endp;
2136 bits = 32;
2137 __set_errno (0);
2138 cp = strchr (val1, '/');
2139 if (cp != NULL)
2140 *cp++ = '\0';
2141 if (inet_pton (AF_INET6, val1, &prefix))
2143 bits = 128;
2144 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2145 && (cp == NULL
2146 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2147 || errno != ERANGE)
2148 && *endp == '\0'
2149 && bits >= 96
2150 && bits <= 128
2151 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2152 || errno != ERANGE)
2153 && *endp == '\0'
2154 && val <= INT_MAX)
2156 struct scopelist *newp;
2157 new_scope:
2158 newp = malloc (sizeof (*newp));
2159 if (newp == NULL)
2161 free (line);
2162 fclose (fp);
2163 goto no_file;
2166 newp->entry.netmask = htonl (bits != 96
2167 ? (0xffffffff
2168 << (128 - bits))
2169 : 0);
2170 newp->entry.addr32 = (prefix.s6_addr32[3]
2171 & newp->entry.netmask);
2172 newp->entry.scope = val;
2173 newp->next = scopelist;
2174 scopelist = newp;
2175 ++nscopelist;
2176 scopelist_nullbits |= bits == 96;
2179 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2180 && (cp == NULL
2181 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2182 || errno != ERANGE)
2183 && *endp == '\0'
2184 && bits <= 32
2185 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2186 || errno != ERANGE)
2187 && *endp == '\0'
2188 && val <= INT_MAX)
2190 bits += 96;
2191 goto new_scope;
2194 break;
2196 case 10:
2197 if (strcmp (cmd, "precedence") == 0)
2199 listp = &precedencelist;
2200 lenp = &nprecedencelist;
2201 nullbitsp = &precedencelist_nullbits;
2202 goto new_elem;
2204 break;
2208 free (line);
2210 fclose (fp);
2212 /* Create the array for the labels. */
2213 struct prefixentry *new_labels;
2214 if (nlabellist > 0)
2216 if (!labellist_nullbits)
2217 ++nlabellist;
2218 new_labels = malloc (nlabellist * sizeof (*new_labels));
2219 if (new_labels == NULL)
2220 goto no_file;
2222 int i = nlabellist;
2223 if (!labellist_nullbits)
2225 --i;
2226 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2227 new_labels[i].bits = 0;
2228 new_labels[i].val = 1;
2231 struct prefixlist *l = labellist;
2232 while (i-- > 0)
2234 new_labels[i] = l->entry;
2235 l = l->next;
2237 free_prefixlist (labellist);
2239 /* Sort the entries so that the most specific ones are at
2240 the beginning. */
2241 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2243 else
2244 new_labels = (struct prefixentry *) default_labels;
2246 struct prefixentry *new_precedence;
2247 if (nprecedencelist > 0)
2249 if (!precedencelist_nullbits)
2250 ++nprecedencelist;
2251 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2252 if (new_precedence == NULL)
2254 if (new_labels != default_labels)
2255 free (new_labels);
2256 goto no_file;
2259 int i = nprecedencelist;
2260 if (!precedencelist_nullbits)
2262 --i;
2263 memset (&new_precedence[i].prefix, '\0',
2264 sizeof (struct in6_addr));
2265 new_precedence[i].bits = 0;
2266 new_precedence[i].val = 40;
2269 struct prefixlist *l = precedencelist;
2270 while (i-- > 0)
2272 new_precedence[i] = l->entry;
2273 l = l->next;
2275 free_prefixlist (precedencelist);
2277 /* Sort the entries so that the most specific ones are at
2278 the beginning. */
2279 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2280 prefixcmp);
2282 else
2283 new_precedence = (struct prefixentry *) default_precedence;
2285 struct scopeentry *new_scopes;
2286 if (nscopelist > 0)
2288 if (!scopelist_nullbits)
2289 ++nscopelist;
2290 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2291 if (new_scopes == NULL)
2293 if (new_labels != default_labels)
2294 free (new_labels);
2295 if (new_precedence != default_precedence)
2296 free (new_precedence);
2297 goto no_file;
2300 int i = nscopelist;
2301 if (!scopelist_nullbits)
2303 --i;
2304 new_scopes[i].addr32 = 0;
2305 new_scopes[i].netmask = 0;
2306 new_scopes[i].scope = 14;
2309 struct scopelist *l = scopelist;
2310 while (i-- > 0)
2312 new_scopes[i] = l->entry;
2313 l = l->next;
2315 free_scopelist (scopelist);
2317 /* Sort the entries so that the most specific ones are at
2318 the beginning. */
2319 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2320 scopecmp);
2322 else
2323 new_scopes = (struct scopeentry *) default_scopes;
2325 /* Now we are ready to replace the values. */
2326 const struct prefixentry *old = labels;
2327 labels = new_labels;
2328 if (old != default_labels)
2329 free ((void *) old);
2331 old = precedence;
2332 precedence = new_precedence;
2333 if (old != default_precedence)
2334 free ((void *) old);
2336 const struct scopeentry *oldscope = scopes;
2337 scopes = new_scopes;
2338 if (oldscope != default_scopes)
2339 free ((void *) oldscope);
2341 save_gaiconf_mtime (&st);
2343 else
2345 no_file:
2346 free_prefixlist (labellist);
2347 free_prefixlist (precedencelist);
2348 free_scopelist (scopelist);
2350 /* If we previously read the file but it is gone now, free the
2351 old data and use the builtin one. Leave the reload flag
2352 alone. */
2353 fini ();
2358 static void
2359 gaiconf_reload (void)
2361 struct stat64 st;
2362 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2363 || !check_gaiconf_mtime (&st))
2364 gaiconf_init ();
2369 getaddrinfo (const char *name, const char *service,
2370 const struct addrinfo *hints, struct addrinfo **pai)
2372 int i = 0, last_i = 0;
2373 int nresults = 0;
2374 struct addrinfo *p = NULL;
2375 struct gaih_service gaih_service, *pservice;
2376 struct addrinfo local_hints;
2378 if (name != NULL && name[0] == '*' && name[1] == 0)
2379 name = NULL;
2381 if (service != NULL && service[0] == '*' && service[1] == 0)
2382 service = NULL;
2384 if (name == NULL && service == NULL)
2385 return EAI_NONAME;
2387 if (hints == NULL)
2388 hints = &default_hints;
2390 if (hints->ai_flags
2391 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2392 #ifdef HAVE_LIBIDN
2393 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2394 |AI_IDN_USE_STD3_ASCII_RULES
2395 #endif
2396 |AI_NUMERICSERV|AI_ALL))
2397 return EAI_BADFLAGS;
2399 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2400 return EAI_BADFLAGS;
2402 struct in6addrinfo *in6ai = NULL;
2403 size_t in6ailen = 0;
2404 bool seen_ipv4 = false;
2405 bool seen_ipv6 = false;
2406 bool check_pf_called = false;
2408 if (hints->ai_flags & AI_ADDRCONFIG)
2410 /* We might need information about what interfaces are available.
2411 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2412 cannot cache the results since new interfaces could be added at
2413 any time. */
2414 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2415 check_pf_called = true;
2417 /* Now make a decision on what we return, if anything. */
2418 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2420 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2421 narrow down the search. */
2422 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2424 local_hints = *hints;
2425 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2426 hints = &local_hints;
2429 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2430 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2432 /* We cannot possibly return a valid answer. */
2433 __free_in6ai (in6ai);
2434 return EAI_NONAME;
2438 if (service && service[0])
2440 char *c;
2441 gaih_service.name = service;
2442 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2443 if (*c != '\0')
2445 if (hints->ai_flags & AI_NUMERICSERV)
2447 __free_in6ai (in6ai);
2448 return EAI_NONAME;
2451 gaih_service.num = -1;
2454 pservice = &gaih_service;
2456 else
2457 pservice = NULL;
2459 struct addrinfo **end = &p;
2461 unsigned int naddrs = 0;
2462 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2463 || hints->ai_family == AF_INET6)
2465 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2466 if (last_i != 0)
2468 freeaddrinfo (p);
2469 __free_in6ai (in6ai);
2471 return -(last_i & GAIH_EAI);
2473 while (*end)
2475 end = &((*end)->ai_next);
2476 ++nresults;
2479 else
2481 __free_in6ai (in6ai);
2482 return EAI_FAMILY;
2485 if (naddrs > 1)
2487 /* Read the config file. */
2488 __libc_once_define (static, once);
2489 __typeof (once) old_once = once;
2490 __libc_once (once, gaiconf_init);
2491 /* Sort results according to RFC 3484. */
2492 struct sort_result results[nresults];
2493 size_t order[nresults];
2494 struct addrinfo *q;
2495 struct addrinfo *last = NULL;
2496 char *canonname = NULL;
2498 /* Now we definitely need the interface information. */
2499 if (! check_pf_called)
2500 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2502 /* If we have information about deprecated and temporary addresses
2503 sort the array now. */
2504 if (in6ai != NULL)
2505 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2507 int fd = -1;
2508 int af = AF_UNSPEC;
2510 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2512 results[i].dest_addr = q;
2513 results[i].native = -1;
2514 order[i] = i;
2516 /* If we just looked up the address for a different
2517 protocol, reuse the result. */
2518 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2519 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2521 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2522 results[i - 1].source_addr_len);
2523 results[i].source_addr_len = results[i - 1].source_addr_len;
2524 results[i].got_source_addr = results[i - 1].got_source_addr;
2525 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2526 results[i].prefixlen = results[i - 1].prefixlen;
2527 results[i].index = results[i - 1].index;
2529 else
2531 results[i].got_source_addr = false;
2532 results[i].source_addr_flags = 0;
2533 results[i].prefixlen = 0;
2534 results[i].index = 0xffffffffu;
2536 /* We overwrite the type with SOCK_DGRAM since we do not
2537 want connect() to connect to the other side. If we
2538 cannot determine the source address remember this
2539 fact. */
2540 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2542 if (fd != -1)
2543 close_retry:
2544 close_not_cancel_no_status (fd);
2545 af = q->ai_family;
2546 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2548 else
2550 /* Reset the connection. */
2551 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2552 __connect (fd, &sa, sizeof (sa));
2555 socklen_t sl = sizeof (results[i].source_addr);
2556 if (fd != -1
2557 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2558 && __getsockname (fd,
2559 (struct sockaddr *) &results[i].source_addr,
2560 &sl) == 0)
2562 results[i].source_addr_len = sl;
2563 results[i].got_source_addr = true;
2565 if (in6ai != NULL)
2567 /* See whether the source address is on the list of
2568 deprecated or temporary addresses. */
2569 struct in6addrinfo tmp;
2571 if (q->ai_family == AF_INET && af == AF_INET)
2573 struct sockaddr_in *sinp
2574 = (struct sockaddr_in *) &results[i].source_addr;
2575 tmp.addr[0] = 0;
2576 tmp.addr[1] = 0;
2577 tmp.addr[2] = htonl (0xffff);
2578 tmp.addr[3] = sinp->sin_addr.s_addr;
2580 else
2582 struct sockaddr_in6 *sin6p
2583 = (struct sockaddr_in6 *) &results[i].source_addr;
2584 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2587 struct in6addrinfo *found
2588 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2589 in6aicmp);
2590 if (found != NULL)
2592 results[i].source_addr_flags = found->flags;
2593 results[i].prefixlen = found->prefixlen;
2594 results[i].index = found->index;
2598 if (q->ai_family == AF_INET && af == AF_INET6)
2600 /* We have to convert the address. The socket is
2601 IPv6 and the request is for IPv4. */
2602 struct sockaddr_in6 *sin6
2603 = (struct sockaddr_in6 *) &results[i].source_addr;
2604 struct sockaddr_in *sin
2605 = (struct sockaddr_in *) &results[i].source_addr;
2606 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2607 sin->sin_family = AF_INET;
2608 /* We do not have to initialize sin_port since this
2609 fields has the same position and size in the IPv6
2610 structure. */
2611 assert (offsetof (struct sockaddr_in, sin_port)
2612 == offsetof (struct sockaddr_in6, sin6_port));
2613 assert (sizeof (sin->sin_port)
2614 == sizeof (sin6->sin6_port));
2615 memcpy (&sin->sin_addr,
2616 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2617 results[i].source_addr_len = sizeof (struct sockaddr_in);
2620 else if (errno == EAFNOSUPPORT && af == AF_INET6
2621 && q->ai_family == AF_INET)
2622 /* This could mean IPv6 sockets are IPv6-only. */
2623 goto close_retry;
2624 else
2625 /* Just make sure that if we have to process the same
2626 address again we do not copy any memory. */
2627 results[i].source_addr_len = 0;
2630 /* Remember the canonical name. */
2631 if (q->ai_canonname != NULL)
2633 assert (canonname == NULL);
2634 canonname = q->ai_canonname;
2635 q->ai_canonname = NULL;
2639 if (fd != -1)
2640 close_not_cancel_no_status (fd);
2642 /* We got all the source addresses we can get, now sort using
2643 the information. */
2644 struct sort_result_combo src
2645 = { .results = results, .nresults = nresults };
2646 if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2648 __libc_lock_define_initialized (static, lock);
2650 __libc_lock_lock (lock);
2651 if (__libc_once_get (old_once) && gaiconf_reload_flag)
2652 gaiconf_reload ();
2653 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2654 __libc_lock_unlock (lock);
2656 else
2657 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2659 /* Queue the results up as they come out of sorting. */
2660 q = p = results[order[0]].dest_addr;
2661 for (i = 1; i < nresults; ++i)
2662 q = q->ai_next = results[order[i]].dest_addr;
2663 q->ai_next = NULL;
2665 /* Fill in the canonical name into the new first entry. */
2666 p->ai_canonname = canonname;
2669 __free_in6ai (in6ai);
2671 if (p)
2673 *pai = p;
2674 return 0;
2677 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2679 libc_hidden_def (getaddrinfo)
2681 nss_interface_function (getaddrinfo)
2683 void
2684 freeaddrinfo (struct addrinfo *ai)
2686 struct addrinfo *p;
2688 while (ai != NULL)
2690 p = ai;
2691 ai = ai->ai_next;
2692 free (p->ai_canonname);
2693 free (p);
2696 libc_hidden_def (freeaddrinfo)