Fix Ipv4&IPv6 lookup in getaddrinfo
[glibc.git] / sysdeps / posix / getaddrinfo.c
blob14e9270b1b8133243e331798f3022ef83454de8a
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)
435 malloc_name = true;
437 #endif
439 if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
441 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
442 at->family = AF_INET;
443 else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
445 at->addr[3] = at->addr[0];
446 at->addr[2] = htonl (0xffff);
447 at->addr[1] = 0;
448 at->addr[0] = 0;
449 at->family = AF_INET6;
451 else
453 result = -EAI_ADDRFAMILY;
454 goto free_and_return;
457 if (req->ai_flags & AI_CANONNAME)
458 canon = name;
460 else if (at->family == AF_UNSPEC)
462 char *scope_delim = strchr (name, SCOPE_DELIMITER);
463 int e;
466 bool malloc_namebuf = false;
467 char *namebuf = (char *) name;
469 if (__builtin_expect (scope_delim != NULL, 0))
471 if (malloc_name)
472 *scope_delim = '\0';
473 else
475 if (__libc_use_alloca (alloca_used
476 + scope_delim - name + 1))
478 namebuf = alloca_account (scope_delim - name + 1,
479 alloca_used);
480 *((char *) __mempcpy (namebuf, name,
481 scope_delim - name)) = '\0';
483 else
485 namebuf = strndup (name, scope_delim - name);
486 if (namebuf == NULL)
488 assert (!malloc_name);
489 return -EAI_MEMORY;
491 malloc_namebuf = true;
496 e = inet_pton (AF_INET6, namebuf, at->addr);
498 if (malloc_namebuf)
499 free (namebuf);
500 else if (scope_delim != NULL && malloc_name)
501 /* Undo what we did above. */
502 *scope_delim = SCOPE_DELIMITER;
504 if (e > 0)
506 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
507 at->family = AF_INET6;
508 else if (req->ai_family == AF_INET
509 && IN6_IS_ADDR_V4MAPPED (at->addr))
511 at->addr[0] = at->addr[3];
512 at->family = AF_INET;
514 else
516 result = -EAI_ADDRFAMILY;
517 goto free_and_return;
520 if (scope_delim != NULL)
522 int try_numericscope = 0;
523 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
524 || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
526 at->scopeid = if_nametoindex (scope_delim + 1);
527 if (at->scopeid == 0)
528 try_numericscope = 1;
530 else
531 try_numericscope = 1;
533 if (try_numericscope != 0)
535 char *end;
536 assert (sizeof (uint32_t) <= sizeof (unsigned long));
537 at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
538 10);
539 if (*end != '\0')
541 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
542 goto free_and_return;
547 if (req->ai_flags & AI_CANONNAME)
548 canon = name;
552 if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
554 struct gaih_addrtuple **pat = &at;
555 int no_data = 0;
556 int no_inet6_data = 0;
557 service_user *nip = NULL;
558 enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
559 enum nss_status status = NSS_STATUS_UNAVAIL;
560 int no_more;
561 int old_res_options;
563 /* If we do not have to look for IPv6 addresses, use
564 the simple, old functions, which do not support
565 IPv6 scope ids. */
566 if (req->ai_family == AF_INET)
568 size_t tmpbuflen = 512;
569 assert (tmpbuf == NULL);
570 tmpbuf = alloca_account (tmpbuflen, alloca_used);
571 int rc;
572 struct hostent th;
573 struct hostent *h;
574 int herrno;
576 while (1)
578 rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
579 tmpbuflen, &h, &herrno);
580 if (rc != ERANGE || herrno != NETDB_INTERNAL)
581 break;
583 if (!malloc_tmpbuf
584 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
585 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
586 2 * tmpbuflen,
587 alloca_used);
588 else
590 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
591 2 * tmpbuflen);
592 if (newp == NULL)
594 result = -EAI_MEMORY;
595 goto free_and_return;
597 tmpbuf = newp;
598 malloc_tmpbuf = true;
599 tmpbuflen = 2 * tmpbuflen;
603 if (rc == 0)
605 if (h != NULL)
607 int i;
608 /* We found data, count the number of addresses. */
609 for (i = 0; h->h_addr_list[i]; ++i)
611 if (i > 0 && *pat != NULL)
612 --i;
614 if (__libc_use_alloca (alloca_used
615 + i * sizeof (struct gaih_addrtuple)))
616 addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
617 alloca_used);
618 else
620 addrmem = malloc (i
621 * sizeof (struct gaih_addrtuple));
622 if (addrmem == NULL)
624 result = -EAI_MEMORY;
625 goto free_and_return;
627 malloc_addrmem = true;
630 /* Now convert it into the list. */
631 struct gaih_addrtuple *addrfree = addrmem;
632 for (i = 0; h->h_addr_list[i]; ++i)
634 if (*pat == NULL)
636 *pat = addrfree++;
637 (*pat)->scopeid = 0;
639 (*pat)->next = NULL;
640 (*pat)->family = AF_INET;
641 memcpy ((*pat)->addr, h->h_addr_list[i],
642 h->h_length);
643 pat = &((*pat)->next);
647 else
649 if (herrno == NETDB_INTERNAL)
651 __set_h_errno (herrno);
652 result = -EAI_SYSTEM;
654 else if (herrno == TRY_AGAIN)
655 result = -EAI_AGAIN;
656 else
657 /* We made requests but they turned out no data.
658 The name is known, though. */
659 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
661 goto free_and_return;
664 goto process_list;
667 #ifdef USE_NSCD
668 if (__nss_not_use_nscd_hosts > 0
669 && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
670 __nss_not_use_nscd_hosts = 0;
672 if (!__nss_not_use_nscd_hosts
673 && !__nss_database_custom[NSS_DBSIDX_hosts])
675 /* Try to use nscd. */
676 struct nscd_ai_result *air = NULL;
677 int herrno;
678 int err = __nscd_getai (name, &air, &herrno);
679 if (air != NULL)
681 /* Transform into gaih_addrtuple list. */
682 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
683 char *addrs = air->addrs;
685 if (__libc_use_alloca (alloca_used
686 + air->naddrs * sizeof (struct gaih_addrtuple)))
687 addrmem = alloca_account (air->naddrs
688 * sizeof (struct gaih_addrtuple),
689 alloca_used);
690 else
692 addrmem = malloc (air->naddrs
693 * sizeof (struct gaih_addrtuple));
694 if (addrmem == NULL)
696 result = -EAI_MEMORY;
697 goto free_and_return;
699 malloc_addrmem = true;
702 struct gaih_addrtuple *addrfree = addrmem;
703 for (int i = 0; i < air->naddrs; ++i)
705 socklen_t size = (air->family[i] == AF_INET
706 ? INADDRSZ : IN6ADDRSZ);
707 if (*pat == NULL)
709 *pat = addrfree++;
710 (*pat)->scopeid = 0;
712 uint32_t *pataddr = (*pat)->addr;
713 (*pat)->next = NULL;
714 if (added_canon || air->canon == NULL)
715 (*pat)->name = NULL;
716 else if (canonbuf == NULL)
718 size_t canonlen = strlen (air->canon) + 1;
719 if ((req->ai_flags & AI_CANONIDN) != 0
720 && __libc_use_alloca (alloca_used + canonlen))
721 canonbuf = alloca_account (canonlen, alloca_used);
722 else
724 canonbuf = malloc (canonlen);
725 if (canonbuf == NULL)
727 result = -EAI_MEMORY;
728 goto free_and_return;
730 malloc_canonbuf = true;
732 canon = (*pat)->name = memcpy (canonbuf, air->canon,
733 canonlen);
736 if (air->family[i] == AF_INET
737 && req->ai_family == AF_INET6
738 && (req->ai_flags & AI_V4MAPPED))
740 (*pat)->family = AF_INET6;
741 pataddr[3] = *(uint32_t *) addrs;
742 pataddr[2] = htonl (0xffff);
743 pataddr[1] = 0;
744 pataddr[0] = 0;
745 pat = &((*pat)->next);
746 added_canon = true;
748 else if (req->ai_family == AF_UNSPEC
749 || air->family[i] == req->ai_family)
751 (*pat)->family = air->family[i];
752 memcpy (pataddr, addrs, size);
753 pat = &((*pat)->next);
754 added_canon = true;
755 if (air->family[i] == AF_INET6)
756 got_ipv6 = true;
758 addrs += size;
761 free (air);
763 if (at->family == AF_UNSPEC)
765 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
766 goto free_and_return;
769 goto process_list;
771 else if (err == 0)
772 /* The database contains a negative entry. */
773 goto free_and_return;
774 else if (__nss_not_use_nscd_hosts == 0)
776 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
777 result = -EAI_MEMORY;
778 else if (herrno == TRY_AGAIN)
779 result = -EAI_AGAIN;
780 else
781 result = -EAI_SYSTEM;
783 goto free_and_return;
786 #endif
788 if (__nss_hosts_database != NULL)
790 no_more = 0;
791 nip = __nss_hosts_database;
793 else
794 no_more = __nss_database_lookup ("hosts", NULL,
795 "dns [!UNAVAIL=return] files",
796 &nip);
798 /* Initialize configurations. */
799 if (__builtin_expect (!_res_hconf.initialized, 0))
800 _res_hconf_init ();
801 if (__res_maybe_init (&_res, 0) == -1)
802 no_more = 1;
804 /* If we are looking for both IPv4 and IPv6 address we don't
805 want the lookup functions to automatically promote IPv4
806 addresses to IPv6 addresses. Currently this is decided
807 by setting the RES_USE_INET6 bit in _res.options. */
808 old_res_options = _res.options;
809 _res.options &= ~RES_USE_INET6;
811 size_t tmpbuflen = 1024;
812 malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
813 assert (tmpbuf == NULL);
814 if (!malloc_tmpbuf)
815 tmpbuf = alloca_account (tmpbuflen, alloca_used);
816 else
818 tmpbuf = malloc (tmpbuflen);
819 if (tmpbuf == NULL)
821 result = -EAI_MEMORY;
822 goto free_and_return;
826 while (!no_more)
828 no_data = 0;
829 nss_gethostbyname4_r fct4
830 = __nss_lookup_function (nip, "gethostbyname4_r");
831 if (fct4 != NULL)
833 int herrno;
835 while (1)
837 rc = 0;
838 status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
839 tmpbuflen, &rc, &herrno,
840 NULL));
841 if (status == NSS_STATUS_SUCCESS)
842 break;
843 if (status != NSS_STATUS_TRYAGAIN
844 || rc != ERANGE || herrno != NETDB_INTERNAL)
846 if (status == NSS_STATUS_TRYAGAIN
847 && herrno == TRY_AGAIN)
848 no_data = EAI_AGAIN;
849 else
850 no_data = herrno == NO_DATA;
851 break;
854 if (!malloc_tmpbuf
855 && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
856 tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
857 2 * tmpbuflen,
858 alloca_used);
859 else
861 char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
862 2 * tmpbuflen);
863 if (newp == NULL)
865 result = -EAI_MEMORY;
866 goto free_and_return;
868 tmpbuf = newp;
869 malloc_tmpbuf = true;
870 tmpbuflen = 2 * tmpbuflen;
874 if (status == NSS_STATUS_SUCCESS)
876 assert (!no_data);
877 no_data = 1;
879 if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
880 canon = (*pat)->name;
882 while (*pat != NULL)
884 if ((*pat)->family == AF_INET
885 && req->ai_family == AF_INET6
886 && (req->ai_flags & AI_V4MAPPED) != 0)
888 uint32_t *pataddr = (*pat)->addr;
889 (*pat)->family = AF_INET6;
890 pataddr[3] = pataddr[0];
891 pataddr[2] = htonl (0xffff);
892 pataddr[1] = 0;
893 pataddr[0] = 0;
894 pat = &((*pat)->next);
895 no_data = 0;
897 else if (req->ai_family == AF_UNSPEC
898 || (*pat)->family == req->ai_family)
900 pat = &((*pat)->next);
902 no_data = 0;
903 if (req->ai_family == AF_INET6)
904 got_ipv6 = true;
906 else
907 *pat = ((*pat)->next);
911 no_inet6_data = no_data;
913 else
915 nss_gethostbyname3_r fct = NULL;
916 if (req->ai_flags & AI_CANONNAME)
917 /* No need to use this function if we do not look for
918 the canonical name. The function does not exist in
919 all NSS modules and therefore the lookup would
920 often fail. */
921 fct = __nss_lookup_function (nip, "gethostbyname3_r");
922 if (fct == NULL)
923 /* We are cheating here. The gethostbyname2_r
924 function does not have the same interface as
925 gethostbyname3_r but the extra arguments the
926 latter takes are added at the end. So the
927 gethostbyname2_r code will just ignore them. */
928 fct = __nss_lookup_function (nip, "gethostbyname2_r");
930 if (fct != NULL)
932 if (req->ai_family == AF_INET6
933 || req->ai_family == AF_UNSPEC)
935 gethosts (AF_INET6, struct in6_addr);
936 no_inet6_data = no_data;
937 inet6_status = status;
939 if (req->ai_family == AF_INET
940 || req->ai_family == AF_UNSPEC
941 || (req->ai_family == AF_INET6
942 && (req->ai_flags & AI_V4MAPPED)
943 /* Avoid generating the mapped addresses if we
944 know we are not going to need them. */
945 && ((req->ai_flags & AI_ALL) || !got_ipv6)))
947 gethosts (AF_INET, struct in_addr);
949 if (req->ai_family == AF_INET)
951 no_inet6_data = no_data;
952 inet6_status = status;
956 /* If we found one address for AF_INET or AF_INET6,
957 don't continue the search. */
958 if (inet6_status == NSS_STATUS_SUCCESS
959 || status == NSS_STATUS_SUCCESS)
961 if ((req->ai_flags & AI_CANONNAME) != 0
962 && canon == NULL)
964 /* If we need the canonical name, get it
965 from the same service as the result. */
966 nss_getcanonname_r cfct;
967 int herrno;
969 cfct = __nss_lookup_function (nip,
970 "getcanonname_r");
971 if (cfct != NULL)
973 const size_t max_fqdn_len = 256;
974 if ((req->ai_flags & AI_CANONIDN) != 0
975 && __libc_use_alloca (alloca_used
976 + max_fqdn_len))
977 canonbuf = alloca_account (max_fqdn_len,
978 alloca_used);
979 else
981 canonbuf = malloc (max_fqdn_len);
982 if (canonbuf == NULL)
984 result = -EAI_MEMORY;
985 goto free_and_return;
987 malloc_canonbuf = true;
989 char *s;
991 if (DL_CALL_FCT (cfct, (at->name ?: name,
992 canonbuf,
993 max_fqdn_len,
994 &s, &rc, &herrno))
995 == NSS_STATUS_SUCCESS)
996 canon = s;
997 else
999 /* Set to name now to avoid using
1000 gethostbyaddr. */
1001 if (malloc_canonbuf)
1003 free (canonbuf);
1004 malloc_canonbuf = false;
1006 canon = name;
1010 status = NSS_STATUS_SUCCESS;
1012 else
1014 /* We can have different states for AF_INET and
1015 AF_INET6. Try to find a useful one for both. */
1016 if (inet6_status == NSS_STATUS_TRYAGAIN)
1017 status = NSS_STATUS_TRYAGAIN;
1018 else if (status == NSS_STATUS_UNAVAIL
1019 && inet6_status != NSS_STATUS_UNAVAIL)
1020 status = inet6_status;
1023 else
1024 status = NSS_STATUS_UNAVAIL;
1027 if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
1028 break;
1030 if (nip->next == NULL)
1031 no_more = -1;
1032 else
1033 nip = nip->next;
1036 _res.options |= old_res_options & RES_USE_INET6;
1038 if (no_data != 0 && no_inet6_data != 0)
1040 /* If both requests timed out report this. */
1041 if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
1042 result = -EAI_AGAIN;
1043 else
1044 /* We made requests but they turned out no data. The name
1045 is known, though. */
1046 result = GAIH_OKIFUNSPEC | -EAI_NODATA;
1048 goto free_and_return;
1052 process_list:
1053 if (at->family == AF_UNSPEC)
1055 result = GAIH_OKIFUNSPEC | -EAI_NONAME;
1056 goto free_and_return;
1059 else
1061 struct gaih_addrtuple *atr;
1062 atr = at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
1063 memset (at, '\0', sizeof (struct gaih_addrtuple));
1065 if (req->ai_family == AF_UNSPEC)
1067 at->next = __alloca (sizeof (struct gaih_addrtuple));
1068 memset (at->next, '\0', sizeof (struct gaih_addrtuple));
1071 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
1073 at->family = AF_INET6;
1074 if ((req->ai_flags & AI_PASSIVE) == 0)
1075 memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
1076 atr = at->next;
1079 if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
1081 atr->family = AF_INET;
1082 if ((req->ai_flags & AI_PASSIVE) == 0)
1083 atr->addr[0] = htonl (INADDR_LOOPBACK);
1088 struct gaih_servtuple *st2;
1089 struct gaih_addrtuple *at2 = at;
1090 size_t socklen;
1091 sa_family_t family;
1094 buffer is the size of an unformatted IPv6 address in printable format.
1096 while (at2 != NULL)
1098 /* Only the first entry gets the canonical name. */
1099 if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
1101 char *tmpbuf2 = NULL;
1102 bool malloc_tmpbuf2 = false;
1104 if (canon == NULL)
1106 struct hostent *h = NULL;
1107 int herrno;
1108 struct hostent th;
1109 size_t tmpbuf2len = 512;
1113 if (__libc_use_alloca (alloca_used + 2 * tmpbuf2len))
1114 tmpbuf2 = extend_alloca_account (tmpbuf2, tmpbuf2len,
1115 tmpbuf2len * 2,
1116 alloca_used);
1117 else
1119 char *newp = realloc (malloc_tmpbuf2 ? tmpbuf2 : NULL,
1120 2 * tmpbuf2len);
1121 if (newp == NULL)
1123 if (malloc_tmpbuf2)
1124 free (tmpbuf2);
1125 result = -EAI_MEMORY;
1126 goto free_and_return;
1129 tmpbuf2 = newp;
1130 tmpbuf2len = 2 * tmpbuf2len;
1131 malloc_tmpbuf2 = true;
1134 rc = __gethostbyaddr_r (at2->addr,
1135 ((at2->family == AF_INET6)
1136 ? sizeof (struct in6_addr)
1137 : sizeof (struct in_addr)),
1138 at2->family, &th, tmpbuf2,
1139 tmpbuf2len, &h, &herrno);
1141 while (rc == ERANGE && herrno == NETDB_INTERNAL);
1143 if (rc != 0 && herrno == NETDB_INTERNAL)
1145 if (malloc_tmpbuf2)
1146 free (tmpbuf2);
1148 __set_h_errno (herrno);
1149 result = -EAI_SYSTEM;
1150 goto free_and_return;
1153 if (h != NULL)
1154 canon = h->h_name;
1155 else
1157 assert (orig_name != NULL);
1158 /* If the canonical name cannot be determined, use
1159 the passed in string. */
1160 canon = orig_name;
1164 #ifdef HAVE_LIBIDN
1165 if (req->ai_flags & AI_CANONIDN)
1167 int idn_flags = 0;
1168 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1169 idn_flags |= IDNA_ALLOW_UNASSIGNED;
1170 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1171 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1173 char *out;
1174 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1175 if (rc != IDNA_SUCCESS)
1177 if (malloc_tmpbuf2)
1178 free (tmpbuf2);
1180 if (rc == IDNA_MALLOC_ERROR)
1181 result = -EAI_MEMORY;
1182 else if (rc == IDNA_DLOPEN_ERROR)
1183 result = -EAI_SYSTEM;
1184 else
1185 result = -EAI_IDN_ENCODE;
1186 goto free_and_return;
1188 /* In case the output string is the same as the input
1189 string no new string has been allocated and we
1190 make a copy. */
1191 if (out == canon)
1192 goto make_copy;
1193 canon = out;
1195 else
1196 #endif
1198 #ifdef HAVE_LIBIDN
1199 make_copy:
1200 #endif
1201 if (malloc_canonbuf)
1202 /* We already allocated the string using malloc. */
1203 malloc_canonbuf = false;
1204 else
1206 canon = strdup (canon);
1207 if (canon == NULL)
1209 if (malloc_tmpbuf2)
1210 free (tmpbuf2);
1212 result = -EAI_MEMORY;
1213 goto free_and_return;
1218 if (malloc_tmpbuf2)
1219 free (tmpbuf2);
1222 family = at2->family;
1223 if (family == AF_INET6)
1225 socklen = sizeof (struct sockaddr_in6);
1227 /* If we looked up IPv4 mapped address discard them here if
1228 the caller isn't interested in all address and we have
1229 found at least one IPv6 address. */
1230 if (got_ipv6
1231 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1232 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1233 goto ignore;
1235 else
1236 socklen = sizeof (struct sockaddr_in);
1238 for (st2 = st; st2 != NULL; st2 = st2->next)
1240 struct addrinfo *ai;
1241 ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1242 if (ai == NULL)
1244 free ((char *) canon);
1245 result = -EAI_MEMORY;
1246 goto free_and_return;
1249 ai->ai_flags = req->ai_flags;
1250 ai->ai_family = family;
1251 ai->ai_socktype = st2->socktype;
1252 ai->ai_protocol = st2->protocol;
1253 ai->ai_addrlen = socklen;
1254 ai->ai_addr = (void *) (ai + 1);
1256 /* We only add the canonical name once. */
1257 ai->ai_canonname = (char *) canon;
1258 canon = NULL;
1260 #ifdef _HAVE_SA_LEN
1261 ai->ai_addr->sa_len = socklen;
1262 #endif /* _HAVE_SA_LEN */
1263 ai->ai_addr->sa_family = family;
1265 /* In case of an allocation error the list must be NULL
1266 terminated. */
1267 ai->ai_next = NULL;
1269 if (family == AF_INET6)
1271 struct sockaddr_in6 *sin6p =
1272 (struct sockaddr_in6 *) ai->ai_addr;
1274 sin6p->sin6_port = st2->port;
1275 sin6p->sin6_flowinfo = 0;
1276 memcpy (&sin6p->sin6_addr,
1277 at2->addr, sizeof (struct in6_addr));
1278 sin6p->sin6_scope_id = at2->scopeid;
1280 else
1282 struct sockaddr_in *sinp =
1283 (struct sockaddr_in *) ai->ai_addr;
1284 sinp->sin_port = st2->port;
1285 memcpy (&sinp->sin_addr,
1286 at2->addr, sizeof (struct in_addr));
1287 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1290 pai = &(ai->ai_next);
1293 ++*naddrs;
1295 ignore:
1296 at2 = at2->next;
1300 free_and_return:
1301 if (malloc_name)
1302 free ((char *) name);
1303 if (malloc_addrmem)
1304 free (addrmem);
1305 if (malloc_canonbuf)
1306 free (canonbuf);
1307 if (malloc_tmpbuf)
1308 free (tmpbuf);
1310 return result;
1314 struct sort_result
1316 struct addrinfo *dest_addr;
1317 /* Using sockaddr_storage is for now overkill. We only support IPv4
1318 and IPv6 so far. If this changes at some point we can adjust the
1319 type here. */
1320 struct sockaddr_in6 source_addr;
1321 uint8_t source_addr_len;
1322 bool got_source_addr;
1323 uint8_t source_addr_flags;
1324 uint8_t prefixlen;
1325 uint32_t index;
1326 int32_t native;
1329 struct sort_result_combo
1331 struct sort_result *results;
1332 int nresults;
1336 #if __BYTE_ORDER == __BIG_ENDIAN
1337 # define htonl_c(n) n
1338 #else
1339 # define htonl_c(n) __bswap_constant_32 (n)
1340 #endif
1342 static const struct scopeentry
1344 union
1346 char addr[4];
1347 uint32_t addr32;
1349 uint32_t netmask;
1350 int32_t scope;
1351 } default_scopes[] =
1353 /* Link-local addresses: scope 2. */
1354 { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1355 { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1356 /* Site-local addresses: scope 5. */
1357 { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1358 { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1359 { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1360 /* Default: scope 14. */
1361 { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1364 /* The label table. */
1365 static const struct scopeentry *scopes;
1368 static int
1369 get_scope (const struct sockaddr_in6 *in6)
1371 int scope;
1372 if (in6->sin6_family == PF_INET6)
1374 if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1376 if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1377 /* RFC 4291 2.5.3 says that the loopback address is to be
1378 treated like a link-local address. */
1379 || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1380 scope = 2;
1381 else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1382 scope = 5;
1383 else
1384 /* XXX Is this the correct default behavior? */
1385 scope = 14;
1387 else
1388 scope = in6->sin6_addr.s6_addr[1] & 0xf;
1390 else if (in6->sin6_family == PF_INET)
1392 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1394 size_t cnt = 0;
1395 while (1)
1397 if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1398 == scopes[cnt].addr32)
1399 return scopes[cnt].scope;
1401 ++cnt;
1403 /* NOTREACHED */
1405 else
1406 /* XXX What is a good default? */
1407 scope = 15;
1409 return scope;
1413 struct prefixentry
1415 struct in6_addr prefix;
1416 unsigned int bits;
1417 int val;
1421 /* The label table. */
1422 static const struct prefixentry *labels;
1424 /* Default labels. */
1425 static const struct prefixentry default_labels[] =
1427 /* See RFC 3484 for the details. */
1428 { { .__in6_u
1429 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1431 }, 128, 0 },
1432 { { .__in6_u
1433 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1435 }, 16, 2 },
1436 { { .__in6_u
1437 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1439 }, 96, 3 },
1440 { { .__in6_u
1441 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1442 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1443 }, 96, 4 },
1444 /* The next two entries differ from RFC 3484. We need to treat
1445 IPv6 site-local addresses special because they are never NATed,
1446 unlike site-locale IPv4 addresses. If this would not happen, on
1447 machines which have only IPv4 and IPv6 site-local addresses, the
1448 sorting would prefer the IPv6 site-local addresses, causing
1449 unnecessary delays when trying to connect to a global IPv6 address
1450 through a site-local IPv6 address. */
1451 { { .__in6_u
1452 = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1454 }, 10, 5 },
1455 { { .__in6_u
1456 = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1458 }, 7, 6 },
1459 /* Additional rule for Teredo tunnels. */
1460 { { .__in6_u
1461 = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1462 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1463 }, 32, 7 },
1464 { { .__in6_u
1465 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1467 }, 0, 1 }
1471 /* The precedence table. */
1472 static const struct prefixentry *precedence;
1474 /* The default precedences. */
1475 static const struct prefixentry default_precedence[] =
1477 /* See RFC 3484 for the details. */
1478 { { .__in6_u
1479 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1481 }, 128, 50 },
1482 { { .__in6_u
1483 = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1485 }, 16, 30 },
1486 { { .__in6_u
1487 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1489 }, 96, 20 },
1490 { { .__in6_u
1491 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1492 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1493 }, 96, 10 },
1494 { { .__in6_u
1495 = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1497 }, 0, 40 }
1501 static int
1502 match_prefix (const struct sockaddr_in6 *in6,
1503 const struct prefixentry *list, int default_val)
1505 int idx;
1506 struct sockaddr_in6 in6_mem;
1508 if (in6->sin6_family == PF_INET)
1510 const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1512 /* Construct a V4-to-6 mapped address. */
1513 in6_mem.sin6_family = PF_INET6;
1514 in6_mem.sin6_port = in->sin_port;
1515 in6_mem.sin6_flowinfo = 0;
1516 memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1517 in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1518 in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1519 in6_mem.sin6_scope_id = 0;
1521 in6 = &in6_mem;
1523 else if (in6->sin6_family != PF_INET6)
1524 return default_val;
1526 for (idx = 0; ; ++idx)
1528 unsigned int bits = list[idx].bits;
1529 const uint8_t *mask = list[idx].prefix.s6_addr;
1530 const uint8_t *val = in6->sin6_addr.s6_addr;
1532 while (bits >= 8)
1534 if (*mask != *val)
1535 break;
1537 ++mask;
1538 ++val;
1539 bits -= 8;
1542 if (bits < 8)
1544 if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1545 /* Match! */
1546 break;
1550 return list[idx].val;
1554 static int
1555 get_label (const struct sockaddr_in6 *in6)
1557 /* XXX What is a good default value? */
1558 return match_prefix (in6, labels, INT_MAX);
1562 static int
1563 get_precedence (const struct sockaddr_in6 *in6)
1565 /* XXX What is a good default value? */
1566 return match_prefix (in6, precedence, 0);
1570 /* Find last bit set in a word. */
1571 static int
1572 fls (uint32_t a)
1574 uint32_t mask;
1575 int n;
1576 for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1577 if ((a & mask) != 0)
1578 break;
1579 return n;
1583 static int
1584 rfc3484_sort (const void *p1, const void *p2, void *arg)
1586 const size_t idx1 = *(const size_t *) p1;
1587 const size_t idx2 = *(const size_t *) p2;
1588 struct sort_result_combo *src = (struct sort_result_combo *) arg;
1589 struct sort_result *a1 = &src->results[idx1];
1590 struct sort_result *a2 = &src->results[idx2];
1592 /* Rule 1: Avoid unusable destinations.
1593 We have the got_source_addr flag set if the destination is reachable. */
1594 if (a1->got_source_addr && ! a2->got_source_addr)
1595 return -1;
1596 if (! a1->got_source_addr && a2->got_source_addr)
1597 return 1;
1600 /* Rule 2: Prefer matching scope. Only interesting if both
1601 destination addresses are IPv6. */
1602 int a1_dst_scope
1603 = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1605 int a2_dst_scope
1606 = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1608 if (a1->got_source_addr)
1610 int a1_src_scope = get_scope (&a1->source_addr);
1611 int a2_src_scope = get_scope (&a2->source_addr);
1613 if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1614 return -1;
1615 if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1616 return 1;
1620 /* Rule 3: Avoid deprecated addresses. */
1621 if (a1->got_source_addr)
1623 if (!(a1->source_addr_flags & in6ai_deprecated)
1624 && (a2->source_addr_flags & in6ai_deprecated))
1625 return -1;
1626 if ((a1->source_addr_flags & in6ai_deprecated)
1627 && !(a2->source_addr_flags & in6ai_deprecated))
1628 return 1;
1631 /* Rule 4: Prefer home addresses. */
1632 if (a1->got_source_addr)
1634 if (!(a1->source_addr_flags & in6ai_homeaddress)
1635 && (a2->source_addr_flags & in6ai_homeaddress))
1636 return 1;
1637 if ((a1->source_addr_flags & in6ai_homeaddress)
1638 && !(a2->source_addr_flags & in6ai_homeaddress))
1639 return -1;
1642 /* Rule 5: Prefer matching label. */
1643 if (a1->got_source_addr)
1645 int a1_dst_label
1646 = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1647 int a1_src_label = get_label (&a1->source_addr);
1649 int a2_dst_label
1650 = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1651 int a2_src_label = get_label (&a2->source_addr);
1653 if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1654 return -1;
1655 if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1656 return 1;
1660 /* Rule 6: Prefer higher precedence. */
1661 int a1_prec
1662 = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1663 int a2_prec
1664 = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1666 if (a1_prec > a2_prec)
1667 return -1;
1668 if (a1_prec < a2_prec)
1669 return 1;
1672 /* Rule 7: Prefer native transport. */
1673 if (a1->got_source_addr)
1675 /* The same interface index means the same interface which means
1676 there is no difference in transport. This should catch many
1677 (most?) cases. */
1678 if (a1->index != a2->index)
1680 int a1_native = a1->native;
1681 int a2_native = a2->native;
1683 if (a1_native == -1 || a2_native == -1)
1685 uint32_t a1_index;
1686 if (a1_native == -1)
1688 /* If we do not have the information use 'native' as
1689 the default. */
1690 a1_native = 0;
1691 a1_index = a1->index;
1693 else
1694 a1_index = 0xffffffffu;
1696 uint32_t a2_index;
1697 if (a2_native == -1)
1699 /* If we do not have the information use 'native' as
1700 the default. */
1701 a2_native = 0;
1702 a2_index = a2->index;
1704 else
1705 a2_index = 0xffffffffu;
1707 __check_native (a1_index, &a1_native, a2_index, &a2_native);
1709 /* Fill in the results in all the records. */
1710 for (int i = 0; i < src->nresults; ++i)
1711 if (src->results[i].index == a1_index)
1713 assert (src->results[i].native == -1
1714 || src->results[i].native == a1_native);
1715 src->results[i].native = a1_native;
1717 else if (src->results[i].index == a2_index)
1719 assert (src->results[i].native == -1
1720 || src->results[i].native == a2_native);
1721 src->results[i].native = a2_native;
1725 if (a1_native && !a2_native)
1726 return -1;
1727 if (!a1_native && a2_native)
1728 return 1;
1733 /* Rule 8: Prefer smaller scope. */
1734 if (a1_dst_scope < a2_dst_scope)
1735 return -1;
1736 if (a1_dst_scope > a2_dst_scope)
1737 return 1;
1740 /* Rule 9: Use longest matching prefix. */
1741 if (a1->got_source_addr
1742 && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1744 int bit1 = 0;
1745 int bit2 = 0;
1747 if (a1->dest_addr->ai_family == PF_INET)
1749 assert (a1->source_addr.sin6_family == PF_INET);
1750 assert (a2->source_addr.sin6_family == PF_INET);
1752 /* Outside of subnets, as defined by the network masks,
1753 common address prefixes for IPv4 addresses make no sense.
1754 So, define a non-zero value only if source and
1755 destination address are on the same subnet. */
1756 struct sockaddr_in *in1_dst
1757 = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1758 in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1759 struct sockaddr_in *in1_src
1760 = (struct sockaddr_in *) &a1->source_addr;
1761 in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1762 in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1764 if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1765 bit1 = fls (in1_dst_addr ^ in1_src_addr);
1767 struct sockaddr_in *in2_dst
1768 = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1769 in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1770 struct sockaddr_in *in2_src
1771 = (struct sockaddr_in *) &a2->source_addr;
1772 in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1773 in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1775 if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1776 bit2 = fls (in2_dst_addr ^ in2_src_addr);
1778 else if (a1->dest_addr->ai_family == PF_INET6)
1780 assert (a1->source_addr.sin6_family == PF_INET6);
1781 assert (a2->source_addr.sin6_family == PF_INET6);
1783 struct sockaddr_in6 *in1_dst;
1784 struct sockaddr_in6 *in1_src;
1785 struct sockaddr_in6 *in2_dst;
1786 struct sockaddr_in6 *in2_src;
1788 in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1789 in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1790 in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1791 in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1793 int i;
1794 for (i = 0; i < 4; ++i)
1795 if (in1_dst->sin6_addr.s6_addr32[i]
1796 != in1_src->sin6_addr.s6_addr32[i]
1797 || (in2_dst->sin6_addr.s6_addr32[i]
1798 != in2_src->sin6_addr.s6_addr32[i]))
1799 break;
1801 if (i < 4)
1803 bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1804 ^ in1_src->sin6_addr.s6_addr32[i]));
1805 bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1806 ^ in2_src->sin6_addr.s6_addr32[i]));
1810 if (bit1 > bit2)
1811 return -1;
1812 if (bit1 < bit2)
1813 return 1;
1817 /* Rule 10: Otherwise, leave the order unchanged. To ensure this
1818 compare with the value indicating the order in which the entries
1819 have been received from the services. NB: no two entries can have
1820 the same order so the test will never return zero. */
1821 return idx1 < idx2 ? -1 : 1;
1825 static int
1826 in6aicmp (const void *p1, const void *p2)
1828 struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1829 struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1831 return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1835 /* Name of the config file for RFC 3484 sorting (for now). */
1836 #define GAICONF_FNAME "/etc/gai.conf"
1839 /* Non-zero if we are supposed to reload the config file automatically
1840 whenever it changed. */
1841 static int gaiconf_reload_flag;
1843 /* Non-zero if gaiconf_reload_flag was ever set to true. */
1844 static int gaiconf_reload_flag_ever_set;
1846 /* Last modification time. */
1847 static struct timespec gaiconf_mtime;
1850 libc_freeres_fn(fini)
1852 if (labels != default_labels)
1854 const struct prefixentry *old = labels;
1855 labels = default_labels;
1856 free ((void *) old);
1859 if (precedence != default_precedence)
1861 const struct prefixentry *old = precedence;
1862 precedence = default_precedence;
1863 free ((void *) old);
1866 if (scopes != default_scopes)
1868 const struct scopeentry *old = scopes;
1869 scopes = default_scopes;
1870 free ((void *) old);
1875 struct prefixlist
1877 struct prefixentry entry;
1878 struct prefixlist *next;
1882 struct scopelist
1884 struct scopeentry entry;
1885 struct scopelist *next;
1889 static void
1890 free_prefixlist (struct prefixlist *list)
1892 while (list != NULL)
1894 struct prefixlist *oldp = list;
1895 list = list->next;
1896 free (oldp);
1901 static void
1902 free_scopelist (struct scopelist *list)
1904 while (list != NULL)
1906 struct scopelist *oldp = list;
1907 list = list->next;
1908 free (oldp);
1913 static int
1914 prefixcmp (const void *p1, const void *p2)
1916 const struct prefixentry *e1 = (const struct prefixentry *) p1;
1917 const struct prefixentry *e2 = (const struct prefixentry *) p2;
1919 if (e1->bits < e2->bits)
1920 return 1;
1921 if (e1->bits == e2->bits)
1922 return 0;
1923 return -1;
1927 static int
1928 scopecmp (const void *p1, const void *p2)
1930 const struct scopeentry *e1 = (const struct scopeentry *) p1;
1931 const struct scopeentry *e2 = (const struct scopeentry *) p2;
1933 if (e1->netmask > e2->netmask)
1934 return -1;
1935 if (e1->netmask == e2->netmask)
1936 return 0;
1937 return 1;
1941 static void
1942 gaiconf_init (void)
1944 struct prefixlist *labellist = NULL;
1945 size_t nlabellist = 0;
1946 bool labellist_nullbits = false;
1947 struct prefixlist *precedencelist = NULL;
1948 size_t nprecedencelist = 0;
1949 bool precedencelist_nullbits = false;
1950 struct scopelist *scopelist = NULL;
1951 size_t nscopelist = 0;
1952 bool scopelist_nullbits = false;
1954 FILE *fp = fopen (GAICONF_FNAME, "rc");
1955 if (fp != NULL)
1957 struct stat64 st;
1958 if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1960 fclose (fp);
1961 goto no_file;
1964 char *line = NULL;
1965 size_t linelen = 0;
1967 __fsetlocking (fp, FSETLOCKING_BYCALLER);
1969 while (!feof_unlocked (fp))
1971 ssize_t n = __getline (&line, &linelen, fp);
1972 if (n <= 0)
1973 break;
1975 /* Handle comments. No escaping possible so this is easy. */
1976 char *cp = strchr (line, '#');
1977 if (cp != NULL)
1978 *cp = '\0';
1980 cp = line;
1981 while (isspace (*cp))
1982 ++cp;
1984 char *cmd = cp;
1985 while (*cp != '\0' && !isspace (*cp))
1986 ++cp;
1987 size_t cmdlen = cp - cmd;
1989 if (*cp != '\0')
1990 *cp++ = '\0';
1991 while (isspace (*cp))
1992 ++cp;
1994 char *val1 = cp;
1995 while (*cp != '\0' && !isspace (*cp))
1996 ++cp;
1997 size_t val1len = cp - cmd;
1999 /* We always need at least two values. */
2000 if (val1len == 0)
2001 continue;
2003 if (*cp != '\0')
2004 *cp++ = '\0';
2005 while (isspace (*cp))
2006 ++cp;
2008 char *val2 = cp;
2009 while (*cp != '\0' && !isspace (*cp))
2010 ++cp;
2012 /* Ignore the rest of the line. */
2013 *cp = '\0';
2015 struct prefixlist **listp;
2016 size_t *lenp;
2017 bool *nullbitsp;
2018 switch (cmdlen)
2020 case 5:
2021 if (strcmp (cmd, "label") == 0)
2023 struct in6_addr prefix;
2024 unsigned long int bits;
2025 unsigned long int val;
2026 char *endp;
2028 listp = &labellist;
2029 lenp = &nlabellist;
2030 nullbitsp = &labellist_nullbits;
2032 new_elem:
2033 bits = 128;
2034 __set_errno (0);
2035 cp = strchr (val1, '/');
2036 if (cp != NULL)
2037 *cp++ = '\0';
2038 if (inet_pton (AF_INET6, val1, &prefix)
2039 && (cp == NULL
2040 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2041 || errno != ERANGE)
2042 && *endp == '\0'
2043 && bits <= 128
2044 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2045 || errno != ERANGE)
2046 && *endp == '\0'
2047 && val <= INT_MAX)
2049 struct prefixlist *newp = malloc (sizeof (*newp));
2050 if (newp == NULL)
2052 free (line);
2053 fclose (fp);
2054 goto no_file;
2057 memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
2058 newp->entry.bits = bits;
2059 newp->entry.val = val;
2060 newp->next = *listp;
2061 *listp = newp;
2062 ++*lenp;
2063 *nullbitsp |= bits == 0;
2066 break;
2068 case 6:
2069 if (strcmp (cmd, "reload") == 0)
2071 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
2072 if (gaiconf_reload_flag)
2073 gaiconf_reload_flag_ever_set = 1;
2075 break;
2077 case 7:
2078 if (strcmp (cmd, "scopev4") == 0)
2080 struct in6_addr prefix;
2081 unsigned long int bits;
2082 unsigned long int val;
2083 char *endp;
2085 bits = 32;
2086 __set_errno (0);
2087 cp = strchr (val1, '/');
2088 if (cp != NULL)
2089 *cp++ = '\0';
2090 if (inet_pton (AF_INET6, val1, &prefix))
2092 bits = 128;
2093 if (IN6_IS_ADDR_V4MAPPED (&prefix)
2094 && (cp == NULL
2095 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2096 || errno != ERANGE)
2097 && *endp == '\0'
2098 && bits >= 96
2099 && bits <= 128
2100 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2101 || errno != ERANGE)
2102 && *endp == '\0'
2103 && val <= INT_MAX)
2105 struct scopelist *newp;
2106 new_scope:
2107 newp = malloc (sizeof (*newp));
2108 if (newp == NULL)
2110 free (line);
2111 fclose (fp);
2112 goto no_file;
2115 newp->entry.netmask = htonl (bits != 96
2116 ? (0xffffffff
2117 << (128 - bits))
2118 : 0);
2119 newp->entry.addr32 = (prefix.s6_addr32[3]
2120 & newp->entry.netmask);
2121 newp->entry.scope = val;
2122 newp->next = scopelist;
2123 scopelist = newp;
2124 ++nscopelist;
2125 scopelist_nullbits |= bits == 96;
2128 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
2129 && (cp == NULL
2130 || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
2131 || errno != ERANGE)
2132 && *endp == '\0'
2133 && bits <= 32
2134 && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
2135 || errno != ERANGE)
2136 && *endp == '\0'
2137 && val <= INT_MAX)
2139 bits += 96;
2140 goto new_scope;
2143 break;
2145 case 10:
2146 if (strcmp (cmd, "precedence") == 0)
2148 listp = &precedencelist;
2149 lenp = &nprecedencelist;
2150 nullbitsp = &precedencelist_nullbits;
2151 goto new_elem;
2153 break;
2157 free (line);
2159 fclose (fp);
2161 /* Create the array for the labels. */
2162 struct prefixentry *new_labels;
2163 if (nlabellist > 0)
2165 if (!labellist_nullbits)
2166 ++nlabellist;
2167 new_labels = malloc (nlabellist * sizeof (*new_labels));
2168 if (new_labels == NULL)
2169 goto no_file;
2171 int i = nlabellist;
2172 if (!labellist_nullbits)
2174 --i;
2175 memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
2176 new_labels[i].bits = 0;
2177 new_labels[i].val = 1;
2180 struct prefixlist *l = labellist;
2181 while (i-- > 0)
2183 new_labels[i] = l->entry;
2184 l = l->next;
2186 free_prefixlist (labellist);
2188 /* Sort the entries so that the most specific ones are at
2189 the beginning. */
2190 qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
2192 else
2193 new_labels = (struct prefixentry *) default_labels;
2195 struct prefixentry *new_precedence;
2196 if (nprecedencelist > 0)
2198 if (!precedencelist_nullbits)
2199 ++nprecedencelist;
2200 new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
2201 if (new_precedence == NULL)
2203 if (new_labels != default_labels)
2204 free (new_labels);
2205 goto no_file;
2208 int i = nprecedencelist;
2209 if (!precedencelist_nullbits)
2211 --i;
2212 memset (&new_precedence[i].prefix, '\0',
2213 sizeof (struct in6_addr));
2214 new_precedence[i].bits = 0;
2215 new_precedence[i].val = 40;
2218 struct prefixlist *l = precedencelist;
2219 while (i-- > 0)
2221 new_precedence[i] = l->entry;
2222 l = l->next;
2224 free_prefixlist (precedencelist);
2226 /* Sort the entries so that the most specific ones are at
2227 the beginning. */
2228 qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
2229 prefixcmp);
2231 else
2232 new_precedence = (struct prefixentry *) default_precedence;
2234 struct scopeentry *new_scopes;
2235 if (nscopelist > 0)
2237 if (!scopelist_nullbits)
2238 ++nscopelist;
2239 new_scopes = malloc (nscopelist * sizeof (*new_scopes));
2240 if (new_scopes == NULL)
2242 if (new_labels != default_labels)
2243 free (new_labels);
2244 if (new_precedence != default_precedence)
2245 free (new_precedence);
2246 goto no_file;
2249 int i = nscopelist;
2250 if (!scopelist_nullbits)
2252 --i;
2253 new_scopes[i].addr32 = 0;
2254 new_scopes[i].netmask = 0;
2255 new_scopes[i].scope = 14;
2258 struct scopelist *l = scopelist;
2259 while (i-- > 0)
2261 new_scopes[i] = l->entry;
2262 l = l->next;
2264 free_scopelist (scopelist);
2266 /* Sort the entries so that the most specific ones are at
2267 the beginning. */
2268 qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2269 scopecmp);
2271 else
2272 new_scopes = (struct scopeentry *) default_scopes;
2274 /* Now we are ready to replace the values. */
2275 const struct prefixentry *old = labels;
2276 labels = new_labels;
2277 if (old != default_labels)
2278 free ((void *) old);
2280 old = precedence;
2281 precedence = new_precedence;
2282 if (old != default_precedence)
2283 free ((void *) old);
2285 const struct scopeentry *oldscope = scopes;
2286 scopes = new_scopes;
2287 if (oldscope != default_scopes)
2288 free ((void *) oldscope);
2290 gaiconf_mtime = st.st_mtim;
2292 else
2294 no_file:
2295 free_prefixlist (labellist);
2296 free_prefixlist (precedencelist);
2297 free_scopelist (scopelist);
2299 /* If we previously read the file but it is gone now, free the
2300 old data and use the builtin one. Leave the reload flag
2301 alone. */
2302 fini ();
2307 static void
2308 gaiconf_reload (void)
2310 struct stat64 st;
2311 if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2312 || memcmp (&st.st_mtim, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
2313 gaiconf_init ();
2318 getaddrinfo (const char *name, const char *service,
2319 const struct addrinfo *hints, struct addrinfo **pai)
2321 int i = 0, last_i = 0;
2322 int nresults = 0;
2323 struct addrinfo *p = NULL;
2324 struct gaih_service gaih_service, *pservice;
2325 struct addrinfo local_hints;
2327 if (name != NULL && name[0] == '*' && name[1] == 0)
2328 name = NULL;
2330 if (service != NULL && service[0] == '*' && service[1] == 0)
2331 service = NULL;
2333 if (name == NULL && service == NULL)
2334 return EAI_NONAME;
2336 if (hints == NULL)
2337 hints = &default_hints;
2339 if (hints->ai_flags
2340 & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2341 #ifdef HAVE_LIBIDN
2342 |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2343 |AI_IDN_USE_STD3_ASCII_RULES
2344 #endif
2345 |AI_NUMERICSERV|AI_ALL))
2346 return EAI_BADFLAGS;
2348 if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2349 return EAI_BADFLAGS;
2351 struct in6addrinfo *in6ai = NULL;
2352 size_t in6ailen = 0;
2353 bool seen_ipv4 = false;
2354 bool seen_ipv6 = false;
2355 /* We might need information about what interfaces are available.
2356 Also determine whether we have IPv4 or IPv6 interfaces or both. We
2357 cannot cache the results since new interfaces could be added at
2358 any time. */
2359 __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2361 if (hints->ai_flags & AI_ADDRCONFIG)
2363 /* Now make a decision on what we return, if anything. */
2364 if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2366 /* If we haven't seen both IPv4 and IPv6 interfaces we can
2367 narrow down the search. */
2368 if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2370 local_hints = *hints;
2371 local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2372 hints = &local_hints;
2375 else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2376 || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2378 /* We cannot possibly return a valid answer. */
2379 free (in6ai);
2380 return EAI_NONAME;
2384 if (service && service[0])
2386 char *c;
2387 gaih_service.name = service;
2388 gaih_service.num = strtoul (gaih_service.name, &c, 10);
2389 if (*c != '\0')
2391 if (hints->ai_flags & AI_NUMERICSERV)
2393 free (in6ai);
2394 return EAI_NONAME;
2397 gaih_service.num = -1;
2400 pservice = &gaih_service;
2402 else
2403 pservice = NULL;
2405 struct addrinfo **end = &p;
2407 unsigned int naddrs = 0;
2408 if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2409 || hints->ai_family == AF_INET6)
2411 last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2412 if (last_i != 0)
2414 freeaddrinfo (p);
2415 free (in6ai);
2417 return -(last_i & GAIH_EAI);
2419 while (*end)
2421 end = &((*end)->ai_next);
2422 ++nresults;
2425 else
2427 free (in6ai);
2428 return EAI_FAMILY;
2431 if (naddrs > 1)
2433 /* Read the config file. */
2434 __libc_once_define (static, once);
2435 __typeof (once) old_once = once;
2436 __libc_once (once, gaiconf_init);
2437 /* Sort results according to RFC 3484. */
2438 struct sort_result results[nresults];
2439 size_t order[nresults];
2440 struct addrinfo *q;
2441 struct addrinfo *last = NULL;
2442 char *canonname = NULL;
2444 /* If we have information about deprecated and temporary addresses
2445 sort the array now. */
2446 if (in6ai != NULL)
2447 qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2449 int fd = -1;
2450 int af = AF_UNSPEC;
2452 for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2454 results[i].dest_addr = q;
2455 results[i].native = -1;
2456 order[i] = i;
2458 /* If we just looked up the address for a different
2459 protocol, reuse the result. */
2460 if (last != NULL && last->ai_addrlen == q->ai_addrlen
2461 && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2463 memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2464 results[i - 1].source_addr_len);
2465 results[i].source_addr_len = results[i - 1].source_addr_len;
2466 results[i].got_source_addr = results[i - 1].got_source_addr;
2467 results[i].source_addr_flags = results[i - 1].source_addr_flags;
2468 results[i].prefixlen = results[i - 1].prefixlen;
2469 results[i].index = results[i - 1].index;
2471 else
2473 results[i].got_source_addr = false;
2474 results[i].source_addr_flags = 0;
2475 results[i].prefixlen = 0;
2476 results[i].index = 0xffffffffu;
2478 /* We overwrite the type with SOCK_DGRAM since we do not
2479 want connect() to connect to the other side. If we
2480 cannot determine the source address remember this
2481 fact. */
2482 if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2484 if (fd != -1)
2485 close_retry:
2486 close_not_cancel_no_status (fd);
2487 af = q->ai_family;
2488 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2490 else
2492 /* Reset the connection. */
2493 struct sockaddr sa = { .sa_family = AF_UNSPEC };
2494 __connect (fd, &sa, sizeof (sa));
2497 socklen_t sl = sizeof (results[i].source_addr);
2498 if (fd != -1
2499 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2500 && __getsockname (fd,
2501 (struct sockaddr *) &results[i].source_addr,
2502 &sl) == 0)
2504 results[i].source_addr_len = sl;
2505 results[i].got_source_addr = true;
2507 if (in6ai != NULL)
2509 /* See whether the source address is on the list of
2510 deprecated or temporary addresses. */
2511 struct in6addrinfo tmp;
2513 if (q->ai_family == AF_INET && af == AF_INET)
2515 struct sockaddr_in *sinp
2516 = (struct sockaddr_in *) &results[i].source_addr;
2517 tmp.addr[0] = 0;
2518 tmp.addr[1] = 0;
2519 tmp.addr[2] = htonl (0xffff);
2520 tmp.addr[3] = sinp->sin_addr.s_addr;
2522 else
2524 struct sockaddr_in6 *sin6p
2525 = (struct sockaddr_in6 *) &results[i].source_addr;
2526 memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2529 struct in6addrinfo *found
2530 = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2531 in6aicmp);
2532 if (found != NULL)
2534 results[i].source_addr_flags = found->flags;
2535 results[i].prefixlen = found->prefixlen;
2536 results[i].index = found->index;
2540 if (q->ai_family == AF_INET && af == AF_INET6)
2542 /* We have to convert the address. The socket is
2543 IPv6 and the request is for IPv4. */
2544 struct sockaddr_in6 *sin6
2545 = (struct sockaddr_in6 *) &results[i].source_addr;
2546 struct sockaddr_in *sin
2547 = (struct sockaddr_in *) &results[i].source_addr;
2548 assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2549 sin->sin_family = AF_INET;
2550 /* We do not have to initialize sin_port since this
2551 fields has the same position and size in the IPv6
2552 structure. */
2553 assert (offsetof (struct sockaddr_in, sin_port)
2554 == offsetof (struct sockaddr_in6, sin6_port));
2555 assert (sizeof (sin->sin_port)
2556 == sizeof (sin6->sin6_port));
2557 memcpy (&sin->sin_addr,
2558 &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2559 results[i].source_addr_len = sizeof (struct sockaddr_in);
2562 else if (errno == EAFNOSUPPORT && af == AF_INET6
2563 && q->ai_family == AF_INET)
2564 /* This could mean IPv6 sockets are IPv6-only. */
2565 goto close_retry;
2566 else
2567 /* Just make sure that if we have to process the same
2568 address again we do not copy any memory. */
2569 results[i].source_addr_len = 0;
2572 /* Remember the canonical name. */
2573 if (q->ai_canonname != NULL)
2575 assert (canonname == NULL);
2576 canonname = q->ai_canonname;
2577 q->ai_canonname = NULL;
2581 if (fd != -1)
2582 close_not_cancel_no_status (fd);
2584 /* We got all the source addresses we can get, now sort using
2585 the information. */
2586 struct sort_result_combo src
2587 = { .results = results, .nresults = nresults };
2588 if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2590 __libc_lock_define_initialized (static, lock);
2592 __libc_lock_lock (lock);
2593 if (old_once && gaiconf_reload_flag)
2594 gaiconf_reload ();
2595 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2596 __libc_lock_unlock (lock);
2598 else
2599 qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2601 /* Queue the results up as they come out of sorting. */
2602 q = p = results[order[0]].dest_addr;
2603 for (i = 1; i < nresults; ++i)
2604 q = q->ai_next = results[order[i]].dest_addr;
2605 q->ai_next = NULL;
2607 /* Fill in the canonical name into the new first entry. */
2608 p->ai_canonname = canonname;
2611 free (in6ai);
2613 if (p)
2615 *pai = p;
2616 return 0;
2619 return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2621 libc_hidden_def (getaddrinfo)
2623 static_link_warning (getaddrinfo)
2625 void
2626 freeaddrinfo (struct addrinfo *ai)
2628 struct addrinfo *p;
2630 while (ai != NULL)
2632 p = ai;
2633 ai = ai->ai_next;
2634 free (p->ai_canonname);
2635 free (p);
2638 libc_hidden_def (freeaddrinfo)